first commit
This commit is contained in:
commit
1218dd1517
12716 files changed
+989233
No files matched your search
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Page\PageRenderer;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Contains an abstract class for all tslib content class implementations.
|
||||
*/
|
||||
abstract class AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* @var ContentObjectRenderer
|
||||
*/
|
||||
protected $cObj;
|
||||
|
||||
/**
|
||||
* @var PageRenderer
|
||||
*/
|
||||
protected $pageRenderer;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param ContentObjectRenderer $cObj
|
||||
*/
|
||||
public function __construct(ContentObjectRenderer $cObj)
|
||||
{
|
||||
$this->cObj = $cObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content object.
|
||||
*
|
||||
* @param array $conf
|
||||
* @return string
|
||||
*/
|
||||
abstract public function render($conf = []);
|
||||
|
||||
/**
|
||||
* Getter for current ContentObjectRenderer
|
||||
*
|
||||
* @return ContentObjectRenderer
|
||||
*/
|
||||
public function getContentObjectRenderer()
|
||||
{
|
||||
return $this->cObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PageRenderer
|
||||
*/
|
||||
protected function getPageRenderer()
|
||||
{
|
||||
if ($this->pageRenderer === null) {
|
||||
$this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
|
||||
}
|
||||
|
||||
return $this->pageRenderer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains CASE class object.
|
||||
*/
|
||||
class CaseContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, CASE
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$setCurrent = isset($conf['setCurrent.'])
|
||||
? $this->cObj->stdWrap($conf['setCurrent'] ?? '', $conf['setCurrent.'])
|
||||
: ($conf['setCurrent'] ?? null);
|
||||
if ($setCurrent) {
|
||||
$this->cObj->data[$this->cObj->currentValKey] = $setCurrent;
|
||||
}
|
||||
$key = isset($conf['key.']) ? $this->cObj->stdWrap($conf['key'], $conf['key.']) : $conf['key'];
|
||||
$key = isset($conf[$key]) && (string)$conf[$key] !== '' ? $key : 'default';
|
||||
// If no "default" property is available, then an empty string is returned
|
||||
if ($key === 'default' && !isset($conf['default'])) {
|
||||
$theValue = '';
|
||||
} else {
|
||||
$theValue = $this->cObj->cObjGetSingle($conf[$key], $conf[$key . '.'] ?? [], $key);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* Contains CONTENT class object.
|
||||
*/
|
||||
class ContentContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, CONTENT
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$frontendController = $this->getFrontendController();
|
||||
$theValue = '';
|
||||
$originalRec = $frontendController->currentRecord;
|
||||
// If the currentRecord is set, we register, that this record has invoked this function.
|
||||
// It's should not be allowed to do this again then!!
|
||||
if ($originalRec) {
|
||||
++$frontendController->recordRegister[$originalRec];
|
||||
}
|
||||
$conf['table'] = isset($conf['table.']) ? trim($this->cObj->stdWrap($conf['table'], $conf['table.'])) : trim($conf['table']);
|
||||
$conf['select.'] = !empty($conf['select.']) ? $conf['select.'] : [];
|
||||
$renderObjName = $conf['renderObj'] ?: '<' . $conf['table'];
|
||||
$renderObjKey = $conf['renderObj'] ? 'renderObj' : '';
|
||||
$renderObjConf = $conf['renderObj.'];
|
||||
$slide = isset($conf['slide.']) ? (int)$this->cObj->stdWrap($conf['slide'], $conf['slide.']) : (int)$conf['slide'];
|
||||
if (!$slide) {
|
||||
$slide = 0;
|
||||
}
|
||||
$slideCollect = isset($conf['slide.']['collect.']) ? (int)$this->cObj->stdWrap($conf['slide.']['collect'], $conf['slide.']['collect.']) : (int)$conf['slide.']['collect'];
|
||||
if (!$slideCollect) {
|
||||
$slideCollect = 0;
|
||||
}
|
||||
$slideCollectReverse = isset($conf['slide.']['collectReverse.']) ? (int)$this->cObj->stdWrap($conf['slide.']['collectReverse'], $conf['slide.']['collectReverse.']) : (int)$conf['slide.']['collectReverse'];
|
||||
$slideCollectReverse = (bool)$slideCollectReverse;
|
||||
$slideCollectFuzzy = isset($conf['slide.']['collectFuzzy.'])
|
||||
? (bool)$this->cObj->stdWrap($conf['slide.']['collectFuzzy'], $conf['slide.']['collectFuzzy.'])
|
||||
: (bool)$conf['slide.']['collectFuzzy'];
|
||||
if (!$slideCollect) {
|
||||
$slideCollectFuzzy = true;
|
||||
}
|
||||
$again = false;
|
||||
$tmpValue = '';
|
||||
|
||||
do {
|
||||
$records = $this->cObj->getRecords($conf['table'], $conf['select.']);
|
||||
$cobjValue = '';
|
||||
if (!empty($records)) {
|
||||
$this->cObj->currentRecordTotal = count($records);
|
||||
$this->getTimeTracker()->setTSlogMessage('NUMROWS: ' . count($records));
|
||||
|
||||
/** @var ContentObjectRenderer $cObj */
|
||||
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$cObj->setParent($this->cObj->data, $this->cObj->currentRecord);
|
||||
$this->cObj->currentRecordNumber = 0;
|
||||
|
||||
foreach ($records as $row) {
|
||||
// Call hook for possible manipulation of database row for cObj->data
|
||||
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content_content.php']['modifyDBRow'] ?? [] as $className) {
|
||||
$_procObj = GeneralUtility::makeInstance($className);
|
||||
$_procObj->modifyDBRow($row, $conf['table']);
|
||||
}
|
||||
if (!$frontendController->recordRegister[$conf['table'] . ':' . $row['uid']]) {
|
||||
$this->cObj->currentRecordNumber++;
|
||||
$cObj->parentRecordNumber = $this->cObj->currentRecordNumber;
|
||||
$frontendController->currentRecord = $conf['table'] . ':' . $row['uid'];
|
||||
$this->cObj->lastChanged($row['tstamp']);
|
||||
$cObj->start($row, $conf['table']);
|
||||
$tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
|
||||
$cobjValue .= $tmpValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($slideCollectReverse) {
|
||||
$theValue = $cobjValue . $theValue;
|
||||
} else {
|
||||
$theValue .= $cobjValue;
|
||||
}
|
||||
if ($slideCollect > 0) {
|
||||
$slideCollect--;
|
||||
}
|
||||
if ($slide) {
|
||||
if ($slide > 0) {
|
||||
$slide--;
|
||||
}
|
||||
$conf['select.']['pidInList'] = $this->cObj->getSlidePids($conf['select.']['pidInList'], $conf['select.']['pidInList.']);
|
||||
if (isset($conf['select.']['pidInList.'])) {
|
||||
unset($conf['select.']['pidInList.']);
|
||||
}
|
||||
$again = (string)$conf['select.']['pidInList'] !== '';
|
||||
}
|
||||
} while ($again && $slide && ((string)$tmpValue === '' && $slideCollectFuzzy || $slideCollect));
|
||||
|
||||
$wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
|
||||
if ($wrap) {
|
||||
$theValue = $this->cObj->wrap($theValue, $wrap);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
// Restore
|
||||
$frontendController->currentRecord = $originalRec;
|
||||
if ($originalRec) {
|
||||
--$frontendController->recordRegister[$originalRec];
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the frontend controller
|
||||
*
|
||||
* @return TypoScriptFrontendController
|
||||
*/
|
||||
protected function getFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Time Tracker
|
||||
*
|
||||
* @return TimeTracker
|
||||
*/
|
||||
protected function getTimeTracker()
|
||||
{
|
||||
return GeneralUtility::makeInstance(TimeTracker::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* A class that contains methods that can be used to use the dataProcessing functionality
|
||||
*/
|
||||
class ContentDataProcessor
|
||||
{
|
||||
/**
|
||||
* Check for the availability of processors, defined in TypoScript, and use them for data processing
|
||||
*
|
||||
* @param ContentObjectRenderer $cObject
|
||||
* @param array $configuration Configuration array
|
||||
* @param array $variables the variables to be processed
|
||||
* @return array the processed data and variables as key/value store
|
||||
* @throws \UnexpectedValueException If a processor class does not exist
|
||||
*/
|
||||
public function process(ContentObjectRenderer $cObject, array $configuration, array $variables)
|
||||
{
|
||||
if (
|
||||
!empty($configuration['dataProcessing.'])
|
||||
&& is_array($configuration['dataProcessing.'])
|
||||
) {
|
||||
$processors = $configuration['dataProcessing.'];
|
||||
$processorKeys = ArrayUtility::filterAndSortByNumericKeys($processors);
|
||||
|
||||
foreach ($processorKeys as $key) {
|
||||
$className = $processors[$key];
|
||||
if (!class_exists($className)) {
|
||||
throw new \UnexpectedValueException('Processor class name "' . $className . '" does not exist!', 1427455378);
|
||||
}
|
||||
|
||||
if (!in_array(DataProcessorInterface::class, class_implements($className), true)) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Processor with class name "' . $className . '" ' .
|
||||
'must implement interface "' . DataProcessorInterface::class . '"',
|
||||
1427455377
|
||||
);
|
||||
}
|
||||
|
||||
$processorConfiguration = $processors[$key . '.'] ?? [];
|
||||
|
||||
$variables = GeneralUtility::makeInstance($className)->process(
|
||||
$cObject,
|
||||
$configuration,
|
||||
$processorConfiguration,
|
||||
$variables
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $variables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Contains COA class object.
|
||||
*/
|
||||
class ContentObjectArrayContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, COBJ_ARRAY / COA
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (empty($conf)) {
|
||||
$this->getTimeTracker()->setTSlogMessage('No elements in this content object array (COBJ_ARRAY, COA).', 2);
|
||||
return '';
|
||||
}
|
||||
if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = $this->cObj->cObjGet($conf);
|
||||
$wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
|
||||
if ($wrap) {
|
||||
$content = $this->cObj->wrap($content, $wrap);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TimeTracker
|
||||
*/
|
||||
protected function getTimeTracker()
|
||||
{
|
||||
return GeneralUtility::makeInstance(TimeTracker::class);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* Contains COA_INT class object.
|
||||
*/
|
||||
class ContentObjectArrayInternalContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, COA_INT
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!is_array($conf)) {
|
||||
$this->getTimeTracker()->setTSlogMessage('No elements in this content object array (COA_INT).', 2);
|
||||
return '';
|
||||
}
|
||||
$substKey = 'INT_SCRIPT.' . $this->getTypoScriptFrontendController()->uniqueHash();
|
||||
$content = '<!--' . $substKey . '-->';
|
||||
$this->getTypoScriptFrontendController()->config['INTincScript'][$substKey] = [
|
||||
'conf' => $conf,
|
||||
'cObj' => serialize($this->cObj),
|
||||
'type' => 'COA'
|
||||
];
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TimeTracker
|
||||
*/
|
||||
protected function getTimeTracker()
|
||||
{
|
||||
return GeneralUtility::makeInstance(TimeTracker::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypoScriptFrontendController
|
||||
*/
|
||||
protected function getTypoScriptFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* interface for classes which hook into \TYPO3\CMS\Frontend\ContentObject and do additional getData processing
|
||||
*/
|
||||
interface ContentObjectGetDataHookInterface
|
||||
{
|
||||
/**
|
||||
* Extends the getData()-Method of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer to process more/other commands
|
||||
*
|
||||
* @param string $getDataString Full content of getData-request e.g. "TSFE:id // field:title // field:uid
|
||||
* @param array $fields Current field-array
|
||||
* @param string $sectionValue Currently examined section value of the getData request e.g. "field:title
|
||||
* @param string $returnValue Current returnValue that was processed so far by getData
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject Parent content object
|
||||
* @return string Get data result
|
||||
*/
|
||||
public function getDataExtension($getDataString, array $fields, $sectionValue, $returnValue, ContentObjectRenderer &$parentObject);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into \TYPO3\CMS\Frontend\ContentObject and do additional getImgResource processing
|
||||
*/
|
||||
interface ContentObjectGetImageResourceHookInterface
|
||||
{
|
||||
/**
|
||||
* Hook for post-processing image resources
|
||||
*
|
||||
* @param string $file Original image file
|
||||
* @param array $configuration TypoScript getImgResource properties
|
||||
* @param array $imageResource Information of the created/converted image resource
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parent Parent content object
|
||||
* @return array Modified image resource information
|
||||
*/
|
||||
public function getImgResourcePostProcess($file, array $configuration, array $imageResource, ContentObjectRenderer $parent);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
|
||||
/**
|
||||
* Interface for hooks to fetch the public URL of files
|
||||
*/
|
||||
interface ContentObjectGetPublicUrlForFileHookInterface
|
||||
{
|
||||
/**
|
||||
* Post-processes a public URL.
|
||||
*
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parent The current content object (context)
|
||||
* @param array $configuration TypoScript configuration
|
||||
* @param File $file The file object to be used
|
||||
* @param string $pubicUrl Reference to the public URL
|
||||
*/
|
||||
public function postProcess(ContentObjectRenderer $parent, array $configuration, File $file, &$pubicUrl);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into \TYPO3\CMS\Frontend\ContentObject and do additional cObjGetSingle processing
|
||||
*/
|
||||
interface ContentObjectGetSingleHookInterface
|
||||
{
|
||||
/**
|
||||
* Renders content objects, that are not defined in the core
|
||||
*
|
||||
* @param string $contentObjectName The content object name, eg. "TEXT" or "USER" or "IMAGE
|
||||
* @param array $configuration Array with TypoScript properties for the content object
|
||||
* @param string $TypoScriptKey Label used for the internal debug tracking
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject Parent content object
|
||||
* @return string cObject output
|
||||
*/
|
||||
public function getSingleContentObject($contentObjectName, array $configuration, $TypoScriptKey, ContentObjectRenderer &$parentObject);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into getSourceCollection for additional processing
|
||||
*/
|
||||
interface ContentObjectOneSourceCollectionHookInterface
|
||||
{
|
||||
/**
|
||||
* Renders One Source Collection
|
||||
*
|
||||
* @param array $sourceRenderConfiguration Array with TypoScript Properties for the imgResource
|
||||
* @param array $sourceConfiguration
|
||||
* @param string $oneSourceCollection already prerendered SourceCollection
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject Parent content object
|
||||
* @internal param array $configuration Array with the Source Configuration
|
||||
* @return string HTML Content for oneSourceCollection
|
||||
*/
|
||||
public function getOneSourceCollection(array $sourceRenderConfiguration, array $sourceConfiguration, $oneSourceCollection, ContentObjectRenderer &$parentObject);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into \TYPO3\CMS\Frontend\ContentObject and do additional
|
||||
* initialization processing.
|
||||
*/
|
||||
interface ContentObjectPostInitHookInterface
|
||||
{
|
||||
/**
|
||||
* Hook for post processing the initialization of ContentObjectRenderer
|
||||
*
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject Parent content object
|
||||
*/
|
||||
public function postProcessContentObjectInitialization(ContentObjectRenderer &$parentObject);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* interface for classes which hook into \TYPO3\CMS\Frontend\ContentObject and do additional stdWrap processing
|
||||
*/
|
||||
interface ContentObjectStdWrapHookInterface
|
||||
{
|
||||
/**
|
||||
* Hook for modifying $content before core's stdWrap does anything
|
||||
*
|
||||
* @param string $content Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
|
||||
* @param array $configuration TypoScript stdWrap properties
|
||||
* @param ContentObjectRenderer $parentObject Parent content object
|
||||
* @return string Further processed $content
|
||||
*/
|
||||
public function stdWrapPreProcess($content, array $configuration, ContentObjectRenderer &$parentObject);
|
||||
|
||||
/**
|
||||
* Hook for modifying $content after core's stdWrap has processed setContentToCurrent, setCurrent, lang, data, field, current, cObject, numRows, filelist and/or preUserFunc
|
||||
*
|
||||
* @param string $content Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
|
||||
* @param array $configuration TypoScript stdWrap properties
|
||||
* @param ContentObjectRenderer $parentObject Parent content object
|
||||
* @return string Further processed $content
|
||||
*/
|
||||
public function stdWrapOverride($content, array $configuration, ContentObjectRenderer &$parentObject);
|
||||
|
||||
/**
|
||||
* Hook for modifying $content after core's stdWrap has processed override, preIfEmptyListNum, ifEmpty, ifBlank, listNum, trim and/or more (nested) stdWraps
|
||||
*
|
||||
* @param string $content Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
|
||||
* @param array $configuration TypoScript "stdWrap properties".
|
||||
* @param ContentObjectRenderer $parentObject Parent content object
|
||||
* @return string Further processed $content
|
||||
*/
|
||||
public function stdWrapProcess($content, array $configuration, ContentObjectRenderer &$parentObject);
|
||||
|
||||
/**
|
||||
* Hook for modifying $content after core's stdWrap has processed anything but debug
|
||||
*
|
||||
* @param string $content Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
|
||||
* @param array $configuration TypoScript stdWrap properties
|
||||
* @param ContentObjectRenderer $parentObject Parent content object
|
||||
* @return string Further processed $content
|
||||
*/
|
||||
public function stdWrapPostProcess($content, array $configuration, ContentObjectRenderer &$parentObject);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for data processor classes processing data from
|
||||
* ContentObjectRenderer, used e.g. with the FLUIDTEMPLATE content object
|
||||
*/
|
||||
interface DataProcessorInterface
|
||||
{
|
||||
/**
|
||||
* Process content object data
|
||||
*
|
||||
* @param ContentObjectRenderer $cObj The data of the content element or page
|
||||
* @param array $contentObjectConfiguration The configuration of Content Object
|
||||
* @param array $processorConfiguration The configuration of this processor
|
||||
* @param array $processedData Key/value store of processed data (e.g. to be passed to a Fluid View)
|
||||
* @return array the processed data as key/value store
|
||||
*/
|
||||
public function process(
|
||||
ContentObjectRenderer $cObj,
|
||||
array $contentObjectConfiguration,
|
||||
array $processorConfiguration,
|
||||
array $processedData
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains EDITPANEL class object.
|
||||
*/
|
||||
class EditPanelContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, EDITPANEL
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$theValue = '';
|
||||
if ($GLOBALS['TSFE']->isBackendUserLoggedIn()) {
|
||||
$theValue = $this->cObj->editPanel($theValue, $conf);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Exception;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Exception
|
||||
* @internal this is a concrete TYPO3 implementation and solely used for EXT:frontend and not part of TYPO3's Core API.
|
||||
*/
|
||||
class ContentRenderingException extends \TYPO3\CMS\Core\Error\Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Exception;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Frontend\ContentObject\AbstractContentObject;
|
||||
|
||||
/**
|
||||
* Interface ExceptionHandlerInterface
|
||||
*/
|
||||
interface ExceptionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Handles exceptions thrown during rendering of content objects
|
||||
* The handler can decide whether to re-throw the exception or
|
||||
* return a nice error message for production context.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param AbstractContentObject $contentObject
|
||||
* @param array $contentObjectConfiguration
|
||||
* @return string
|
||||
*/
|
||||
public function handle(\Exception $exception, AbstractContentObject $contentObject = null, $contentObjectConfiguration = []);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Exception;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use TYPO3\CMS\Core\Crypto\Random;
|
||||
use TYPO3\CMS\Core\Http\ImmediateResponseException;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\AbstractContentObject;
|
||||
|
||||
/**
|
||||
* Exception handler class for content object rendering
|
||||
* @internal this is a concrete TYPO3 implementation and solely used for EXT:frontend and not part of TYPO3's Core API.
|
||||
*/
|
||||
class ProductionExceptionHandler implements ExceptionHandlerInterface, LoggerAwareInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $configuration = [];
|
||||
|
||||
/**
|
||||
* @param array $configuration
|
||||
*/
|
||||
public function __construct(array $configuration = [])
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles exceptions thrown during rendering of content objects
|
||||
* The handler can decide whether to re-throw the exception or
|
||||
* return a nice error message for production context.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param AbstractContentObject $contentObject
|
||||
* @param array $contentObjectConfiguration
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle(\Exception $exception, AbstractContentObject $contentObject = null, $contentObjectConfiguration = [])
|
||||
{
|
||||
// ImmediateResponseException should work similar to exit / die and must therefore not be handled by this ExceptionHandler.
|
||||
if ($exception instanceof ImmediateResponseException) {
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
if (!empty($this->configuration['ignoreCodes.'])) {
|
||||
if (in_array($exception->getCode(), array_map('intval', $this->configuration['ignoreCodes.']), true)) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
$errorMessage = $this->configuration['errorMessage'] ?? 'Oops, an error occurred! Code: %s';
|
||||
$code = date('YmdHis', $_SERVER['REQUEST_TIME']) . GeneralUtility::makeInstance(Random::class)->generateRandomHexString(8);
|
||||
|
||||
$this->logException($exception, $errorMessage, $code);
|
||||
|
||||
return sprintf($errorMessage, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Exception $exception
|
||||
* @param string $errorMessage
|
||||
* @param string $code
|
||||
*/
|
||||
protected function logException(\Exception $exception, $errorMessage, $code)
|
||||
{
|
||||
$this->logger->alert(sprintf($errorMessage, $code), ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Type\File\ImageInfo;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
use TYPO3\CMS\Frontend\Resource\FilePathSanitizer;
|
||||
|
||||
/**
|
||||
* Contains FILE class object.
|
||||
* @deprecated FILE cObject will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
class FileContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, FILE
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$this->getTypoScriptFrontendController()->logDeprecatedTyposcript('cObject FILE', 'Use IMAGE to show images instead.');
|
||||
$theValue = '';
|
||||
$file = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
|
||||
try {
|
||||
$file = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($file);
|
||||
if (file_exists($file)) {
|
||||
$fileInfo = GeneralUtility::split_fileref($file);
|
||||
$extension = $fileInfo['fileext'];
|
||||
if ($extension === 'jpg' || $extension === 'jpeg' || $extension === 'gif' || $extension === 'png') {
|
||||
$imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $file);
|
||||
$altParameters = trim($this->cObj->getAltParam($conf, false));
|
||||
$theValue = '<img src="'
|
||||
. htmlspecialchars($this->getTypoScriptFrontendController()->absRefPrefix . $file)
|
||||
. '" width="' . (int)$imageInfo->getWidth() . '" height="' . (int)$imageInfo->getHeight()
|
||||
. '"' . $this->cObj->getBorderAttr(' border="0"') . ' ' . $altParameters . ' />';
|
||||
} elseif (filesize($file) < 1024 * 1024) {
|
||||
$theValue = file_get_contents($file);
|
||||
}
|
||||
}
|
||||
} catch (\TYPO3\CMS\Core\Resource\Exception $e) {
|
||||
// do nothing
|
||||
}
|
||||
$linkWrap = isset($conf['linkWrap.']) ? $this->cObj->stdWrap($conf['linkWrap'], $conf['linkWrap.']) : $conf['linkWrap'];
|
||||
if ($linkWrap) {
|
||||
$theValue = $this->cObj->linkWrap($theValue, $linkWrap);
|
||||
}
|
||||
$wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
|
||||
if ($wrap) {
|
||||
$theValue = $this->cObj->wrap($theValue, $wrap);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypoScriptFrontendController
|
||||
*/
|
||||
protected function getTypoScriptFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into \TYPO3\CMS\Frontend\ContentObject and do additional getImgResource processing
|
||||
*/
|
||||
interface FileLinkHookInterface
|
||||
{
|
||||
/**
|
||||
* Finds alternative previewImage for given File.
|
||||
*
|
||||
* @param File $file
|
||||
* @return File
|
||||
* @abstract
|
||||
*/
|
||||
public function getPreviewImage(File $file);
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\MathUtility;
|
||||
use TYPO3\CMS\Frontend\Resource\FileCollector;
|
||||
|
||||
/**
|
||||
* Contains FILES content object
|
||||
*/
|
||||
class FilesContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject FILES
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
|
||||
return '';
|
||||
}
|
||||
// Store the original "currentFile" within a variable so it can be re-applied later-on
|
||||
$originalFileInContentObject = $this->cObj->getCurrentFile();
|
||||
|
||||
$fileCollector = $this->findAndSortFiles($conf);
|
||||
$fileObjects = $fileCollector->getFiles();
|
||||
$availableFileObjectCount = count($fileObjects);
|
||||
|
||||
// optionSplit applied to conf to allow different settings per file
|
||||
$splitConf = GeneralUtility::makeInstance(TypoScriptService::class)
|
||||
->explodeConfigurationForOptionSplit($conf, $availableFileObjectCount);
|
||||
|
||||
$start = 0;
|
||||
if (!empty($conf['begin'])) {
|
||||
$start = (int)$conf['begin'];
|
||||
}
|
||||
if (!empty($conf['begin.'])) {
|
||||
$start = (int)$this->cObj->stdWrap($start, $conf['begin.']);
|
||||
}
|
||||
$start = MathUtility::forceIntegerInRange($start, 0, $availableFileObjectCount);
|
||||
|
||||
$limit = $availableFileObjectCount;
|
||||
if (!empty($conf['maxItems'])) {
|
||||
$limit = (int)$conf['maxItems'];
|
||||
}
|
||||
if (!empty($conf['maxItems.'])) {
|
||||
$limit = (int)$this->cObj->stdWrap($limit, $conf['maxItems.']);
|
||||
}
|
||||
|
||||
$end = MathUtility::forceIntegerInRange($start + $limit, $start, $availableFileObjectCount);
|
||||
|
||||
if (isset($GLOBALS['TSFE'])) {
|
||||
$GLOBALS['TSFE']->register['FILES_COUNT'] = min($limit, $availableFileObjectCount);
|
||||
}
|
||||
$fileObjectCounter = 0;
|
||||
$keys = array_keys($fileObjects);
|
||||
|
||||
$content = '';
|
||||
for ($i = $start; $i < $end; $i++) {
|
||||
$key = $keys[$i];
|
||||
$fileObject = $fileObjects[$key];
|
||||
|
||||
if (isset($GLOBALS['TSFE'])) {
|
||||
$GLOBALS['TSFE']->register['FILE_NUM_CURRENT'] = $fileObjectCounter;
|
||||
}
|
||||
$this->cObj->setCurrentFile($fileObject);
|
||||
$content .= $this->cObj->cObjGetSingle($splitConf[$key]['renderObj'], $splitConf[$key]['renderObj.'], 'renderObj');
|
||||
$fileObjectCounter++;
|
||||
}
|
||||
|
||||
// Reset current file within cObj to the original file after rendering output of FILES
|
||||
// so e.g. stdWrap is not working on the last current file applied, thus avoiding side-effects
|
||||
$this->cObj->setCurrentFile($originalFileInContentObject);
|
||||
|
||||
return $this->cObj->stdWrap($content, $conf['stdWrap.'] ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to check for references, collections, folders and
|
||||
* accumulates into one etc.
|
||||
*
|
||||
* @param array $conf
|
||||
* @return FileCollector
|
||||
*/
|
||||
protected function findAndSortFiles(array $conf)
|
||||
{
|
||||
$fileCollector = $this->getFileCollector();
|
||||
|
||||
// Getting the files
|
||||
if ((isset($conf['references']) && $conf['references']) || (isset($conf['references.']) && $conf['references.'])) {
|
||||
/*
|
||||
The TypoScript could look like this:
|
||||
# all items related to the page.media field:
|
||||
references {
|
||||
table = pages
|
||||
uid.data = page:uid
|
||||
fieldName = media
|
||||
}
|
||||
# or: sys_file_references with uid 27:
|
||||
references = 27
|
||||
*/
|
||||
$referencesUidList = $this->cObj->stdWrapValue('references', $conf);
|
||||
$referencesUids = GeneralUtility::intExplode(',', $referencesUidList, true);
|
||||
$fileCollector->addFileReferences($referencesUids);
|
||||
|
||||
if (!empty($conf['references.'])) {
|
||||
$this->addFileReferences($conf, (array)$this->cObj->data, $fileCollector);
|
||||
}
|
||||
}
|
||||
|
||||
if ((isset($conf['files']) && $conf['files']) || (isset($conf['files.']) && $conf['files.'])) {
|
||||
/*
|
||||
The TypoScript could look like this:
|
||||
# with sys_file UIDs:
|
||||
files = 12,14,15# using stdWrap:
|
||||
files.field = some_field
|
||||
*/
|
||||
$fileUids = GeneralUtility::intExplode(',', $this->cObj->stdWrapValue('files', $conf), true);
|
||||
$fileCollector->addFiles($fileUids);
|
||||
}
|
||||
|
||||
if ((isset($conf['collections']) && $conf['collections']) || (isset($conf['collections.']) && $conf['collections.'])) {
|
||||
$collectionUids = GeneralUtility::intExplode(',', $this->cObj->stdWrapValue('collections', $conf), true);
|
||||
$fileCollector->addFilesFromFileCollections($collectionUids);
|
||||
}
|
||||
|
||||
if ((isset($conf['folders']) && $conf['folders']) || (isset($conf['folders.']) && $conf['folders.'])) {
|
||||
$folderIdentifiers = GeneralUtility::trimExplode(',', $this->cObj->stdWrapValue('folders', $conf));
|
||||
$fileCollector->addFilesFromFolders($folderIdentifiers, !empty($conf['folders.']['recursive']));
|
||||
}
|
||||
|
||||
// Enable sorting for multiple fileObjects
|
||||
$sortingProperty = '';
|
||||
if ((isset($conf['sorting']) && $conf['sorting']) || (isset($conf['sorting.']) && $conf['sorting.'])) {
|
||||
$sortingProperty = $this->cObj->stdWrapValue('sorting', $conf);
|
||||
}
|
||||
if ($sortingProperty !== '') {
|
||||
$sortingDirection = $conf['sorting.']['direction'] ?? '';
|
||||
if (isset($conf['sorting.']['direction.'])) {
|
||||
$sortingDirection = $this->cObj->stdWrap($sortingDirection, $conf['sorting.']['direction.']);
|
||||
}
|
||||
$fileCollector->sort($sortingProperty, $sortingDirection);
|
||||
}
|
||||
|
||||
return $fileCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles and resolves file references.
|
||||
*
|
||||
* @param array $configuration TypoScript configuration
|
||||
* @param array $element The parent element referencing to files
|
||||
* @param FileCollector $fileCollector
|
||||
*/
|
||||
protected function addFileReferences(array $configuration, array $element, FileCollector $fileCollector)
|
||||
{
|
||||
|
||||
// It's important that this always stays "fieldName" and not be renamed to "field" as it would otherwise collide with the stdWrap key of that name
|
||||
$referencesFieldName = $this->cObj->stdWrapValue('fieldName', $configuration['references.']);
|
||||
|
||||
// If no reference fieldName is set, there's nothing to do
|
||||
if (empty($referencesFieldName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentId = !empty($element['uid']) ? $element['uid'] : 0;
|
||||
$tableName = $this->cObj->getCurrentTable();
|
||||
|
||||
// Fetch the references of the default element
|
||||
$referencesForeignTable = $this->cObj->stdWrapValue('table', $configuration['references.'], $tableName);
|
||||
$referencesForeignUid = $this->cObj->stdWrapValue('uid', $configuration['references.'], $currentId);
|
||||
|
||||
$pageRepository = $this->getPageRepository();
|
||||
// Fetch element if definition has been modified via TypoScript
|
||||
if ($referencesForeignTable !== $tableName || $referencesForeignUid !== $currentId) {
|
||||
$element = $pageRepository->getRawRecord($referencesForeignTable, $referencesForeignUid);
|
||||
|
||||
$pageRepository->versionOL($referencesForeignTable, $element, true);
|
||||
if (is_array($element)) {
|
||||
$element = $pageRepository->getLanguageOverlay($referencesForeignTable, $element);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($element)) {
|
||||
$fileCollector->addFilesFromRelation($referencesForeignTable, $referencesFieldName, $element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Frontend\Page\PageRepository
|
||||
*/
|
||||
protected function getPageRepository()
|
||||
{
|
||||
return $GLOBALS['TSFE']->sys_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FileCollector
|
||||
*/
|
||||
protected function getFileCollector()
|
||||
{
|
||||
return GeneralUtility::makeInstance(FileCollector::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\StringUtility;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
|
||||
use TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||
use TYPO3\CMS\Frontend\ContentObject\Exception\ContentRenderingException;
|
||||
|
||||
/**
|
||||
* Contains FLUIDTEMPLATE class object
|
||||
*/
|
||||
class FluidTemplateContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* @var StandaloneView
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* @var ContentDataProcessor
|
||||
*/
|
||||
protected $contentDataProcessor;
|
||||
|
||||
/**
|
||||
* @param ContentObjectRenderer $cObj
|
||||
*/
|
||||
public function __construct(ContentObjectRenderer $cObj)
|
||||
{
|
||||
parent::__construct($cObj);
|
||||
$this->contentDataProcessor = GeneralUtility::makeInstance(ContentDataProcessor::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContentDataProcessor $contentDataProcessor
|
||||
*/
|
||||
public function setContentDataProcessor($contentDataProcessor)
|
||||
{
|
||||
$this->contentDataProcessor = $contentDataProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering the cObject, FLUIDTEMPLATE
|
||||
*
|
||||
* Configuration properties:
|
||||
* - file string+stdWrap The FLUID template file
|
||||
* - layoutRootPaths array of filepath+stdWrap Root paths to layouts (fallback)
|
||||
* - partialRootPaths array of filepath+stdWrap Root paths to partials (fallback)
|
||||
* - variable array of cObjects, the keys are the variable names in fluid
|
||||
* - dataProcessing array of data processors which are classes to manipulate $data
|
||||
* - extbase.pluginName
|
||||
* - extbase.controllerExtensionName
|
||||
* - extbase.controllerName
|
||||
* - extbase.controllerActionName
|
||||
*
|
||||
* Example:
|
||||
* 10 = FLUIDTEMPLATE
|
||||
* 10.templateName = MyTemplate
|
||||
* 10.templateRootPaths.10 = EXT:site_configuration/Resources/Private/Templates/
|
||||
* 10.partialRootPaths.10 = EXT:site_configuration/Resources/Private/Patials/
|
||||
* 10.layoutRootPaths.10 = EXT:site_configuration/Resources/Private/Layouts/
|
||||
* 10.variables {
|
||||
* mylabel = TEXT
|
||||
* mylabel.value = Label from TypoScript coming
|
||||
* }
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string The HTML output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$parentView = $this->view;
|
||||
$this->initializeStandaloneViewInstance();
|
||||
|
||||
if (!is_array($conf)) {
|
||||
$conf = [];
|
||||
}
|
||||
|
||||
$this->setFormat($conf);
|
||||
$this->setTemplate($conf);
|
||||
$this->setLayoutRootPath($conf);
|
||||
$this->setPartialRootPath($conf);
|
||||
$this->setExtbaseVariables($conf);
|
||||
$this->assignSettings($conf);
|
||||
$variables = $this->getContentObjectVariables($conf);
|
||||
$variables = $this->contentDataProcessor->process($this->cObj, $conf, $variables);
|
||||
|
||||
$this->view->assignMultiple($variables);
|
||||
|
||||
$this->renderFluidTemplateAssetsIntoPageRenderer();
|
||||
$content = $this->renderFluidView();
|
||||
$content = $this->applyStandardWrapToRenderedContent($content, $conf);
|
||||
|
||||
$this->view = $parentView;
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to render HeaderAssets and FooterAssets sections from the
|
||||
* Fluid template, then adds each (if not empty) to either header or
|
||||
* footer, as appropriate, using PageRenderer.
|
||||
*/
|
||||
protected function renderFluidTemplateAssetsIntoPageRenderer()
|
||||
{
|
||||
$pageRenderer = $this->getPageRenderer();
|
||||
$headerAssets = $this->view->renderSection('HeaderAssets', ['contentObject' => $this], true);
|
||||
$footerAssets = $this->view->renderSection('FooterAssets', ['contentObject' => $this], true);
|
||||
if (!empty(trim($headerAssets))) {
|
||||
$pageRenderer->addHeaderData($headerAssets);
|
||||
}
|
||||
if (!empty(trim($footerAssets))) {
|
||||
$pageRenderer->addFooterData($footerAssets);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating standalone view instance must not be done in construct() as
|
||||
* it can lead to a nasty cache issue since content object instances
|
||||
* are not always re-created by the content object rendered for every
|
||||
* usage, but can be re-used. Thus, we need a fresh instance of
|
||||
* StandaloneView every time render() is called.
|
||||
*/
|
||||
protected function initializeStandaloneViewInstance()
|
||||
{
|
||||
$this->view = GeneralUtility::makeInstance(StandaloneView::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set template
|
||||
*
|
||||
* @param array $conf With possibly set file resource
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function setTemplate(array $conf)
|
||||
{
|
||||
// Fetch the Fluid template by templateName
|
||||
if (
|
||||
(!empty($conf['templateName']) || !empty($conf['templateName.']))
|
||||
&& !empty($conf['templateRootPaths.']) && is_array($conf['templateRootPaths.'])
|
||||
) {
|
||||
$templateRootPaths = $this->applyStandardWrapToFluidPaths($conf['templateRootPaths.']);
|
||||
$this->view->setTemplateRootPaths($templateRootPaths);
|
||||
$templateName = isset($conf['templateName.'])
|
||||
? $this->cObj->stdWrap($conf['templateName'] ?? '', $conf['templateName.'])
|
||||
: $conf['templateName'];
|
||||
$this->view->setTemplate($templateName);
|
||||
} elseif (!empty($conf['template']) && !empty($conf['template.'])) {
|
||||
// Fetch the Fluid template by template cObject
|
||||
$templateSource = $this->cObj->cObjGetSingle($conf['template'], $conf['template.'], 'template');
|
||||
if ($templateSource === '') {
|
||||
throw new ContentRenderingException(
|
||||
'Could not find template source for ' . $conf['template'],
|
||||
1437420865
|
||||
);
|
||||
}
|
||||
$this->view->setTemplateSource($templateSource);
|
||||
} else {
|
||||
// Fetch the Fluid template by file stdWrap
|
||||
$file = isset($conf['file.'])
|
||||
? $this->cObj->stdWrap($conf['file'] ?? '', $conf['file.'])
|
||||
: ($conf['file'] ?? '');
|
||||
// Get the absolute file name
|
||||
$templatePathAndFilename = GeneralUtility::getFileAbsFileName($file);
|
||||
$this->view->setTemplatePathAndFilename($templatePathAndFilename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layout root path if given in configuration
|
||||
*
|
||||
* @param array $conf Configuration array
|
||||
*/
|
||||
protected function setLayoutRootPath(array $conf)
|
||||
{
|
||||
// Override the default layout path via typoscript
|
||||
$layoutPaths = [];
|
||||
if (isset($conf['layoutRootPath']) || isset($conf['layoutRootPath.'])) {
|
||||
$layoutRootPath = isset($conf['layoutRootPath.'])
|
||||
? $this->cObj->stdWrap($conf['layoutRootPath'], $conf['layoutRootPath.'])
|
||||
: $conf['layoutRootPath'];
|
||||
$layoutPaths[] = GeneralUtility::getFileAbsFileName($layoutRootPath);
|
||||
}
|
||||
if (isset($conf['layoutRootPaths.'])) {
|
||||
$layoutPaths = array_replace($layoutPaths, $this->applyStandardWrapToFluidPaths($conf['layoutRootPaths.']));
|
||||
}
|
||||
if (!empty($layoutPaths)) {
|
||||
$this->view->setLayoutRootPaths($layoutPaths);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set partial root path if given in configuration
|
||||
*
|
||||
* @param array $conf Configuration array
|
||||
*/
|
||||
protected function setPartialRootPath(array $conf)
|
||||
{
|
||||
$partialPaths = [];
|
||||
if (isset($conf['partialRootPath']) || isset($conf['partialRootPath.'])) {
|
||||
$partialRootPath = isset($conf['partialRootPath.'])
|
||||
? $this->cObj->stdWrap($conf['partialRootPath'], $conf['partialRootPath.'])
|
||||
: $conf['partialRootPath'];
|
||||
$partialPaths[] = GeneralUtility::getFileAbsFileName($partialRootPath);
|
||||
}
|
||||
if (isset($conf['partialRootPaths.'])) {
|
||||
$partialPaths = array_replace($partialPaths, $this->applyStandardWrapToFluidPaths($conf['partialRootPaths.']));
|
||||
}
|
||||
if (!empty($partialPaths)) {
|
||||
$this->view->setPartialRootPaths($partialPaths);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set different format if given in configuration
|
||||
*
|
||||
* @param array $conf Configuration array
|
||||
*/
|
||||
protected function setFormat(array $conf)
|
||||
{
|
||||
$format = isset($conf['format.'])
|
||||
? $this->cObj->stdWrap($conf['format'] ?? '', $conf['format.'])
|
||||
: ($conf['format'] ?? '');
|
||||
if ($format) {
|
||||
$this->view->setFormat($format);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some extbase variables if given
|
||||
*
|
||||
* @param array $conf Configuration array
|
||||
*/
|
||||
protected function setExtbaseVariables(array $conf)
|
||||
{
|
||||
/** @var \TYPO3\CMS\Extbase\Mvc\Request $request */
|
||||
$requestPluginName = isset($conf['extbase.']['pluginName.'])
|
||||
? $this->cObj->stdWrap($conf['extbase.']['pluginName'] ?? '', $conf['extbase.']['pluginName.'])
|
||||
: ($conf['extbase.']['pluginName'] ?? '');
|
||||
if ($requestPluginName) {
|
||||
$this->view->getRequest()->setPluginName($requestPluginName);
|
||||
}
|
||||
$requestControllerExtensionName = isset($conf['extbase.']['controllerExtensionName.'])
|
||||
? $this->cObj->stdWrap($conf['extbase.']['controllerExtensionName'] ?? '', $conf['extbase.']['controllerExtensionName.'])
|
||||
: ($conf['extbase.']['controllerExtensionName'] ?? '');
|
||||
if ($requestControllerExtensionName) {
|
||||
$this->view->getRequest()->setControllerExtensionName($requestControllerExtensionName);
|
||||
}
|
||||
$requestControllerName = isset($conf['extbase.']['controllerName.'])
|
||||
? $this->cObj->stdWrap($conf['extbase.']['controllerName'] ?? '', $conf['extbase.']['controllerName.'])
|
||||
: ($conf['extbase.']['controllerName'] ?? '');
|
||||
if ($requestControllerName) {
|
||||
$this->view->getRequest()->setControllerName($requestControllerName);
|
||||
}
|
||||
$requestControllerActionName = isset($conf['extbase.']['controllerActionName.'])
|
||||
? $this->cObj->stdWrap($conf['extbase.']['controllerActionName'] ?? '', $conf['extbase.']['controllerActionName.'])
|
||||
: ($conf['extbase.']['controllerActionName'] ?? '');
|
||||
if ($requestControllerActionName) {
|
||||
$this->view->getRequest()->setControllerActionName($requestControllerActionName);
|
||||
}
|
||||
|
||||
if (
|
||||
$requestPluginName
|
||||
&& $requestControllerExtensionName
|
||||
&& $requestControllerName
|
||||
&& $requestControllerActionName
|
||||
) {
|
||||
$configurationManager = GeneralUtility::makeInstance(ObjectManager::class)->get(ConfigurationManager::class);
|
||||
$configurationManager->setConfiguration([
|
||||
'extensionName' => $requestControllerExtensionName,
|
||||
'pluginName' => $requestPluginName,
|
||||
]);
|
||||
|
||||
if (!isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$requestControllerExtensionName]['plugins'][$requestPluginName]['controllers'])) {
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$requestControllerExtensionName]['plugins'][$requestPluginName]['controllers'] = [
|
||||
$requestControllerName => [
|
||||
'actions' => [
|
||||
$requestControllerActionName,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$requestBuilder = GeneralUtility::makeInstance(ObjectManager::class)->get(RequestBuilder::class);
|
||||
$this->view->getRenderingContext()->getControllerContext()->setRequest($requestBuilder->build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile rendered content objects in variables array ready to assign to the view
|
||||
*
|
||||
* @param array $conf Configuration array
|
||||
* @return array the variables to be assigned
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function getContentObjectVariables(array $conf)
|
||||
{
|
||||
$variables = [];
|
||||
$reservedVariables = ['data', 'current'];
|
||||
// Accumulate the variables to be process and loop them through cObjGetSingle
|
||||
$variablesToProcess = (array)($conf['variables.'] ?? []);
|
||||
foreach ($variablesToProcess as $variableName => $cObjType) {
|
||||
if (is_array($cObjType)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($variableName, $reservedVariables)) {
|
||||
$variables[$variableName] = $this->cObj->cObjGetSingle($cObjType, $variablesToProcess[$variableName . '.'], 'variables.' . $variableName);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(
|
||||
'Cannot use reserved name "' . $variableName . '" as variable name in FLUIDTEMPLATE.',
|
||||
1288095720
|
||||
);
|
||||
}
|
||||
}
|
||||
$variables['data'] = $this->cObj->data;
|
||||
$variables['current'] = $this->cObj->data[$this->cObj->currentValKey ?? null] ?? null;
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set any TypoScript settings to the view. This is similar to a
|
||||
* default MVC action controller in extbase.
|
||||
*
|
||||
* @param array $conf Configuration
|
||||
*/
|
||||
protected function assignSettings(array $conf)
|
||||
{
|
||||
if (isset($conf['settings.'])) {
|
||||
/** @var TypoScriptService $typoScriptService */
|
||||
$typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
|
||||
$settings = $typoScriptService->convertTypoScriptArrayToPlainArray($conf['settings.']);
|
||||
$this->view->assign('settings', $settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render fluid standalone view
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function renderFluidView()
|
||||
{
|
||||
return $this->view->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply standard wrap to content
|
||||
*
|
||||
* @param string $content Rendered HTML content
|
||||
* @param array $conf Configuration array
|
||||
* @return string Standard wrapped content
|
||||
*/
|
||||
protected function applyStandardWrapToRenderedContent($content, array $conf)
|
||||
{
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies stdWrap on Fluid path definitions
|
||||
*
|
||||
* @param array $paths
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function applyStandardWrapToFluidPaths(array $paths)
|
||||
{
|
||||
$finalPaths = [];
|
||||
foreach ($paths as $key => $path) {
|
||||
if (StringUtility::endsWith($key, '.')) {
|
||||
if (isset($paths[substr($key, 0, -1)])) {
|
||||
continue;
|
||||
}
|
||||
$path = $this->cObj->stdWrap('', $path);
|
||||
} elseif (isset($paths[$key . '.'])) {
|
||||
$path = $this->cObj->stdWrap($path, $paths[$key . '.']);
|
||||
}
|
||||
$finalPaths[$key] = GeneralUtility::getFileAbsFileName($path);
|
||||
}
|
||||
return $finalPaths;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Contains HMENU class object.
|
||||
*/
|
||||
class HierarchicalMenuContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, HMENU
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$theValue = '';
|
||||
$menuType = $conf[1];
|
||||
try {
|
||||
/** @var Menu\MenuContentObjectFactory $menuObjectFactory */
|
||||
$menuObjectFactory = GeneralUtility::makeInstance(Menu\MenuContentObjectFactory::class);
|
||||
$menu = $menuObjectFactory->getMenuObjectByType($menuType);
|
||||
$GLOBALS['TSFE']->register['count_HMENU']++;
|
||||
$GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'] = 0;
|
||||
$GLOBALS['TSFE']->register['count_MENUOBJ'] = 0;
|
||||
$GLOBALS['TSFE']->applicationData['GMENU_LAYERS']['WMid'] = [];
|
||||
$GLOBALS['TSFE']->applicationData['GMENU_LAYERS']['WMparentId'] = [];
|
||||
$menu->parent_cObj = $this->cObj;
|
||||
$menu->start($GLOBALS['TSFE']->tmpl, $GLOBALS['TSFE']->sys_page, '', $conf, 1);
|
||||
$menu->makeMenu();
|
||||
$theValue .= $menu->writeMenu();
|
||||
} catch (Menu\Exception\NoSuchMenuTypeException $e) {
|
||||
}
|
||||
$wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
|
||||
if ($wrap) {
|
||||
$theValue = $this->cObj->wrap($theValue, $wrap);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains IMAGE class object.
|
||||
*/
|
||||
class ImageContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, IMAGE
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$theValue = $this->cObj->cImage($conf['file'], $conf);
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains IMG_RESOURCE class object.
|
||||
*/
|
||||
class ImageResourceContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, IMG_RESOURCE
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
*
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$GLOBALS['TSFE']->lastImgResourceInfo = $this->cObj->getImgResource($conf['file'], $conf['file.']);
|
||||
if ($GLOBALS['TSFE']->lastImgResourceInfo) {
|
||||
$imageResource = $GLOBALS['TSFE']->lastImgResourceInfo[3];
|
||||
$theValue = isset($conf['stdWrap.']) ? $this->cObj->stdWrap($imageResource, $conf['stdWrap.']) : $imageResource;
|
||||
} else {
|
||||
$theValue = '';
|
||||
}
|
||||
|
||||
return $theValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains LOAD_REGISTER class object.
|
||||
*/
|
||||
class LoadRegisterContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, LOAD_REGISTER
|
||||
* NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Empty string (the cObject only sets internal data!)
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$GLOBALS['TSFE']->registerStack[] = $GLOBALS['TSFE']->register;
|
||||
if (is_array($conf)) {
|
||||
$isExecuted = [];
|
||||
foreach ($conf as $theKey => $theValue) {
|
||||
$register = rtrim($theKey, '.');
|
||||
if (!isset($isExecuted[$register]) || !$isExecuted[$register]) {
|
||||
$registerProperties = $register . '.';
|
||||
if (isset($conf[$register]) && isset($conf[$registerProperties])) {
|
||||
$theValue = $this->cObj->stdWrap($conf[$register], $conf[$registerProperties]);
|
||||
} elseif (isset($conf[$registerProperties])) {
|
||||
$theValue = $this->cObj->stdWrap('', $conf[$registerProperties]);
|
||||
}
|
||||
$GLOBALS['TSFE']->register[$register] = $theValue;
|
||||
$isExecuted[$register] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* interface for classes which hook into AbstractMenuContentObject
|
||||
*/
|
||||
interface AbstractMenuFilterPagesHookInterface
|
||||
{
|
||||
/**
|
||||
* Checks if a page is OK to include in the final menu item array.
|
||||
*
|
||||
* @param array $data Array of menu items
|
||||
* @param array $banUidArray Array of page uids which are to be excluded
|
||||
* @param bool $spacer If set, then the page is a spacer.
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject $obj The menu object
|
||||
* @return bool Returns TRUE if the page can be safely included.
|
||||
*/
|
||||
public function processFilter(array &$data, array $banUidArray, $spacer, AbstractMenuContentObject $obj);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Collection\AbstractRecordCollection;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Category\Collection\CategoryCollection;
|
||||
|
||||
/**
|
||||
* Utility class for menus based on category collections of pages.
|
||||
*
|
||||
* Returns all the relevant pages for rendering with a menu content object.
|
||||
* @internal this is only used for internal purposes and solely used for EXT:frontend and not part of TYPO3's Core API.
|
||||
*/
|
||||
class CategoryMenuUtility
|
||||
{
|
||||
/**
|
||||
* @var string Name of the field used for sorting the pages
|
||||
*/
|
||||
protected static $sortingField;
|
||||
|
||||
/**
|
||||
* Collects all pages for the selected categories, sorted according to configuration.
|
||||
*
|
||||
* @param string $selectedCategories Comma-separated list of system categories primary keys
|
||||
* @param array $configuration TypoScript configuration for the "special." keyword
|
||||
* @param \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject $parentObject Back-reference to the calling object
|
||||
* @return array List of selected pages
|
||||
*/
|
||||
public function collectPages($selectedCategories, $configuration, $parentObject)
|
||||
{
|
||||
$selectedPages = [];
|
||||
$categoriesPerPage = [];
|
||||
// Determine the name of the relation field
|
||||
$relationField = '';
|
||||
if (isset($configuration['relation.'])) {
|
||||
$relationField = $parentObject->parent_cObj->stdWrap(
|
||||
$configuration['relation'],
|
||||
$configuration['relation.']
|
||||
);
|
||||
} elseif (isset($configuration['relation'])) {
|
||||
$relationField = $configuration['relation'];
|
||||
}
|
||||
// Get the pages for each selected category
|
||||
$selectedCategories = GeneralUtility::intExplode(',', $selectedCategories, true);
|
||||
foreach ($selectedCategories as $aCategory) {
|
||||
$collection = CategoryCollection::load(
|
||||
$aCategory,
|
||||
true,
|
||||
'pages',
|
||||
$relationField
|
||||
);
|
||||
$categoryUid = 0;
|
||||
if ($collection instanceof AbstractRecordCollection) {
|
||||
$categoryUid = $collection->getUid();
|
||||
}
|
||||
// Loop on the results, overlay each page record found
|
||||
foreach ($collection as $pageItem) {
|
||||
$parentObject->getSysPage()->versionOL('pages', $pageItem, true);
|
||||
if (is_array($pageItem)) {
|
||||
$selectedPages[$pageItem['uid']] = $parentObject->getSysPage()->getPageOverlay($pageItem);
|
||||
// Keep a list of the categories each page belongs to
|
||||
if (!isset($categoriesPerPage[$pageItem['uid']])) {
|
||||
$categoriesPerPage[$pageItem['uid']] = [];
|
||||
}
|
||||
$categoriesPerPage[$pageItem['uid']][] = $categoryUid;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Loop on the selected pages to add the categories they belong to, as comma-separated list of category uid's)
|
||||
// (this makes them available for rendering, if needed)
|
||||
foreach ($selectedPages as $uid => $pageRecord) {
|
||||
$selectedPages[$uid]['_categories'] = implode(',', $categoriesPerPage[$uid]);
|
||||
}
|
||||
|
||||
// Sort the pages according to the sorting property
|
||||
self::$sortingField = isset($configuration['sorting.']) ? $parentObject->getParentContentObject()->stdWrap($configuration['sorting'], $configuration['sorting.']) : $configuration['sorting'];
|
||||
$order = isset($configuration['order.']) ? $parentObject->getParentContentObject()->stdWrap($configuration['order'], $configuration['order.']) : $configuration['order'];
|
||||
$selectedPages = $this->sortPages($selectedPages, $order);
|
||||
|
||||
return $selectedPages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the selected pages
|
||||
*
|
||||
* If the sorting field is not defined or does not corresponding to an existing field
|
||||
* of the "pages" tables, the list of pages will remain unchanged.
|
||||
*
|
||||
* @param array $pages List of selected pages
|
||||
* @param string $order Order for sorting (should "asc" or "desc")
|
||||
* @return array Sorted list of pages
|
||||
*/
|
||||
protected function sortPages($pages, $order)
|
||||
{
|
||||
// Perform the sorting only if a criterion was actually defined
|
||||
if (!empty(self::$sortingField)) {
|
||||
// Check that the sorting field exists (checking the first record is enough)
|
||||
$firstPage = current($pages);
|
||||
if (isset($firstPage[self::$sortingField])) {
|
||||
// Make sure the order property is either "asc" or "desc" (default is "asc")
|
||||
if (!empty($order)) {
|
||||
$order = strtolower($order);
|
||||
if ($order !== 'desc') {
|
||||
$order = 'asc';
|
||||
}
|
||||
}
|
||||
uasort(
|
||||
$pages,
|
||||
[
|
||||
self::class,
|
||||
'sortPagesUtility'
|
||||
]
|
||||
);
|
||||
// If the sort order is descending, reverse the sorted array
|
||||
if ($order === 'desc') {
|
||||
$pages = array_reverse($pages, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static utility for sorting pages according to the selected criterion
|
||||
*
|
||||
* @param array $pageA Record for first page to be compared
|
||||
* @param array $pageB Record for second page to be compared
|
||||
* @return array -1 if first argument is smaller than second argument, 1 if first is greater than second and 0 if both are equal
|
||||
*/
|
||||
public static function sortPagesUtility($pageA, $pageB)
|
||||
{
|
||||
return strnatcasecmp($pageA[self::$sortingField], $pageB[self::$sortingField]);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu\Exception;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* No such menu type exception
|
||||
*/
|
||||
class NoSuchMenuTypeException extends \TYPO3\CMS\Frontend\Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,569 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Type\File\ImageInfo;
|
||||
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
use TYPO3\CMS\Frontend\Imaging\GifBuilder;
|
||||
|
||||
/**
|
||||
* Extension class creating graphic based menus (PNG or GIF files)
|
||||
*
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0
|
||||
*/
|
||||
class GraphicalMenuContentObject extends AbstractMenuContentObject
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
trigger_error('GMENU and GraphicalMenuContentObject will be removed in TYPO3 v10.0, you should build accessible websites with TMENU/Text, and optional images on top, which can be achieved with TypoScript.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
|
||||
* Calls makeGifs() for all "normal" items and if configured for, also the "rollover" items.
|
||||
*
|
||||
* @see AbstractMenuContentObject::procesItemStates(), makeGifs()
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
$splitCount = count($this->menuArr);
|
||||
if ($splitCount) {
|
||||
list($NOconf, $ROconf) = $this->procesItemStates($splitCount);
|
||||
//store initial count value
|
||||
$tsfe = $this->getTypoScriptFrontendController();
|
||||
$temp_HMENU_MENUOBJ = $tsfe->register['count_HMENU_MENUOBJ'];
|
||||
$temp_MENUOBJ = $tsfe->register['count_MENUOBJ'];
|
||||
// Now we generate the giffiles:
|
||||
$this->makeGifs($NOconf, 'NO');
|
||||
// store count from NO obj
|
||||
$tempcnt_HMENU_MENUOBJ = $tsfe->register['count_HMENU_MENUOBJ'];
|
||||
$tempcnt_MENUOBJ = $tsfe->register['count_MENUOBJ'];
|
||||
if ($this->mconf['debugItemConf']) {
|
||||
echo '<h3>$NOconf:</h3>';
|
||||
debug($NOconf);
|
||||
}
|
||||
// RollOver
|
||||
if ($ROconf) {
|
||||
// Start recount for rollover with initial values
|
||||
$tsfe->register['count_HMENU_MENUOBJ'] = $temp_HMENU_MENUOBJ;
|
||||
$tsfe->register['count_MENUOBJ'] = $temp_MENUOBJ;
|
||||
$this->makeGifs($ROconf, 'RO');
|
||||
if ($this->mconf['debugItemConf']) {
|
||||
echo '<h3>$ROconf:</h3>';
|
||||
debug($ROconf);
|
||||
}
|
||||
}
|
||||
// Use count from NO obj
|
||||
$tsfe->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
|
||||
$tsfe->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will traverse input array with configuration per-item and create corresponding GIF files for the menu.
|
||||
* The data of the files are stored in $this->result
|
||||
*
|
||||
* @param array $conf Array with configuration for each item.
|
||||
* @param string $resKey Type of images: normal ("NO") or rollover ("RO"). Valid values are "NO" and "RO
|
||||
* @internal
|
||||
* @see generate()
|
||||
*/
|
||||
public function makeGifs($conf, $resKey)
|
||||
{
|
||||
$isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
|
||||
if (!is_array($conf)) {
|
||||
$conf = [];
|
||||
}
|
||||
$totalWH = [];
|
||||
$items = count($conf);
|
||||
$minDim = 0;
|
||||
$maxDim = 0;
|
||||
$Hcounter = 0;
|
||||
$Wcounter = 0;
|
||||
$Hobjs = [];
|
||||
$Wobjs = [];
|
||||
if ($isGD) {
|
||||
// Generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
|
||||
$Hobjs = $this->mconf['applyTotalH'];
|
||||
if ($Hobjs) {
|
||||
$Hobjs = GeneralUtility::intExplode(',', $Hobjs);
|
||||
}
|
||||
$Wobjs = $this->mconf['applyTotalW'];
|
||||
if ($Wobjs) {
|
||||
$Wobjs = GeneralUtility::intExplode(',', $Wobjs);
|
||||
}
|
||||
$minDim = $this->mconf['min'];
|
||||
if ($minDim) {
|
||||
$minDim = $this->calcIntExplode($minDim . ',');
|
||||
}
|
||||
$maxDim = $this->mconf['max'];
|
||||
if ($maxDim) {
|
||||
$maxDim = $this->calcIntExplode($maxDim . ',');
|
||||
}
|
||||
if ($minDim) {
|
||||
$conf[$items] = $conf[$items - 1];
|
||||
$this->menuArr[$items] = [];
|
||||
$items = count($conf);
|
||||
}
|
||||
// TOTAL width
|
||||
if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY']) {
|
||||
$totalWH = $this->findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim);
|
||||
}
|
||||
}
|
||||
$c = 0;
|
||||
$maxFlag = 0;
|
||||
$distributeAccu = ['H' => 0, 'W' => 0];
|
||||
foreach ($conf as $key => $val) {
|
||||
$this->getTypoScriptFrontendController()->register['count_HMENU_MENUOBJ']++;
|
||||
$this->getTypoScriptFrontendController()->register['count_MENUOBJ']++;
|
||||
if ($items === $c + 1 && $minDim) {
|
||||
$Lobjs = $this->mconf['removeObjectsOfDummy'];
|
||||
if ($Lobjs) {
|
||||
$Lobjs = GeneralUtility::intExplode(',', $Lobjs);
|
||||
foreach ($Lobjs as $remItem) {
|
||||
unset($val[$remItem]);
|
||||
unset($val[$remItem . '.']);
|
||||
}
|
||||
}
|
||||
$flag = 0;
|
||||
$tempXY = explode(',', $val['XY']);
|
||||
if ($Wcounter < $minDim[0]) {
|
||||
$tempXY[0] = $minDim[0] - $Wcounter;
|
||||
$flag = 1;
|
||||
}
|
||||
if ($Hcounter < $minDim[1]) {
|
||||
$tempXY[1] = $minDim[1] - $Hcounter;
|
||||
$flag = 1;
|
||||
}
|
||||
$val['XY'] = implode(',', $tempXY);
|
||||
if (!$flag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$c++;
|
||||
$gifCreator = null;
|
||||
if ($isGD) {
|
||||
// Pre-working the item
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$gifCreator->start($val, $this->menuArr[$key]);
|
||||
// If useLargestItemH/W is specified
|
||||
if (!empty($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'])) {
|
||||
$tempXY = explode(',', $gifCreator->setup['XY']);
|
||||
if ($this->mconf['useLargestItemX']) {
|
||||
$tempXY[0] = max($totalWH['W']);
|
||||
}
|
||||
if ($this->mconf['useLargestItemY']) {
|
||||
$tempXY[1] = max($totalWH['H']);
|
||||
}
|
||||
// Regenerate the new values...
|
||||
$val['XY'] = implode(',', $tempXY);
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$gifCreator->start($val, $this->menuArr[$key]);
|
||||
}
|
||||
// If distributeH/W is specified
|
||||
if (!empty($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY'])) {
|
||||
$tempXY = explode(',', $gifCreator->setup['XY']);
|
||||
if ($this->mconf['distributeX']) {
|
||||
$diff = $this->mconf['distributeX'] - $totalWH['W_total'] - $distributeAccu['W'];
|
||||
$compensate = round($diff / ($items - $c + 1));
|
||||
$distributeAccu['W'] += $compensate;
|
||||
$tempXY[0] = $totalWH['W'][$key] + $compensate;
|
||||
}
|
||||
if ($this->mconf['distributeY']) {
|
||||
$diff = $this->mconf['distributeY'] - $totalWH['H_total'] - $distributeAccu['H'];
|
||||
$compensate = round($diff / ($items - $c + 1));
|
||||
$distributeAccu['H'] += $compensate;
|
||||
$tempXY[1] = $totalWH['H'][$key] + $compensate;
|
||||
}
|
||||
// Regenerate the new values...
|
||||
$val['XY'] = implode(',', $tempXY);
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$gifCreator->start($val, $this->menuArr[$key]);
|
||||
}
|
||||
// If max dimensions are specified
|
||||
if ($maxDim) {
|
||||
$tempXY = explode(',', $val['XY']);
|
||||
if ($maxDim[0] && $Wcounter + $gifCreator->XY[0] >= $maxDim[0]) {
|
||||
$tempXY[0] = $maxDim[0] - $Wcounter;
|
||||
$maxFlag = 1;
|
||||
}
|
||||
if ($maxDim[1] && $Hcounter + $gifCreator->XY[1] >= $maxDim[1]) {
|
||||
$tempXY[1] = $maxDim[1] - $Hcounter;
|
||||
$maxFlag = 1;
|
||||
}
|
||||
if ($maxFlag) {
|
||||
$val['XY'] = implode(',', $tempXY);
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$gifCreator->start($val, $this->menuArr[$key]);
|
||||
}
|
||||
}
|
||||
// displace
|
||||
if ($Hobjs) {
|
||||
foreach ($Hobjs as $index) {
|
||||
if ($gifCreator->setup[$index] && $gifCreator->setup[$index . '.']) {
|
||||
$oldOffset = explode(',', $gifCreator->setup[$index . '.']['offset']);
|
||||
$gifCreator->setup[$index . '.']['offset'] = implode(',', $gifCreator->applyOffset($oldOffset, [0, -$Hcounter]));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Wobjs) {
|
||||
foreach ($Wobjs as $index) {
|
||||
if ($gifCreator->setup[$index] && $gifCreator->setup[$index . '.']) {
|
||||
$oldOffset = explode(',', $gifCreator->setup[$index . '.']['offset']);
|
||||
$gifCreator->setup[$index . '.']['offset'] = implode(',', $gifCreator->applyOffset($oldOffset, [-$Wcounter, 0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Finding alternative GIF names if any (by altImgResource)
|
||||
$gifFileName = '';
|
||||
if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.'])) {
|
||||
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$cObj->start($this->menuArr[$key], 'pages');
|
||||
$altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'], $conf[$key]['altImgResource.']);
|
||||
$gifFileName = $altImgInfo[3];
|
||||
}
|
||||
// If an alternative name was NOT given, find the GIFBUILDER name.
|
||||
if (!$gifFileName && $isGD) {
|
||||
GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/typo3temp/assets/menu/');
|
||||
$gifFileName = $gifCreator->fileName('assets/menu/');
|
||||
}
|
||||
$this->result[$resKey][$key] = $conf[$key];
|
||||
// Generation of image file:
|
||||
// File exists
|
||||
if (file_exists($gifFileName)) {
|
||||
$imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $gifFileName);
|
||||
$this->result[$resKey][$key]['output_w'] = (int)$imageInfo->getWidth();
|
||||
$this->result[$resKey][$key]['output_h'] = (int)$imageInfo->getHeight();
|
||||
$this->result[$resKey][$key]['output_file'] = $gifFileName;
|
||||
} elseif ($isGD) {
|
||||
// file is generated
|
||||
$gifCreator->make();
|
||||
$this->result[$resKey][$key]['output_w'] = $gifCreator->w;
|
||||
$this->result[$resKey][$key]['output_h'] = $gifCreator->h;
|
||||
$this->result[$resKey][$key]['output_file'] = $gifFileName;
|
||||
$gifCreator->output($this->result[$resKey][$key]['output_file']);
|
||||
$gifCreator->destroy();
|
||||
}
|
||||
// counter is increased
|
||||
$Hcounter += $this->result[$resKey][$key]['output_h'];
|
||||
// counter is increased
|
||||
$Wcounter += $this->result[$resKey][$key]['output_w'];
|
||||
if ($maxFlag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function searching for the largest width and height of the menu items to be generated.
|
||||
* Uses some of the same code as makeGifs and even instantiates some gifbuilder objects BUT does not render the images - only reading out which width they would have.
|
||||
* Remember to upgrade the code in here if the makeGifs function is updated.
|
||||
*
|
||||
* @param array $conf Same configuration array as passed to makeGifs()
|
||||
* @param int $items The number of menu items
|
||||
* @param array $Hobjs Array with "applyTotalH" numbers (unused)
|
||||
* @param array $Wobjs Array with "applyTotalW" numbers (unused)
|
||||
* @param array $minDim Array with "min" x/y
|
||||
* @param array $maxDim Array with "max" x/y
|
||||
* @return array Array with keys "H" and "W" which are in themselves arrays with the heights and widths of menu items inside. This can be used to find the max/min size of the menu items.
|
||||
* @internal
|
||||
* @see makeGifs()
|
||||
*/
|
||||
public function findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim)
|
||||
{
|
||||
$items = (int)$items;
|
||||
$totalWH = [
|
||||
'W' => [],
|
||||
'H' => [],
|
||||
'W_total' => 0,
|
||||
'H_total' => 0
|
||||
];
|
||||
$Hcounter = 0;
|
||||
$Wcounter = 0;
|
||||
$c = 0;
|
||||
$maxFlag = 0;
|
||||
foreach ($conf as $key => $val) {
|
||||
// SAME CODE AS makeGifs()! BEGIN
|
||||
if ($items === $c + 1 && $minDim) {
|
||||
$Lobjs = $this->mconf['removeObjectsOfDummy'];
|
||||
if ($Lobjs) {
|
||||
$Lobjs = GeneralUtility::intExplode(',', $Lobjs);
|
||||
foreach ($Lobjs as $remItem) {
|
||||
unset($val[$remItem]);
|
||||
unset($val[$remItem . '.']);
|
||||
}
|
||||
}
|
||||
$flag = 0;
|
||||
$tempXY = explode(',', $val['XY']);
|
||||
if ($Wcounter < $minDim[0]) {
|
||||
$tempXY[0] = $minDim[0] - $Wcounter;
|
||||
$flag = 1;
|
||||
}
|
||||
if ($Hcounter < $minDim[1]) {
|
||||
$tempXY[1] = $minDim[1] - $Hcounter;
|
||||
$flag = 1;
|
||||
}
|
||||
$val['XY'] = implode(',', $tempXY);
|
||||
if (!$flag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$c++;
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$gifCreator->start($val, $this->menuArr[$key]);
|
||||
if ($maxDim) {
|
||||
$tempXY = explode(',', $val['XY']);
|
||||
if ($maxDim[0] && $Wcounter + $gifCreator->XY[0] >= $maxDim[0]) {
|
||||
$tempXY[0] = $maxDim[0] - $Wcounter;
|
||||
$maxFlag = 1;
|
||||
}
|
||||
if ($maxDim[1] && $Hcounter + $gifCreator->XY[1] >= $maxDim[1]) {
|
||||
$tempXY[1] = $maxDim[1] - $Hcounter;
|
||||
$maxFlag = 1;
|
||||
}
|
||||
if ($maxFlag) {
|
||||
$val['XY'] = implode(',', $tempXY);
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$gifCreator->start($val, $this->menuArr[$key]);
|
||||
}
|
||||
}
|
||||
// SAME CODE AS makeGifs()! END
|
||||
// Setting the width/height
|
||||
$totalWH['W'][$key] = $gifCreator->XY[0];
|
||||
$totalWH['H'][$key] = $gifCreator->XY[1];
|
||||
$totalWH['W_total'] += $gifCreator->XY[0];
|
||||
$totalWH['H_total'] += $gifCreator->XY[1];
|
||||
// counter is increased
|
||||
$Hcounter += $gifCreator->XY[1];
|
||||
// counter is increased
|
||||
$Wcounter += $gifCreator->XY[0];
|
||||
if ($maxFlag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $totalWH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the ->result['NO'] array of menu items configuration (made by ->generate()) and renders the HTML of each item (the images themselves was made with makeGifs() before this. See ->generate())
|
||||
* During the execution of this function many internal methods prefixed "extProc_" from this class is called and many of these are for now dummy functions. But they can be used for processing as they are used by the GMENU_LAYERS
|
||||
*
|
||||
* @return string The HTML for the menu (returns result through $this->extProc_finish(); )
|
||||
*/
|
||||
public function writeMenu()
|
||||
{
|
||||
if (!is_array($this->menuArr) || empty($this->result) || !is_array($this->result['NO'])) {
|
||||
return '';
|
||||
}
|
||||
$this->WMresult = '';
|
||||
$this->INPfixMD5 = substr(md5(microtime() . $this->GMENU_fixKey), 0, 4);
|
||||
$this->WMmenuItems = count($this->result['NO']);
|
||||
$typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
|
||||
$this->WMsubmenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes']], $this->WMmenuItems);
|
||||
$this->extProc_init();
|
||||
$tsfe = $this->getTypoScriptFrontendController();
|
||||
if (!isset($tsfe->additionalJavaScript['JSImgCode'])) {
|
||||
$tsfe->additionalJavaScript['JSImgCode'] = '';
|
||||
}
|
||||
for ($key = 0; $key < $this->WMmenuItems; $key++) {
|
||||
if ($this->result['NO'][$key]['output_file']) {
|
||||
// Initialize the cObj with the page record of the menu item
|
||||
$this->WMcObj->start($this->menuArr[$key], 'pages');
|
||||
$this->I = [];
|
||||
$this->I['key'] = $key;
|
||||
$this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_' . $this->INPfixMD5) . '_' . $key;
|
||||
$this->I['val'] = $this->result['NO'][$key];
|
||||
$this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']);
|
||||
$this->I['uid'] = $this->menuArr[$key]['uid'];
|
||||
$this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
|
||||
$this->I['pid'] = $this->menuArr[$key]['pid'];
|
||||
$this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
|
||||
if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {
|
||||
$this->I['spacer'] = 1;
|
||||
}
|
||||
$this->I['noLink'] = $this->I['spacer'] || $this->I['val']['noLink'] || empty($this->menuArr[$key]);
|
||||
// !count($this->menuArr[$key]) means that this item is a dummyItem
|
||||
$this->I['name'] = '';
|
||||
// Set access key
|
||||
if ($this->mconf['accessKey']) {
|
||||
$this->I['accessKey'] = $this->accessKey($this->I['title']);
|
||||
} else {
|
||||
$this->I['accessKey'] = [];
|
||||
}
|
||||
// Make link tag
|
||||
$this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
|
||||
if (isset($this->I['val']['additionalParams.'])) {
|
||||
$this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
|
||||
}
|
||||
$this->I['linkHREF'] = $this->link($key, $this->I['val']['altTarget'], $this->mconf['forceTypeValue']);
|
||||
// Title attribute of links:
|
||||
$titleAttrValue = isset($this->I['val']['ATagTitle.']) ? $this->WMcObj->stdWrap($this->I['val']['ATagTitle'], $this->I['val']['ATagTitle.']) . $this->I['accessKey']['alt'] : $this->I['val']['ATagTitle'] . $this->I['accessKey']['alt'];
|
||||
if ($titleAttrValue !== '') {
|
||||
$this->I['linkHREF']['title'] = $titleAttrValue;
|
||||
}
|
||||
// Set rollover
|
||||
if ($this->result['RO'][$key] && !$this->I['noLink']) {
|
||||
$this->I['theName'] = $this->imgNamePrefix . $this->I['uid'] . $this->I['INPfix'];
|
||||
$this->I['name'] = ' ' . $this->nameAttribute . '="' . $this->I['theName'] . '"';
|
||||
$this->I['linkHREF']['onMouseover'] = $this->WMfreezePrefix . 'over(' . GeneralUtility::quoteJSvalue($this->I['theName']) . ');';
|
||||
$this->I['linkHREF']['onMouseout'] = $this->WMfreezePrefix . 'out(' . GeneralUtility::quoteJSvalue($this->I['theName']) . ');';
|
||||
$tsfe->additionalJavaScript['JSImgCode'] .= LF . $this->I['theName'] . '_n=new Image(); ' . $this->I['theName'] . '_n.src = ' . GeneralUtility::quoteJSvalue($tsfe->absRefPrefix . $this->I['val']['output_file']) . '; ';
|
||||
$tsfe->additionalJavaScript['JSImgCode'] .= LF . $this->I['theName'] . '_h=new Image(); ' . $this->I['theName'] . '_h.src = ' . GeneralUtility::quoteJSvalue($tsfe->absRefPrefix . $this->result['RO'][$key]['output_file']) . '; ';
|
||||
$tsfe->imagesOnPage[] = $this->result['RO'][$key]['output_file'];
|
||||
$tsfe->setJS('mouseOver');
|
||||
$this->extProc_RO($key);
|
||||
}
|
||||
// Set altText
|
||||
$this->I['altText'] = $this->I['title'] . $this->I['accessKey']['alt'];
|
||||
// Calling extra processing function
|
||||
$this->extProc_beforeLinking($key);
|
||||
// Set linking
|
||||
if (!$this->I['noLink']) {
|
||||
$this->setATagParts();
|
||||
} else {
|
||||
$this->I['A1'] = '';
|
||||
$this->I['A2'] = '';
|
||||
}
|
||||
$this->I['IMG'] = '<img src="' . $tsfe->absRefPrefix . $this->I['val']['output_file'] . '" width="' . $this->I['val']['output_w'] . '" height="' . $this->I['val']['output_h'] . '" ' . $this->parent_cObj->getBorderAttr('border="0"') . ($this->mconf['disableAltText'] ? '' : ' alt="' . htmlspecialchars($this->I['altText']) . '"') . $this->I['name'] . ($this->I['val']['imgParams'] ? ' ' . $this->I['val']['imgParams'] : '') . ' />';
|
||||
// Make before, middle and after parts
|
||||
$this->I['parts'] = [];
|
||||
$this->I['parts']['ATag_begin'] = $this->I['A1'];
|
||||
$this->I['parts']['image'] = $this->I['IMG'];
|
||||
$this->I['parts']['ATag_end'] = $this->I['A2'];
|
||||
// Passing I to a user function
|
||||
if ($this->mconf['IProcFunc']) {
|
||||
$this->I = $this->userProcess('IProcFunc', $this->I);
|
||||
}
|
||||
// Putting the item together.
|
||||
// Merge parts + beforeAllWrap
|
||||
$this->I['theItem'] = implode('', $this->I['parts']);
|
||||
$this->I['theItem'] = $this->extProc_beforeAllWrap($this->I['theItem'], $key);
|
||||
// wrap:
|
||||
$this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $this->I['val']['wrap']);
|
||||
// allWrap:
|
||||
$allWrap = isset($this->I['val']['allWrap.']) ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.']) : $this->I['val']['allWrap'];
|
||||
$this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $allWrap);
|
||||
if ($this->I['val']['subst_elementUid']) {
|
||||
$this->I['theItem'] = str_replace('{elementUid}', $this->I['uid'], $this->I['theItem']);
|
||||
}
|
||||
// allStdWrap:
|
||||
if (is_array($this->I['val']['allStdWrap.'])) {
|
||||
$this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
|
||||
}
|
||||
$tsfe->imagesOnPage[] = $this->I['val']['output_file'];
|
||||
$this->extProc_afterLinking($key);
|
||||
}
|
||||
}
|
||||
return $this->extProc_finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right before the traversing of $this->result begins.
|
||||
* Can be used for various initialization
|
||||
*
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after all processing for RollOver of an element has been done.
|
||||
*
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found OR $this->result['RO'][$key] where the configuration for that elements RO version is found!
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_RO($key)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right before the creation of the link for the menu item
|
||||
*
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_beforeLinking($key)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right after the creation of links for the menu item. This is also the last function call before the
|
||||
* for-loop traversing menu items goes to the next item.
|
||||
* This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
|
||||
* Further this calls the subMenu function in the parent class to create any submenu there might be.
|
||||
*
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
|
||||
* @see writeMenu(), AbstractMenuContentObject::subMenu()
|
||||
*/
|
||||
protected function extProc_afterLinking($key)
|
||||
{
|
||||
// Add part to the accumulated result + fetch submenus
|
||||
if (!$this->I['spacer']) {
|
||||
$this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
|
||||
}
|
||||
$part = isset($this->I['val']['wrapItemAndSub.']) ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.']) : $this->I['val']['wrapItemAndSub'];
|
||||
$this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the "wrap" happens on the menu item.
|
||||
*
|
||||
* @param string $item The current content of the menu item, $this->I['theItem'], passed along.
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found (unused)
|
||||
* @return string The modified version of $item, going back into $this->I['theItem']
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_beforeAllWrap($item, $key)
|
||||
{
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the writeMenu() function returns (only if a menu was generated)
|
||||
*
|
||||
* @return string The total menu content should be returned by this function
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_finish()
|
||||
{
|
||||
// stdWrap:
|
||||
if (is_array($this->mconf['stdWrap.'])) {
|
||||
$this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
|
||||
}
|
||||
return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap']) . $this->WMextraScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* This explodes a comma-list into an array where the values are parsed through ContentObjectRender::calc() and cast to (int)(so you are sure to have integers in the output array)
|
||||
* Used to split and calculate min and max values for GMENUs.
|
||||
*
|
||||
* @param string $string The string with parts in (where each part is evaluated by ->calc())
|
||||
* @return array And array with evaluated values.
|
||||
* @see ContentObjectRenderer::calc(), makeGifs()
|
||||
*/
|
||||
protected function calcIntExplode($string)
|
||||
{
|
||||
$temp = explode(',', $string);
|
||||
foreach ($temp as $key => $val) {
|
||||
$temp[$key] = (int)$this->parent_cObj->calc($val);
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Type\File\ImageInfo;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
use TYPO3\CMS\Frontend\Imaging\GifBuilder;
|
||||
|
||||
/**
|
||||
* ImageMap based menus
|
||||
*
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0
|
||||
*/
|
||||
class ImageMenuContentObject extends AbstractMenuContentObject
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
trigger_error('IMGMENU and ImageMenuContentObject will be removed in TYPO3 v10.0, you should build accessible websites with TMENU/Text, and optional images on top, which can be achieved with TypoScript.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
|
||||
* Calls makeImageMap() to generate the image map image-file
|
||||
*
|
||||
* @see AbstractMenuContentObject::procesItemStates(), makeImageMap()
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
$NOconf = [];
|
||||
$splitCount = count($this->menuArr);
|
||||
if ($splitCount) {
|
||||
list($NOconf) = $this->procesItemStates($splitCount);
|
||||
}
|
||||
if (!empty($this->mconf['debugItemConf'])) {
|
||||
echo '<h3>$NOconf:</h3>';
|
||||
debug($NOconf);
|
||||
}
|
||||
$this->makeImageMap($NOconf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will traverse input array with configuration per-item and create corresponding GIF files for the menu.
|
||||
* The data of the files are stored in $this->result
|
||||
*
|
||||
* @param array $conf Array with configuration for each item.
|
||||
* @internal
|
||||
* @see generate()
|
||||
*/
|
||||
public function makeImageMap($conf)
|
||||
{
|
||||
if (!is_array($conf)) {
|
||||
$conf = [];
|
||||
}
|
||||
if (is_array($this->mconf['main.'])) {
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
|
||||
$itemsConf = $conf;
|
||||
$conf = $this->mconf['main.'];
|
||||
if (is_array($conf)) {
|
||||
$sKeyArray = ArrayUtility::filterAndSortByNumericKeys($conf);
|
||||
$gifObjCount = (int)end($sKeyArray);
|
||||
// Now we add graphical objects to the gifbuilder-setup
|
||||
$waArr = [];
|
||||
foreach ($itemsConf as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$gifObjCount++;
|
||||
$waArr[$key]['free'] = $gifObjCount;
|
||||
$sKeyArray = ArrayUtility::filterAndSortByNumericKeys($val);
|
||||
foreach ($sKeyArray as $theKey) {
|
||||
$theValue = $val[$theKey];
|
||||
if ((int)$theKey && ($theValArr = $val[$theKey . '.'])) {
|
||||
$cObjData = $this->menuArr[$key] ?: [];
|
||||
$gifObjCount++;
|
||||
if ($theValue === 'TEXT') {
|
||||
$waArr[$key]['textNum'] = $gifObjCount;
|
||||
$gifCreator->data = $cObjData;
|
||||
$theValArr = $gifCreator->checkTextObj($theValArr);
|
||||
// if this is not done it seems that imageMaps will be rendered wrong!!
|
||||
unset($theValArr['text.']);
|
||||
// check links
|
||||
$LD = $this->menuTypoLink($this->menuArr[$key], $this->mconf['target'], '', '', [], '', $this->mconf['forceTypeValue']);
|
||||
// If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
|
||||
$this->changeLinksForAccessRestrictedPages($LD, $this->menuArr[$key], $this->mconf['target'], $this->mconf['forceTypeValue']);
|
||||
// Overriding URL / Target if set to do so:
|
||||
if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
|
||||
$LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
|
||||
if ($this->menuArr[$key]['_OVERRIDE_TARGET']) {
|
||||
$LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
|
||||
}
|
||||
}
|
||||
// Setting target/url for Image Map:
|
||||
if ($theValArr['imgMap.']['url'] === '') {
|
||||
$theValArr['imgMap.']['url'] = $LD['totalURL'];
|
||||
}
|
||||
if ($theValArr['imgMap.']['target'] === '') {
|
||||
$theValArr['imgMap.']['target'] = $LD['target'];
|
||||
}
|
||||
if (is_array($theValArr['imgMap.']['altText.'])) {
|
||||
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$cObj->start($cObjData, 'pages');
|
||||
if (isset($theValArr['imgMap.']['altText.'])) {
|
||||
$theValArr['imgMap.']['altText'] = $cObj->stdWrap($theValArr['imgMap.']['altText'], $theValArr['imgMap.']['altText.']);
|
||||
}
|
||||
unset($theValArr['imgMap.']['altText.']);
|
||||
}
|
||||
if (is_array($theValArr['imgMap.']['titleText.'])) {
|
||||
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$cObj->start($cObjData, 'pages');
|
||||
if (isset($theValArr['imgMap.']['titleText.'])) {
|
||||
$theValArr['imgMap.']['titleText'] = $cObj->stdWrap($theValArr['imgMap.']['titleText'], $theValArr['imgMap.']['titleText.']);
|
||||
}
|
||||
unset($theValArr['imgMap.']['titleText.']);
|
||||
}
|
||||
}
|
||||
// This code goes one level in if the object is an image. If 'file' and/or 'mask' appears to be GIFBUILDER-objects, they are both searched for TEXT objects, and if a textobj is found, it's checked with the currently loaded record!!
|
||||
if ($theValue === 'IMAGE') {
|
||||
if ($theValArr['file'] === 'GIFBUILDER') {
|
||||
$temp_sKeyArray = ArrayUtility::filterAndSortByNumericKeys($theValArr['file.']);
|
||||
foreach ($temp_sKeyArray as $temp_theKey) {
|
||||
if ($theValArr['mask.'][$temp_theKey] === 'TEXT') {
|
||||
$gifCreator->data = $this->menuArr[$key] ?: [];
|
||||
$theValArr['mask.'][$temp_theKey . '.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey . '.']);
|
||||
// If this is not done it seems that imageMaps will be rendered wrong!!
|
||||
unset($theValArr['mask.'][$temp_theKey . '.']['text.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($theValArr['mask'] === 'GIFBUILDER') {
|
||||
$temp_sKeyArray = ArrayUtility::filterAndSortByNumericKeys($theValArr['mask.']);
|
||||
foreach ($temp_sKeyArray as $temp_theKey) {
|
||||
if ($theValArr['mask.'][$temp_theKey] === 'TEXT') {
|
||||
$gifCreator->data = $this->menuArr[$key] ?: [];
|
||||
$theValArr['mask.'][$temp_theKey . '.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey . '.']);
|
||||
// if this is not done it seems that imageMaps will be rendered wrong!!
|
||||
unset($theValArr['mask.'][$temp_theKey . '.']['text.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Checks if disabled is set...
|
||||
$setObjFlag = 1;
|
||||
if ($theValArr['if.']) {
|
||||
/** @var ContentObjectRenderer $cObj */
|
||||
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$cObj->start($cObjData, 'pages');
|
||||
if (!empty($theValArr['if.']) && !$cObj->checkIf($theValArr['if.'])) {
|
||||
$setObjFlag = 0;
|
||||
}
|
||||
unset($theValArr['if.']);
|
||||
}
|
||||
// Set the object!
|
||||
if ($setObjFlag) {
|
||||
$conf[$gifObjCount] = $theValue;
|
||||
$conf[$gifObjCount . '.'] = $theValArr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$gifCreator->start($conf, $this->getTypoScriptFrontendController()->page);
|
||||
// calculations
|
||||
$dConf = [];
|
||||
foreach ($waArr as $key => $val) {
|
||||
if ($dConf[$key] = $itemsConf[$key]['distrib']) {
|
||||
$textBB = $gifCreator->objBB[$val['textNum']];
|
||||
$dConf[$key] = str_replace(
|
||||
['textX', 'textY'],
|
||||
[$textBB[0], $textBB[1]],
|
||||
$dConf[$key]
|
||||
);
|
||||
$dConf[$key] = GeneralUtility::intExplode(',', $gifCreator->calcOffset($dConf[$key]));
|
||||
}
|
||||
}
|
||||
$workArea = GeneralUtility::intExplode(',', $gifCreator->calcOffset($this->mconf['dWorkArea']));
|
||||
foreach ($waArr as $key => $val) {
|
||||
$index = $val['free'];
|
||||
$gifCreator->setup[$index] = 'WORKAREA';
|
||||
$workArea[2] = $dConf[$key][2] ?: $dConf[$key][0];
|
||||
$workArea[3] = $dConf[$key][3] ?: $dConf[$key][1];
|
||||
$gifCreator->setup[$index . '.']['set'] = implode(',', $workArea);
|
||||
$workArea[0] += $dConf[$key][0];
|
||||
$workArea[1] += $dConf[$key][1];
|
||||
}
|
||||
if ($this->mconf['debugRenumberedObject']) {
|
||||
echo '<h3>Renumbered GIFBUILDER object:</h3>';
|
||||
debug($gifCreator->setup);
|
||||
}
|
||||
GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/typo3temp/assets/menu/');
|
||||
$gifFileName = $gifCreator->fileName('assets/menu/');
|
||||
// Gets the ImageMap from the cache...
|
||||
$cache = $this->getCache();
|
||||
$imgHash = md5($gifFileName);
|
||||
$imgMap = $cache->get($imgHash);
|
||||
// File exists
|
||||
if ($imgMap && file_exists($gifFileName)) {
|
||||
$imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $gifFileName);
|
||||
$w = $imageInfo->getWidth();
|
||||
$h = $imageInfo->getHeight();
|
||||
} else {
|
||||
// file is generated
|
||||
$gifCreator->make();
|
||||
$w = $gifCreator->w;
|
||||
$h = $gifCreator->h;
|
||||
$gifCreator->output($gifFileName);
|
||||
$gifCreator->destroy();
|
||||
$imgMap = $gifCreator->map;
|
||||
$cache->set($imgHash, $imgMap, ['ident_MENUIMAGEMAP'], 0);
|
||||
}
|
||||
$imgMap .= $this->mconf['imgMapExtras'];
|
||||
$this->result = ['output_file' => $gifFileName, 'output_w' => $w, 'output_h' => $h, 'imgMap' => $imgMap];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML for the image map menu.
|
||||
* If ->result is TRUE it will create the HTML for the image map menu.
|
||||
*
|
||||
* @return string The HTML for the menu
|
||||
*/
|
||||
public function writeMenu()
|
||||
{
|
||||
if ($this->result) {
|
||||
$res = $this->result;
|
||||
// shortMD5 260900
|
||||
$menuName = 'menu_' . GeneralUtility::shortMD5($res['imgMap']);
|
||||
$result = '<img src="' . $this->getTypoScriptFrontendController()->absRefPrefix . $res['output_file'] . '" width="' . $res['output_w'] . '" height="' . $res['output_h'] . '" usemap="#' . $menuName . '" border="0" ' . $this->mconf['params'];
|
||||
// Adding alt attribute if not set.
|
||||
if (!strstr($result, 'alt="')) {
|
||||
$result .= ' alt="Menu Image Map"';
|
||||
}
|
||||
$result .= ' /><map name="' . $menuName . '" id="' . $menuName . '">' . $res['imgMap'] . '</map>';
|
||||
$this->getTypoScriptFrontendController()->imagesOnPage[] = $res['output_file'];
|
||||
return $this->WMcObj->wrap($result, $this->mconf['wrap']);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Factory for menu content objects. Allows overriding the default
|
||||
* types like 'GMENU' with an own implementation (only one possible)
|
||||
* and new types can be registered.
|
||||
* @internal this is only used for internal purposes and solely used for EXT:frontend and not part of TYPO3's Core API.
|
||||
*/
|
||||
class MenuContentObjectFactory implements SingletonInterface
|
||||
{
|
||||
/**
|
||||
* Register of TypoScript keys to according render class
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $menuTypeToClassMapping = [
|
||||
'GMENU' => GraphicalMenuContentObject::class,
|
||||
'TMENU' => TextMenuContentObject::class,
|
||||
'IMGMENU' => ImageMenuContentObject::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets a typo script string like 'TMENU' and returns an object of this type
|
||||
*
|
||||
* @param string $type
|
||||
* @return AbstractMenuContentObject Menu object
|
||||
* @throws Exception\NoSuchMenuTypeException
|
||||
*/
|
||||
public function getMenuObjectByType($type = '')
|
||||
{
|
||||
$upperCasedClassName = strtoupper($type);
|
||||
if (array_key_exists($upperCasedClassName, $this->menuTypeToClassMapping)) {
|
||||
$object = GeneralUtility::makeInstance($this->menuTypeToClassMapping[$upperCasedClassName]);
|
||||
} else {
|
||||
throw new Exception\NoSuchMenuTypeException(
|
||||
'Menu type ' . (string)$type . ' has no implementing class.',
|
||||
1363278130
|
||||
);
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new menu type or override existing type
|
||||
*
|
||||
* @param string $type Menu type to be used in TypoScript
|
||||
* @param string $className Class rendering the menu
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function registerMenuType($type, $className)
|
||||
{
|
||||
if (!is_string($type) || !is_string($className)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'type and className must be strings',
|
||||
1363429303
|
||||
);
|
||||
}
|
||||
$this->menuTypeToClassMapping[strtoupper($type)] = $className;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Extension class creating text based menus
|
||||
*/
|
||||
class TextMenuContentObject extends AbstractMenuContentObject
|
||||
{
|
||||
/**
|
||||
* Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
|
||||
* Sets the result for the new "normal state" in $this->result
|
||||
*
|
||||
* @see AbstractMenuContentObject::procesItemStates()
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
$NOconf = [];
|
||||
$splitCount = count($this->menuArr);
|
||||
if ($splitCount) {
|
||||
list($NOconf) = $this->procesItemStates($splitCount);
|
||||
}
|
||||
if (!empty($this->mconf['debugItemConf'])) {
|
||||
echo '<h3>$NOconf:</h3>';
|
||||
debug($NOconf);
|
||||
}
|
||||
$this->result = $NOconf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
|
||||
* During the execution of this function many internal methods prefixed "extProc_" from this class is called and
|
||||
* many of these are for now dummy functions.
|
||||
* An instance of ContentObjectRenderer is also made and for each menu item rendered it is loaded with
|
||||
* the record for that page so that any stdWrap properties that applies will have the current menu items record available.
|
||||
*
|
||||
* @return string The HTML for the menu (returns result through $this->extProc_finish(); )
|
||||
*/
|
||||
public function writeMenu()
|
||||
{
|
||||
if (empty($this->result)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$this->WMresult = '';
|
||||
$this->INPfixMD5 = substr(md5(microtime() . 'tmenu'), 0, 4);
|
||||
$this->WMmenuItems = count($this->result);
|
||||
$typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
|
||||
$this->WMsubmenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes']], $this->WMmenuItems);
|
||||
$this->extProc_init();
|
||||
foreach ($this->result as $key => $val) {
|
||||
$GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
|
||||
$GLOBALS['TSFE']->register['count_MENUOBJ']++;
|
||||
// Initialize the cObj with the page record of the menu item
|
||||
$this->WMcObj->start($this->menuArr[$key], 'pages');
|
||||
$this->I = [];
|
||||
$this->I['key'] = $key;
|
||||
$this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_' . $this->INPfixMD5) . '_' . $key;
|
||||
$this->I['val'] = $val;
|
||||
$this->I['title'] = isset($this->I['val']['stdWrap.']) ? $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']), $this->I['val']['stdWrap.']) : $this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']);
|
||||
$this->I['uid'] = $this->menuArr[$key]['uid'];
|
||||
$this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
|
||||
$this->I['pid'] = $this->menuArr[$key]['pid'];
|
||||
$this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
|
||||
// Set access key
|
||||
if ($this->mconf['accessKey']) {
|
||||
$this->I['accessKey'] = $this->accessKey($this->I['title']);
|
||||
} else {
|
||||
$this->I['accessKey'] = [];
|
||||
}
|
||||
// Make link tag
|
||||
$this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
|
||||
if (isset($this->I['val']['additionalParams.'])) {
|
||||
$this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
|
||||
}
|
||||
$this->I['linkHREF'] = $this->link($key, $this->I['val']['altTarget'], $this->mconf['forceTypeValue']);
|
||||
if (empty($this->I['linkHREF'])) {
|
||||
$this->I['val']['doNotLinkIt'] = 1;
|
||||
}
|
||||
// Title attribute of links:
|
||||
$titleAttrValue = isset($this->I['val']['ATagTitle.']) ? $this->WMcObj->stdWrap($this->I['val']['ATagTitle'], $this->I['val']['ATagTitle.']) . $this->I['accessKey']['alt'] : $this->I['val']['ATagTitle'] . $this->I['accessKey']['alt'];
|
||||
if ($titleAttrValue !== '') {
|
||||
$this->I['linkHREF']['title'] = $titleAttrValue;
|
||||
}
|
||||
|
||||
// Calling extra processing function
|
||||
$this->extProc_beforeLinking($key);
|
||||
// stdWrap for doNotLinkIt
|
||||
if (isset($this->I['val']['doNotLinkIt.'])) {
|
||||
$this->I['val']['doNotLinkIt'] = $this->WMcObj->stdWrap($this->I['val']['doNotLinkIt'], $this->I['val']['doNotLinkIt.']);
|
||||
}
|
||||
// Compile link tag
|
||||
if (!$this->I['val']['doNotLinkIt']) {
|
||||
$this->I['val']['doNotLinkIt'] = 0;
|
||||
}
|
||||
if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt'] != 1) {
|
||||
$this->setATagParts();
|
||||
} else {
|
||||
$this->I['A1'] = '';
|
||||
$this->I['A2'] = '';
|
||||
}
|
||||
// ATagBeforeWrap processing:
|
||||
if ($this->I['val']['ATagBeforeWrap']) {
|
||||
$wrapPartsBefore = explode('|', $this->I['val']['linkWrap']);
|
||||
$wrapPartsAfter = ['', ''];
|
||||
} else {
|
||||
$wrapPartsBefore = ['', ''];
|
||||
$wrapPartsAfter = explode('|', $this->I['val']['linkWrap']);
|
||||
}
|
||||
if ($this->I['val']['stdWrap2'] || isset($this->I['val']['stdWrap2.'])) {
|
||||
$stdWrap2 = isset($this->I['val']['stdWrap2.']) ? $this->WMcObj->stdWrap('|', $this->I['val']['stdWrap2.']) : '|';
|
||||
$wrapPartsStdWrap = explode($this->I['val']['stdWrap2'] ? $this->I['val']['stdWrap2'] : '|', $stdWrap2);
|
||||
} else {
|
||||
$wrapPartsStdWrap = ['', ''];
|
||||
}
|
||||
// Make before, middle and after parts
|
||||
$this->I['parts'] = [];
|
||||
$this->I['parts']['before'] = $this->getBeforeAfter('before');
|
||||
$this->I['parts']['stdWrap2_begin'] = $wrapPartsStdWrap[0];
|
||||
// stdWrap for doNotShowLink
|
||||
if (isset($this->I['val']['doNotShowLink.'])) {
|
||||
$this->I['val']['doNotShowLink'] = $this->WMcObj->stdWrap($this->I['val']['doNotShowLink'], $this->I['val']['doNotShowLink.']);
|
||||
}
|
||||
if (!$this->I['val']['doNotShowLink']) {
|
||||
$this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0];
|
||||
$this->I['parts']['ATag_begin'] = $this->I['A1'];
|
||||
$this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0];
|
||||
$this->I['parts']['title'] = $this->I['title'];
|
||||
$this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1];
|
||||
$this->I['parts']['ATag_end'] = $this->I['A2'];
|
||||
$this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1];
|
||||
}
|
||||
$this->I['parts']['stdWrap2_end'] = $wrapPartsStdWrap[1];
|
||||
$this->I['parts']['after'] = $this->getBeforeAfter('after');
|
||||
// Passing I to a user function
|
||||
if ($this->mconf['IProcFunc']) {
|
||||
$this->I = $this->userProcess('IProcFunc', $this->I);
|
||||
}
|
||||
// Merge parts + beforeAllWrap
|
||||
$this->I['theItem'] = implode('', $this->I['parts']);
|
||||
$this->I['theItem'] = $this->extProc_beforeAllWrap($this->I['theItem'], $key);
|
||||
// allWrap:
|
||||
$allWrap = isset($this->I['val']['allWrap.']) ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.']) : $this->I['val']['allWrap'];
|
||||
$this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $allWrap);
|
||||
if ($this->I['val']['subst_elementUid']) {
|
||||
$this->I['theItem'] = str_replace('{elementUid}', $this->I['uid'], $this->I['theItem']);
|
||||
}
|
||||
// allStdWrap:
|
||||
if (is_array($this->I['val']['allStdWrap.'])) {
|
||||
$this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
|
||||
}
|
||||
// Calling extra processing function
|
||||
$this->extProc_afterLinking($key);
|
||||
}
|
||||
return $this->extProc_finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the before* and after* images for TMENUs
|
||||
*
|
||||
* @param string $pref Can be "before" or "after" and determines which kind of image to create (basically this is the prefix of the TypoScript properties that are read from the ->I['val'] array
|
||||
* @return string The resulting HTML of the image, if any.
|
||||
*/
|
||||
protected function getBeforeAfter($pref)
|
||||
{
|
||||
$res = '';
|
||||
if ($imgInfo = $this->WMcObj->getImgResource($this->I['val'][$pref . 'Img'], $this->I['val'][$pref . 'Img.'])) {
|
||||
$theName = $this->imgNamePrefix . $this->I['uid'] . $this->I['INPfix'] . $pref;
|
||||
$name = ' ' . $this->nameAttribute . '="' . $theName . '"';
|
||||
$GLOBALS['TSFE']->imagesOnPage[] = $imgInfo[3];
|
||||
$res = '<img' . ' src="' . $GLOBALS['TSFE']->absRefPrefix . $imgInfo[3] . '"' . ' width="' . $imgInfo[0] . '"' . ' height="' . $imgInfo[1] . '"' . $name . ($this->I['val'][$pref . 'ImgTagParams'] ? ' ' . $this->I['val'][$pref . 'ImgTagParams'] : '') . $this->parent_cObj->getBorderAttr(' border="0"');
|
||||
if (!strstr($res, 'alt="')) {
|
||||
// Adding alt attribute if not set.
|
||||
$res .= ' alt=""';
|
||||
}
|
||||
$res .= ' />';
|
||||
if ($this->I['val'][$pref . 'ImgLink']) {
|
||||
$res = $this->I['A1'] . $res . $this->I['A2'];
|
||||
}
|
||||
}
|
||||
$processedPref = isset($this->I['val'][$pref . '.']) ? $this->WMcObj->stdWrap($this->I['val'][$pref], $this->I['val'][$pref . '.']) : $this->I['val'][$pref];
|
||||
if (isset($this->I['val'][$pref . 'Wrap'])) {
|
||||
return $this->WMcObj->wrap($res . $processedPref, $this->I['val'][$pref . 'Wrap']);
|
||||
}
|
||||
return $res . $processedPref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right before the traversing of $this->result begins.
|
||||
* Can be used for various initialization
|
||||
*
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right before the creation of the link for the menu item
|
||||
*
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_beforeLinking($key)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right after the creation of links for the menu item. This is also the last function call before the while-loop traversing menu items goes to the next item.
|
||||
* This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
|
||||
*
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_afterLinking($key)
|
||||
{
|
||||
// Add part to the accumulated result + fetch submenus
|
||||
if (!$this->I['spacer']) {
|
||||
$this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
|
||||
}
|
||||
$part = isset($this->I['val']['wrapItemAndSub.']) ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.']) : $this->I['val']['wrapItemAndSub'];
|
||||
$this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the "allWrap" happens on the menu item.
|
||||
*
|
||||
* @param string $item The current content of the menu item, $this->I['theItem'], passed along.
|
||||
* @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
|
||||
* @return string The modified version of $item, going back into $this->I['theItem']
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_beforeAllWrap($item, $key)
|
||||
{
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the writeMenu() function returns (only if a menu was generated)
|
||||
*
|
||||
* @return string The total menu content should be returned by this function
|
||||
* @see writeMenu()
|
||||
*/
|
||||
protected function extProc_finish()
|
||||
{
|
||||
// stdWrap:
|
||||
if (is_array($this->mconf['stdWrap.'])) {
|
||||
$this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
|
||||
}
|
||||
return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap']) . $this->WMextraScript;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Database\RelationHandler;
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Category\Collection\CategoryCollection;
|
||||
use TYPO3\CMS\Frontend\Page\PageRepository;
|
||||
|
||||
/**
|
||||
* Contains RECORDS class object.
|
||||
*/
|
||||
class RecordsContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* List of all items with table and uid information
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $itemArray = [];
|
||||
|
||||
/**
|
||||
* List of all selected records with full data, arranged per table
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Rendering the cObject, RECORDS
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
// Reset items and data
|
||||
$this->itemArray = [];
|
||||
$this->data = [];
|
||||
|
||||
$theValue = '';
|
||||
$originalRec = $GLOBALS['TSFE']->currentRecord;
|
||||
// If the currentRecord is set, we register, that this record has invoked this function.
|
||||
// It's should not be allowed to do this again then!!
|
||||
if ($originalRec) {
|
||||
++$GLOBALS['TSFE']->recordRegister[$originalRec];
|
||||
}
|
||||
|
||||
$tables = isset($conf['tables.']) ? $this->cObj->stdWrap($conf['tables'], $conf['tables.']) : $conf['tables'];
|
||||
if ($tables) {
|
||||
$tablesArray = array_unique(GeneralUtility::trimExplode(',', $tables, true));
|
||||
// Add tables which have a configuration (note that this may create duplicate entries)
|
||||
if (is_array($conf['conf.'])) {
|
||||
foreach ($conf['conf.'] as $key => $value) {
|
||||
if (substr($key, -1) !== '.' && !in_array($key, $tablesArray)) {
|
||||
$tablesArray[] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the data, depending on collection method.
|
||||
// Property "source" is considered more precise and thus takes precedence over "categories"
|
||||
$source = isset($conf['source.']) ? $this->cObj->stdWrap($conf['source'], $conf['source.']) : $conf['source'];
|
||||
$categories = isset($conf['categories.']) ? $this->cObj->stdWrap($conf['categories'], $conf['categories.']) : $conf['categories'];
|
||||
if ($source) {
|
||||
$this->collectRecordsFromSource($source, $tablesArray);
|
||||
} elseif ($categories) {
|
||||
$relationField = isset($conf['categories.']['relation.']) ? $this->cObj->stdWrap($conf['categories.']['relation'], $conf['categories.']['relation.']) : $conf['categories.']['relation'];
|
||||
$this->collectRecordsFromCategories($categories, $tablesArray, $relationField);
|
||||
}
|
||||
$itemArrayCount = count($this->itemArray);
|
||||
if ($itemArrayCount > 0) {
|
||||
/** @var ContentObjectRenderer $cObj */
|
||||
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$cObj->setParent($this->cObj->data, $this->cObj->currentRecord);
|
||||
$this->cObj->currentRecordNumber = 0;
|
||||
$this->cObj->currentRecordTotal = $itemArrayCount;
|
||||
foreach ($this->itemArray as $val) {
|
||||
$row = $this->data[$val['table']][$val['id']];
|
||||
// Perform overlays if necessary (records coming from category collections are already overlaid)
|
||||
if ($source) {
|
||||
// Versioning preview
|
||||
$this->getPageRepository()->versionOL($val['table'], $row);
|
||||
// Language overlay
|
||||
if (is_array($row)) {
|
||||
$row = $this->getPageRepository()->getLanguageOverlay($val['table'], $row);
|
||||
}
|
||||
}
|
||||
// Might be unset during the overlay process
|
||||
if (is_array($row)) {
|
||||
$dontCheckPid = isset($conf['dontCheckPid.']) ? $this->cObj->stdWrap($conf['dontCheckPid'], $conf['dontCheckPid.']) : $conf['dontCheckPid'];
|
||||
if (!$dontCheckPid) {
|
||||
$row = $this->cObj->checkPid($row['pid']) ? $row : '';
|
||||
}
|
||||
if ($row && !$GLOBALS['TSFE']->recordRegister[$val['table'] . ':' . $val['id']]) {
|
||||
$renderObjName = $conf['conf.'][$val['table']] ?: '<' . $val['table'];
|
||||
$renderObjKey = $conf['conf.'][$val['table']] ? 'conf.' . $val['table'] : '';
|
||||
$renderObjConf = $conf['conf.'][$val['table'] . '.'];
|
||||
$this->cObj->currentRecordNumber++;
|
||||
$cObj->parentRecordNumber = $this->cObj->currentRecordNumber;
|
||||
$GLOBALS['TSFE']->currentRecord = $val['table'] . ':' . $val['id'];
|
||||
$this->cObj->lastChanged($row['tstamp']);
|
||||
$cObj->start($row, $val['table']);
|
||||
$tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
|
||||
$theValue .= $tmpValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
|
||||
if ($wrap) {
|
||||
$theValue = $this->cObj->wrap($theValue, $wrap);
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
|
||||
}
|
||||
// Restore
|
||||
$GLOBALS['TSFE']->currentRecord = $originalRec;
|
||||
if ($originalRec) {
|
||||
--$GLOBALS['TSFE']->recordRegister[$originalRec];
|
||||
}
|
||||
return $theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects records according to the configured source
|
||||
*
|
||||
* @param string $source Source of records
|
||||
* @param array $tables List of tables
|
||||
*/
|
||||
protected function collectRecordsFromSource($source, array $tables)
|
||||
{
|
||||
/** @var RelationHandler $loadDB*/
|
||||
$loadDB = GeneralUtility::makeInstance(RelationHandler::class);
|
||||
$loadDB->setFetchAllFields(true);
|
||||
$loadDB->start($source, implode(',', $tables));
|
||||
foreach ($loadDB->tableArray as $table => $v) {
|
||||
if (isset($GLOBALS['TCA'][$table])) {
|
||||
$loadDB->additionalWhere[$table] = $this->getPageRepository()->enableFields($table);
|
||||
}
|
||||
}
|
||||
$this->data = $loadDB->getFromDB();
|
||||
reset($loadDB->itemArray);
|
||||
$this->itemArray = $loadDB->itemArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects records for all selected tables and categories.
|
||||
*
|
||||
* @param string $selectedCategories Comma-separated list of categories
|
||||
* @param array $tables List of tables
|
||||
* @param string $relationField Name of the field containing the categories relation
|
||||
*/
|
||||
protected function collectRecordsFromCategories($selectedCategories, array $tables, $relationField)
|
||||
{
|
||||
$selectedCategories = array_unique(GeneralUtility::intExplode(',', $selectedCategories, true));
|
||||
|
||||
// Loop on all selected tables
|
||||
foreach ($tables as $table) {
|
||||
|
||||
// Get the records for each selected category
|
||||
$tableRecords = [];
|
||||
$categoriesPerRecord = [];
|
||||
foreach ($selectedCategories as $aCategory) {
|
||||
try {
|
||||
$collection = CategoryCollection::load(
|
||||
$aCategory,
|
||||
true,
|
||||
$table,
|
||||
$relationField
|
||||
);
|
||||
if ($collection->count() > 0) {
|
||||
// Add items to the collection of records for the current table
|
||||
foreach ($collection as $item) {
|
||||
$tableRecords[$item['uid']] = $item;
|
||||
// Keep track of all categories a given item belongs to
|
||||
if (!isset($categoriesPerRecord[$item['uid']])) {
|
||||
$categoriesPerRecord[$item['uid']] = [];
|
||||
}
|
||||
$categoriesPerRecord[$item['uid']][] = $aCategory;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$message = sprintf(
|
||||
'Could not get records for category id %d. Error: %s (%d)',
|
||||
$aCategory,
|
||||
$e->getMessage(),
|
||||
$e->getCode()
|
||||
);
|
||||
$this->getTimeTracker()->setTSlogMessage($message, 2);
|
||||
}
|
||||
}
|
||||
// Store the resulting records into the itemArray and data results array
|
||||
if (!empty($tableRecords)) {
|
||||
$this->data[$table] = [];
|
||||
foreach ($tableRecords as $record) {
|
||||
$this->itemArray[] = [
|
||||
'id' => $record['uid'],
|
||||
'table' => $table
|
||||
];
|
||||
// Add to the record the categories it belongs to
|
||||
$record['_categories'] = implode(',', $categoriesPerRecord[$record['uid']]);
|
||||
$this->data[$table][$record['uid']] = $record;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TimeTracker
|
||||
*/
|
||||
protected function getTimeTracker()
|
||||
{
|
||||
return GeneralUtility::makeInstance(TimeTracker::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PageRepository
|
||||
*/
|
||||
protected function getPageRepository(): PageRepository
|
||||
{
|
||||
return $GLOBALS['TSFE']->sys_page ?: GeneralUtility::makeInstance(PageRepository::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains RESTORE_REGISTER class object.
|
||||
*/
|
||||
class RestoreRegisterContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, RESTORE_REGISTER
|
||||
* NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Empty string (the cObject only sets internal data!)
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$GLOBALS['TSFE']->register = array_pop($GLOBALS['TSFE']->registerStack);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
|
||||
/**
|
||||
* Contains SVG content object.
|
||||
*/
|
||||
class ScalableVectorGraphicsContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, SVG
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string
|
||||
*/
|
||||
public function render($conf = []): string
|
||||
{
|
||||
$renderMode = isset($conf['renderMode.'])
|
||||
? $this->cObj->stdWrap($conf['renderMode'], $conf['renderMode.'])
|
||||
: $conf['renderMode'];
|
||||
|
||||
if ($renderMode === 'inline') {
|
||||
return $this->renderInline($conf);
|
||||
}
|
||||
|
||||
return $this->renderObject($conf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $conf
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function renderInline(array $conf): string
|
||||
{
|
||||
$src = $this->resolveAbsoluteSourcePath($conf);
|
||||
list($width, $height, $isDefaultWidth, $isDefaultHeight) = $this->getDimensions($conf);
|
||||
|
||||
$content = '';
|
||||
if (file_exists($src)) {
|
||||
$svgContent = file_get_contents($src);
|
||||
$svgContent = preg_replace('/<script[\s\S]*?>[\s\S]*?<\/script>/i', '', $svgContent);
|
||||
// Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
|
||||
$previousValueOfEntityLoader = libxml_disable_entity_loader();
|
||||
$svgElement = simplexml_load_string($svgContent);
|
||||
libxml_disable_entity_loader($previousValueOfEntityLoader);
|
||||
|
||||
$domXml = dom_import_simplexml($svgElement);
|
||||
if (!$isDefaultWidth) {
|
||||
$domXml->setAttribute('width', $width);
|
||||
}
|
||||
if (!$isDefaultHeight) {
|
||||
$domXml->setAttribute('height', $height);
|
||||
}
|
||||
// remove xml version tag
|
||||
$content = $domXml->ownerDocument->saveXML($domXml->ownerDocument->documentElement);
|
||||
} else {
|
||||
$value = isset($conf['value.']) ? $this->cObj->stdWrap($conf['value'], $conf['value.']) : $conf['value'];
|
||||
if (!empty($value)) {
|
||||
$content = [];
|
||||
$content[] = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' . (int)$width . '" height="' . (int)$height . '">';
|
||||
$content[] = $value;
|
||||
$content[] = '</svg>';
|
||||
$content = implode(LF, $content);
|
||||
}
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the SVG as <object> tag
|
||||
* @param array $conf
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function renderObject(array $conf): string
|
||||
{
|
||||
$src = $this->resolveAbsoluteSourcePath($conf);
|
||||
list($width, $height) = $this->getDimensions($conf);
|
||||
|
||||
$src = $src === '' ? null : PathUtility::getAbsoluteWebPath($src);
|
||||
|
||||
$value = isset($conf['value.']) ? $this->cObj->stdWrap($conf['value'], $conf['value.']) : $conf['value'];
|
||||
$noscript = isset($conf['noscript.']) ? $this->cObj->stdWrap($conf['noscript'], $conf['noscript.']) : $conf['noscript'];
|
||||
|
||||
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 - see method usages
|
||||
if (!empty($conf['noscript.']) || !empty($conf['noscript'])) {
|
||||
trigger_error('SVG cObject: The option "noscript" will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
if (!empty($conf['value.']) || !empty($conf['value'])) {
|
||||
trigger_error('SVG cObject: The option "value" without setting renderMode=inline will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$content = [];
|
||||
if ($src) {
|
||||
$content[] = '<!--[if IE]>';
|
||||
$content[] = ' <object src="' . htmlspecialchars($src) . '" classid="image/svg+xml" width="' . (int)$width . '" height="' . (int)$height . '">';
|
||||
$content[] = '<![endif]-->';
|
||||
$content[] = '<!--[if !IE]>-->';
|
||||
$content[] = ' <object data="' . htmlspecialchars($src) . '" type="image/svg+xml" width="' . (int)$width . '" height="' . (int)$height . '">';
|
||||
$content[] = '<!--<![endif]-->';
|
||||
$content[] = $noscript;
|
||||
$content[] = '</object>';
|
||||
} else {
|
||||
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 - see method usages
|
||||
$content[] = '<script type="image/svg+xml">';
|
||||
$content[] = ' <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' . (int)$width . '" height="' . (int)$height . '">';
|
||||
$content[] = $value;
|
||||
$content[] = ' </svg>';
|
||||
$content[] = '</script>';
|
||||
$content[] = '<noscript>';
|
||||
$content[] = $noscript;
|
||||
$content[] = '</noscript>';
|
||||
}
|
||||
$content = implode(LF, $content);
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $conf
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveAbsoluteSourcePath(array $conf): string
|
||||
{
|
||||
$src = isset($conf['src.']) ? $this->cObj->stdWrap($conf['src'], $conf['src.']) : $conf['src'];
|
||||
return GeneralUtility::getFileAbsFileName($src);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $conf
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDimensions(array $conf): array
|
||||
{
|
||||
$isDefaultWidth = false;
|
||||
$isDefaultHeight = false;
|
||||
$width = isset($conf['width.']) ? $this->cObj->stdWrap($conf['width'], $conf['width.']) : $conf['width'];
|
||||
$height = isset($conf['height.']) ? $this->cObj->stdWrap($conf['height'], $conf['height.']) : $conf['height'];
|
||||
|
||||
if (empty($width)) {
|
||||
$isDefaultWidth = true;
|
||||
$width = 600;
|
||||
}
|
||||
if (empty($height)) {
|
||||
$isDefaultHeight = true;
|
||||
$height = 400;
|
||||
}
|
||||
|
||||
return [$width, $height, $isDefaultWidth, $isDefaultHeight];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Html\HtmlParser;
|
||||
use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Contains TEMPLATE class object.
|
||||
*/
|
||||
class TemplateContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* @var MarkerBasedTemplateService
|
||||
*/
|
||||
protected $templateService;
|
||||
|
||||
/**
|
||||
* Default constructor, which also instantiates the MarkerBasedTemplateService.
|
||||
*
|
||||
* @param ContentObjectRenderer $cObj
|
||||
*/
|
||||
public function __construct(ContentObjectRenderer $cObj)
|
||||
{
|
||||
$this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
|
||||
parent::__construct($cObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering the cObject, TEMPLATE
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
* @see substituteMarkerArrayCached()
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$subparts = [];
|
||||
$marks = [];
|
||||
$wraps = [];
|
||||
$markerWrap = isset($conf['markerWrap.']) ? $this->cObj->stdWrap($conf['markerWrap'], $conf['markerWrap.']) : $conf['markerWrap'];
|
||||
if (!$markerWrap) {
|
||||
$markerWrap = '### | ###';
|
||||
}
|
||||
list($PRE, $POST) = explode('|', $markerWrap);
|
||||
$POST = trim($POST);
|
||||
$PRE = trim($PRE);
|
||||
// Getting the content
|
||||
$content = $this->cObj->cObjGetSingle($conf['template'], $conf['template.'], 'template');
|
||||
$workOnSubpart = isset($conf['workOnSubpart.']) ? $this->cObj->stdWrap($conf['workOnSubpart'], $conf['workOnSubpart.']) : $conf['workOnSubpart'];
|
||||
if ($workOnSubpart) {
|
||||
$content = $this->templateService->getSubpart($content, $PRE . $workOnSubpart . $POST);
|
||||
}
|
||||
// Fixing all relative paths found:
|
||||
if ($conf['relPathPrefix']) {
|
||||
$htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
|
||||
$content = $htmlParser->prefixResourcePath($conf['relPathPrefix'], $content, $conf['relPathPrefix.']);
|
||||
}
|
||||
if ($content) {
|
||||
$nonCachedSubst = isset($conf['nonCachedSubst.']) ? $this->cObj->stdWrap($conf['nonCachedSubst'], $conf['nonCachedSubst.']) : $conf['nonCachedSubst'];
|
||||
// NON-CACHED:
|
||||
if ($nonCachedSubst) {
|
||||
// Getting marks
|
||||
if (is_array($conf['marks.'])) {
|
||||
foreach ($conf['marks.'] as $theKey => $theValue) {
|
||||
if (!strstr($theKey, '.')) {
|
||||
$content = str_replace($PRE . $theKey . $POST, $this->cObj->cObjGetSingle($theValue, $conf['marks.'][$theKey . '.'], 'marks.' . $theKey), $content);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Getting subparts.
|
||||
if (is_array($conf['subparts.'])) {
|
||||
foreach ($conf['subparts.'] as $theKey => $theValue) {
|
||||
if (!strstr($theKey, '.')) {
|
||||
$subpart = $this->templateService->getSubpart($content, $PRE . $theKey . $POST);
|
||||
if ($subpart) {
|
||||
$this->cObj->setCurrentVal($subpart);
|
||||
$content = $this->templateService->substituteSubpart($content, $PRE . $theKey . $POST, $this->cObj->cObjGetSingle($theValue, $conf['subparts.'][$theKey . '.'], 'subparts.' . $theKey), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Getting subpart wraps
|
||||
if (is_array($conf['wraps.'])) {
|
||||
foreach ($conf['wraps.'] as $theKey => $theValue) {
|
||||
if (!strstr($theKey, '.')) {
|
||||
$subpart = $this->templateService->getSubpart($content, $PRE . $theKey . $POST);
|
||||
if ($subpart) {
|
||||
$this->cObj->setCurrentVal($subpart);
|
||||
$content = $this->templateService->substituteSubpart($content, $PRE . $theKey . $POST, explode('|', $this->cObj->cObjGetSingle($theValue, $conf['wraps.'][$theKey . '.'], 'wraps.' . $theKey)), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// CACHED
|
||||
// Getting subparts.
|
||||
if (is_array($conf['subparts.'])) {
|
||||
foreach ($conf['subparts.'] as $theKey => $theValue) {
|
||||
if (!strstr($theKey, '.')) {
|
||||
$subpart = $this->templateService->getSubpart($content, $PRE . $theKey . $POST);
|
||||
if ($subpart) {
|
||||
$GLOBALS['TSFE']->register['SUBPART_' . $theKey] = $subpart;
|
||||
$subparts[$theKey]['name'] = $theValue;
|
||||
$subparts[$theKey]['conf'] = $conf['subparts.'][$theKey . '.'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Getting marks
|
||||
if (is_array($conf['marks.'])) {
|
||||
foreach ($conf['marks.'] as $theKey => $theValue) {
|
||||
if (!strstr($theKey, '.')) {
|
||||
$marks[$theKey]['name'] = $theValue;
|
||||
$marks[$theKey]['conf'] = $conf['marks.'][$theKey . '.'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Getting subpart wraps
|
||||
if (is_array($conf['wraps.'])) {
|
||||
foreach ($conf['wraps.'] as $theKey => $theValue) {
|
||||
if (!strstr($theKey, '.')) {
|
||||
$wraps[$theKey]['name'] = $theValue;
|
||||
$wraps[$theKey]['conf'] = $conf['wraps.'][$theKey . '.'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Getting subparts
|
||||
$subpartArray = [];
|
||||
foreach ($subparts as $theKey => $theValue) {
|
||||
// Set current with the content of the subpart...
|
||||
$this->cObj->data[$this->cObj->currentValKey] = $GLOBALS['TSFE']->register['SUBPART_' . $theKey];
|
||||
// Get subpart cObject and substitute it!
|
||||
$subpartArray[$PRE . $theKey . $POST] = $this->cObj->cObjGetSingle($theValue['name'], $theValue['conf'], 'subparts.' . $theKey);
|
||||
}
|
||||
// Reset current to empty
|
||||
$this->cObj->data[$this->cObj->currentValKey] = '';
|
||||
// Getting marks
|
||||
$markerArray = [];
|
||||
foreach ($marks as $theKey => $theValue) {
|
||||
$markerArray[$PRE . $theKey . $POST] = $this->cObj->cObjGetSingle($theValue['name'], $theValue['conf'], 'marks.' . $theKey);
|
||||
}
|
||||
// Getting wraps
|
||||
$subpartWraps = [];
|
||||
foreach ($wraps as $theKey => $theValue) {
|
||||
$subpartWraps[$PRE . $theKey . $POST] = explode('|', $this->cObj->cObjGetSingle($theValue['name'], $theValue['conf'], 'wraps.' . $theKey));
|
||||
}
|
||||
// Substitution
|
||||
$substMarksSeparately = isset($conf['substMarksSeparately.']) ? $this->cObj->stdWrap($conf['substMarksSeparately'], $conf['substMarksSeparately.']) : $conf['substMarksSeparately'];
|
||||
if ($substMarksSeparately) {
|
||||
$content = $this->templateService->substituteMarkerArrayCached($content, [], $subpartArray, $subpartWraps);
|
||||
$content = $this->templateService->substituteMarkerArray($content, $markerArray);
|
||||
} else {
|
||||
$content = $this->templateService->substituteMarkerArrayCached($content, $markerArray, $subpartArray, $subpartWraps);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains TEXT class object.
|
||||
*/
|
||||
class TextContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, TEXT
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!is_array($conf)) {
|
||||
return '';
|
||||
}
|
||||
$content = '';
|
||||
if (isset($conf['value'])) {
|
||||
$content = $conf['value'];
|
||||
unset($conf['value']);
|
||||
}
|
||||
if (isset($conf['value.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['value.']);
|
||||
unset($conf['value.']);
|
||||
}
|
||||
if (!empty($conf)) {
|
||||
$content = $this->cObj->stdWrap($content, $conf);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* interface for classes which hook into \TYPO3\CMS\Frontend\ContentObjectRenderer and wish to modify the typolink
|
||||
* configuration of the page link.
|
||||
*/
|
||||
interface TypolinkModifyLinkConfigForPageLinksHookInterface
|
||||
{
|
||||
/**
|
||||
* Modifies the typolink page link configuration array.
|
||||
*
|
||||
* @param array $linkConfiguration The link configuration (for options see TSRef -> typolink)
|
||||
* @param array $linkDetails Additional information for the link
|
||||
* @param array $pageRow The complete page row for the page to link to
|
||||
*
|
||||
* @return array The modified $linkConfiguration
|
||||
*/
|
||||
public function modifyPageLinkConfiguration(array $linkConfiguration, array $linkDetails, array $pageRow): array;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Contains USER class object.
|
||||
*/
|
||||
class UserContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, USER
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
if (!is_array($conf) || empty($conf)) {
|
||||
$this->getTimeTracker()->setTSlogMessage('USER without configuration.', 2);
|
||||
return '';
|
||||
}
|
||||
$content = '';
|
||||
if ($this->cObj->getUserObjectType() === false) {
|
||||
// Come here only if we are not called from $TSFE->INTincScript_process()!
|
||||
$this->cObj->setUserObjectType(ContentObjectRenderer::OBJECTTYPE_USER);
|
||||
}
|
||||
$tempContent = $this->cObj->callUserFunction($conf['userFunc'], $conf, '');
|
||||
if ($this->cObj->doConvertToUserIntObject) {
|
||||
$this->cObj->doConvertToUserIntObject = false;
|
||||
$content = $this->cObj->cObjGetSingle('USER_INT', $conf);
|
||||
} else {
|
||||
$content .= $tempContent;
|
||||
// Only executed when the element is not converted to USER_INT
|
||||
if (isset($conf['stdWrap.'])) {
|
||||
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
|
||||
}
|
||||
}
|
||||
$this->cObj->setUserObjectType(false);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TimeTracker
|
||||
*/
|
||||
protected function getTimeTracker()
|
||||
{
|
||||
return GeneralUtility::makeInstance(TimeTracker::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Frontend\ContentObject;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains USER_INT class object.
|
||||
*/
|
||||
class UserInternalContentObject extends AbstractContentObject
|
||||
{
|
||||
/**
|
||||
* Rendering the cObject, USER_INT
|
||||
*
|
||||
* @param array $conf Array of TypoScript properties
|
||||
* @return string Output
|
||||
*/
|
||||
public function render($conf = [])
|
||||
{
|
||||
$this->cObj->setUserObjectType(ContentObjectRenderer::OBJECTTYPE_USER_INT);
|
||||
$tsfe = $this->getTypoScriptFrontendController();
|
||||
$substKey = 'INT_SCRIPT.' . $tsfe->uniqueHash();
|
||||
$content = '<!--' . $substKey . '-->';
|
||||
$tsfe->config['INTincScript'][$substKey] = [
|
||||
'conf' => $conf,
|
||||
'cObj' => serialize($this->cObj),
|
||||
'type' => 'FUNC'
|
||||
];
|
||||
$this->cObj->setUserObjectType(false);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
|
||||
*/
|
||||
protected function getTypoScriptFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user