[TASK] Deprecate some functions not in use anymore in the core
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / ContentObjectRenderer.php
index f8f1bad..98bdea5 100644 (file)
@@ -17,7 +17,6 @@ namespace TYPO3\CMS\Frontend\ContentObject;
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\FrontendEditing\FrontendEditingController;
 use TYPO3\CMS\Core\Html\HtmlParser;
-use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
 use TYPO3\CMS\Core\Log\LogManager;
 use TYPO3\CMS\Core\Mail\MailMessage;
 use TYPO3\CMS\Core\Resource\Exception;
@@ -28,10 +27,13 @@ use TYPO3\CMS\Core\Resource\FileReference;
 use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
+use TYPO3\CMS\Core\Service\DependencyOrderingService;
+use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\TypoScript\TemplateService;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\DebugUtility;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MailUtility;
@@ -39,12 +41,14 @@ use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
 use TYPO3\CMS\Frontend\ContentObject\Exception\ContentRenderingException;
+use TYPO3\CMS\Frontend\ContentObject\Exception\ExceptionHandlerInterface;
 use TYPO3\CMS\Frontend\ContentObject\Exception\ProductionExceptionHandler;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\CMS\Frontend\Http\UrlProcessorInterface;
 use TYPO3\CMS\Frontend\Imaging\GifBuilder;
-use TYPO3\CMS\Frontend\ContentObject\Exception\ExceptionHandlerInterface;
 use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
 use TYPO3\CMS\Frontend\Page\PageRepository;
+use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
 
 /**
  * This class contains all main TypoScript features.
@@ -54,4049 +58,3850 @@ use TYPO3\CMS\Frontend\Page\PageRepository;
  * There are lots of functions you can use from your include-scripts.
  * The class is normally instantiated and referred to as "cObj".
  * When you call your own PHP-code typically through a USER or USER_INT cObject then it is this class that instantiates the object and calls the main method. Before it does so it will set (if you are using classes) a reference to itself in the internal variable "cObj" of the object. Thus you can access all functions and data from this class by $this->cObj->... from within you classes written to be USER or USER_INT content objects.
- *
- * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
-class ContentObjectRenderer {
-
-       /**
-        * @var array
-        */
-       public $align = array(
-               'center',
-               'right',
-               'left'
-       );
-
-       /**
-        * stdWrap functions in their correct order
-        *
-        * @see stdWrap()
-        */
-       public $stdWrapOrder = array(
-               'stdWrapPreProcess' => 'hook',
-               // this is a placeholder for the first Hook
-               'cacheRead' => 'hook',
-               // this is a placeholder for checking if the content is available in cache
-               'setContentToCurrent' => 'boolean',
-               'setContentToCurrent.' => 'array',
-               'addPageCacheTags' => 'string',
-               'addPageCacheTags.' => 'array',
-               'setCurrent' => 'string',
-               'setCurrent.' => 'array',
-               'lang.' => 'array',
-               'data' => 'getText',
-               'data.' => 'array',
-               'field' => 'fieldName',
-               'field.' => 'array',
-               'current' => 'boolean',
-               'current.' => 'array',
-               'cObject' => 'cObject',
-               'cObject.' => 'array',
-               'numRows.' => 'array',
-               'filelist' => 'dir',
-               'filelist.' => 'array',
-               'preUserFunc' => 'functionName',
-               'stdWrapOverride' => 'hook',
-               // this is a placeholder for the second Hook
-               'override' => 'string',
-               'override.' => 'array',
-               'preIfEmptyListNum' => 'listNum',
-               'preIfEmptyListNum.' => 'array',
-               'ifNull' => 'string',
-               'ifNull.' => 'array',
-               'ifEmpty' => 'string',
-               'ifEmpty.' => 'array',
-               'ifBlank' => 'string',
-               'ifBlank.' => 'array',
-               'listNum' => 'listNum',
-               'listNum.' => 'array',
-               'trim' => 'boolean',
-               'trim.' => 'array',
-               'strPad.' => 'array',
-               'stdWrap' => 'stdWrap',
-               'stdWrap.' => 'array',
-               'stdWrapProcess' => 'hook',
-               // this is a placeholder for the third Hook
-               'required' => 'boolean',
-               'required.' => 'array',
-               'if.' => 'array',
-               'fieldRequired' => 'fieldName',
-               'fieldRequired.' => 'array',
-               'csConv' => 'string',
-               'csConv.' => 'array',
-               'parseFunc' => 'objectpath',
-               'parseFunc.' => 'array',
-               'HTMLparser' => 'boolean',
-               'HTMLparser.' => 'array',
-               'split.' => 'array',
-               'replacement.' => 'array',
-               'prioriCalc' => 'boolean',
-               'prioriCalc.' => 'array',
-               'char' => 'integer',
-               'char.' => 'array',
-               'intval' => 'boolean',
-               'intval.' => 'array',
-               'hash' => 'string',
-               'hash.' => 'array',
-               'round' => 'boolean',
-               'round.' => 'array',
-               'numberFormat.' => 'array',
-               'expandList' => 'boolean',
-               'expandList.' => 'array',
-               'date' => 'dateconf',
-               'date.' => 'array',
-               'strtotime' => 'strtotimeconf',
-               'strtotime.' => 'array',
-               'strftime' => 'strftimeconf',
-               'strftime.' => 'array',
-               'age' => 'boolean',
-               'age.' => 'array',
-               'case' => 'case',
-               'case.' => 'array',
-               'bytes' => 'boolean',
-               'bytes.' => 'array',
-               'substring' => 'parameters',
-               'substring.' => 'array',
-               'removeBadHTML' => 'boolean',
-               'removeBadHTML.' => 'array',
-               'cropHTML' => 'crop',
-               'cropHTML.' => 'array',
-               'stripHtml' => 'boolean',
-               'stripHtml.' => 'array',
-               'crop' => 'crop',
-               'crop.' => 'array',
-               'rawUrlEncode' => 'boolean',
-               'rawUrlEncode.' => 'array',
-               'htmlSpecialChars' => 'boolean',
-               'htmlSpecialChars.' => 'array',
-               'encodeForJavaScriptValue' => 'boolean',
-               'encodeForJavaScriptValue.' => 'array',
-               'doubleBrTag' => 'string',
-               'doubleBrTag.' => 'array',
-               'br' => 'boolean',
-               'br.' => 'array',
-               'brTag' => 'string',
-               'brTag.' => 'array',
-               'encapsLines.' => 'array',
-               'keywords' => 'boolean',
-               'keywords.' => 'array',
-               'innerWrap' => 'wrap',
-               'innerWrap.' => 'array',
-               'innerWrap2' => 'wrap',
-               'innerWrap2.' => 'array',
-               'fontTag' => 'wrap',
-               'fontTag.' => 'array',
-               'addParams.' => 'array',
-               'textStyle.' => 'array',
-               'tableStyle.' => 'array',
-               'filelink.' => 'array',
-               'preCObject' => 'cObject',
-               'preCObject.' => 'array',
-               'postCObject' => 'cObject',
-               'postCObject.' => 'array',
-               'wrapAlign' => 'align',
-               'wrapAlign.' => 'array',
-               'typolink.' => 'array',
-               'TCAselectItem.' => 'array',
-               'space' => 'space',
-               'space.' => 'array',
-               'spaceBefore' => 'int',
-               'spaceBefore.' => 'array',
-               'spaceAfter' => 'int',
-               'spaceAfter.' => 'array',
-               'wrap' => 'wrap',
-               'wrap.' => 'array',
-               'noTrimWrap' => 'wrap',
-               'noTrimWrap.' => 'array',
-               'wrap2' => 'wrap',
-               'wrap2.' => 'array',
-               'dataWrap' => 'dataWrap',
-               'dataWrap.' => 'array',
-               'prepend' => 'cObject',
-               'prepend.' => 'array',
-               'append' => 'cObject',
-               'append.' => 'array',
-               'wrap3' => 'wrap',
-               'wrap3.' => 'array',
-               'orderedStdWrap' => 'stdWrap',
-               'orderedStdWrap.' => 'array',
-               'outerWrap' => 'wrap',
-               'outerWrap.' => 'array',
-               'insertData' => 'boolean',
-               'insertData.' => 'array',
-               'offsetWrap' => 'space',
-               'offsetWrap.' => 'array',
-               'postUserFunc' => 'functionName',
-               'postUserFuncInt' => 'functionName',
-               'prefixComment' => 'string',
-               'prefixComment.' => 'array',
-               'editIcons' => 'string',
-               'editIcons.' => 'array',
-               'editPanel' => 'boolean',
-               'editPanel.' => 'array',
-               'cacheStore' => 'hook',
-               // this is a placeholder for storing the content in cache
-               'stdWrapPostProcess' => 'hook',
-               // this is a placeholder for the last Hook
-               'debug' => 'boolean',
-               'debug.' => 'array',
-               'debugFunc' => 'boolean',
-               'debugFunc.' => 'array',
-               'debugData' => 'boolean',
-               'debugData.' => 'array'
-       );
-
-       /**
-        * Class names for accordant content object names
-        *
-        * @var array
-        */
-       protected $contentObjectClassMap = array();
-
-       /**
-        * Holds ImageMagick parameters and extensions used for compression
-        *
-        * @var array
-        * @see IMGTEXT()
-        */
-       public $image_compression = array(
-               10 => array(
-                       'params' => '',
-                       'ext' => 'gif'
-               ),
-               11 => array(
-                       'params' => '-colors 128',
-                       'ext' => 'gif'
-               ),
-               12 => array(
-                       'params' => '-colors 64',
-                       'ext' => 'gif'
-               ),
-               13 => array(
-                       'params' => '-colors 32',
-                       'ext' => 'gif'
-               ),
-               14 => array(
-                       'params' => '-colors 16',
-                       'ext' => 'gif'
-               ),
-               15 => array(
-                       'params' => '-colors 8',
-                       'ext' => 'gif'
-               ),
-               20 => array(
-                       'params' => '-quality 100',
-                       'ext' => 'jpg'
-               ),
-               21 => array(
-                       'params' => '-quality 90',
-                       'ext' => 'jpg'
-               ),
-               22 => array(
-                       'params' => '-quality 80',
-                       'ext' => 'jpg'
-               ),
-               23 => array(
-                       'params' => '-quality 70',
-                       'ext' => 'jpg'
-               ),
-               24 => array(
-                       'params' => '-quality 60',
-                       'ext' => 'jpg'
-               ),
-               25 => array(
-                       'params' => '-quality 50',
-                       'ext' => 'jpg'
-               ),
-               26 => array(
-                       'params' => '-quality 40',
-                       'ext' => 'jpg'
-               ),
-               27 => array(
-                       'params' => '-quality 30',
-                       'ext' => 'jpg'
-               ),
-               28 => array(
-                       'params' => '-quality 20',
-                       'ext' => 'jpg'
-               ),
-               30 => array(
-                       'params' => '-colors 256',
-                       'ext' => 'png'
-               ),
-               31 => array(
-                       'params' => '-colors 128',
-                       'ext' => 'png'
-               ),
-               32 => array(
-                       'params' => '-colors 64',
-                       'ext' => 'png'
-               ),
-               33 => array(
-                       'params' => '-colors 32',
-                       'ext' => 'png'
-               ),
-               34 => array(
-                       'params' => '-colors 16',
-                       'ext' => 'png'
-               ),
-               35 => array(
-                       'params' => '-colors 8',
-                       'ext' => 'png'
-               ),
-               39 => array(
-                       'params' => '',
-                       'ext' => 'png'
-               )
-       );
-
-       /**
-        * ImageMagick parameters for image effects
-        *
-        * @var array
-        * @see IMGTEXT()
-        */
-       public $image_effects = array(
-               1 => '-rotate 90',
-               2 => '-rotate 270',
-               3 => '-rotate 180',
-               10 => '-colorspace GRAY',
-               11 => '-sharpen 70',
-               20 => '-normalize',
-               23 => '-contrast',
-               25 => '-gamma 1.3',
-               26 => '-gamma 0.8'
-       );
-
-       /**
-        * Loaded with the current data-record.
-        *
-        * If the instance of this class is used to render records from the database those records are found in this array.
-        * The function stdWrap has TypoScript properties that fetch field-data from this array.
-        *
-        * @var array
-        * @see init()
-        */
-       public $data = array();
-
-       /**
-        * @var string
-        */
-       protected $table = '';
-
-       /**
-        * Used for backup...
-        *
-        * @var array
-        */
-       public $oldData = array();
-
-       /**
-        * If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
-        *
-        * @var string
-        */
-       public $alternativeData = '';
-
-       /**
-        * Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
-        *
-        * @var array
-        */
-       public $parameters = array();
-
-       /**
-        * @var string
-        */
-       public $currentValKey = 'currentValue_kidjls9dksoje';
-
-       /**
-        * This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation.
-        * Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
-        *
-        * @var string
-        */
-       public $currentRecord = '';
-
-       /**
-        * Set in RecordsContentObject and ContentContentObject to the current number of records selected in a query.
-        *
-        * @var int
-        */
-       public $currentRecordTotal = 0;
-
-       /**
-        * Incremented in RecordsContentObject and ContentContentObject before each record rendering.
-        *
-        * @var int
-        */
-       public $currentRecordNumber = 0;
-
-       /**
-        * Incremented in RecordsContentObject and ContentContentObject before each record rendering.
-        *
-        * @var int
-        */
-       public $parentRecordNumber = 0;
-
-       /**
-        * If the ContentObjectRender was started from ContentContentObject, RecordsContentObject or SearchResultContentObject this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
-        *
-        * @var array
-        */
-       public $parentRecord = array();
-
-       /**
-        * Is set to 1 if the instance of this cObj is executed from a *_INT plugin (see pagegen, bottom of document)
-        *
-        * @var bool
-        */
-       public $INT_include = 0;
-
-       /**
-        * This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request.
-        *
-        * @var array
-        */
-       public $checkPid_cache = array();
-
-       /**
-        * @var string
-        */
-       public $checkPid_badDoktypeList = '255';
-
-       /**
-        * This will be set by typoLink() to the url of the most recent link created.
-        *
-        * @var string
-        */
-       public $lastTypoLinkUrl = '';
-
-       /**
-        * DO. link target.
-        *
-        * @var string
-        */
-       public $lastTypoLinkTarget = '';
-
-       /**
-        * @var array
-        */
-       public $lastTypoLinkLD = array();
-
-       /**
-        * Caching substituteMarkerArrayCached function
-        *
-        * @var array
-        */
-       public $substMarkerCache = array();
-
-       /**
-        * array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
-        *
-        * @var array
-        */
-       public $recordRegister = array();
-
-       /**
-        * Additionally registered content object types and class names
-        *
-        * @var array
-        */
-       protected $cObjHookObjectsRegistry = array();
-
-       /**
-        * @var array
-        */
-       public $cObjHookObjectsArr = array();
-
-       /**
-        * Containing hook objects for stdWrap
-        *
-        * @var array
-        */
-       protected $stdWrapHookObjects = array();
-
-       /**
-        * Containing hook objects for getImgResource
-        *
-        * @var array
-        */
-       protected $getImgResourceHookObjects;
-
-       /**
-        * @var File Current file objects (during iterations over files)
-        */
-       protected $currentFile = NULL;
-
-       /**
-        * Set to TRUE by doConvertToUserIntObject() if USER object wants to become USER_INT
-        */
-       public $doConvertToUserIntObject = FALSE;
-
-       /**
-        * Indicates current object type. Can hold one of OBJECTTYPE_ constants or FALSE.
-        * The value is set and reset inside USER() function. Any time outside of
-        * USER() it is FALSE.
-        */
-       protected $userObjectType = FALSE;
-
-       /**
-        * @var array
-        */
-       protected $stopRendering = array();
-
-       /**
-        * @var int
-        */
-       protected $stdWrapRecursionLevel = 0;
-
-       /**
-        * @var TypoScriptFrontendController
-        */
-       protected $typoScriptFrontendController;
-
-       /**
-        * Indicates that object type is USER.
-        *
-        * @see ContentObjectRender::$userObjectType
-        */
-       const OBJECTTYPE_USER_INT = 1;
-       /**
-        * Indicates that object type is USER.
-        *
-        * @see ContentObjectRender::$userObjectType
-        */
-       const OBJECTTYPE_USER = 2;
-
-       /**
-        * @param TypoScriptFrontendController $typoScriptFrontendController
-        */
-       public function __construct(TypoScriptFrontendController $typoScriptFrontendController = NULL) {
-               $this->typoScriptFrontendController = $typoScriptFrontendController ?: $GLOBALS['TSFE'];
-               $this->contentObjectClassMap = $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'];
-       }
-
-       /**
-        * Prevent several objects from being serialized.
-        * If currentFile is set, it is either a File or a FileReference object. As the object itself can't be serialized,
-        * we have store a hash and restore the object in __wakeup()
-        *
-        * @return array
-        */
-       public function __sleep() {
-               $vars = get_object_vars($this);
-               unset($vars['typoScriptFrontendController']);
-               if ($this->currentFile instanceof FileReference) {
-                       $this->currentFile = 'FileReference:' . $this->currentFile->getUid();
-               } elseif ($this->currentFile instanceof File) {
-                       $this->currentFile = 'File:' . $this->currentFile->getIdentifier();
-               } else {
-                       unset($vars['currentFile']);
-               }
-               return array_keys($vars);
-       }
-
-       /**
-        * Restore currentFile from hash.
-        * If currentFile references a File, the identifier equals file identifier.
-        * If it references a FileReference the identifier equals the uid of the reference.
-        */
-       public function __wakeup() {
-               if (isset($GLOBALS['TSFE'])) {
-                       $this->typoScriptFrontendController = $GLOBALS['TSFE'];
-               }
-               if ($this->currentFile !== NULL && is_string($this->currentFile)) {
-                       list($objectType, $identifier) = explode(':', $this->currentFile, 2);
-                       try {
-                               if ($objectType === 'File') {
-                                       $this->currentFile = ResourceFactory::getInstance()->retrieveFileOrFolderObject($identifier);
-                               } elseif ($objectType === 'FileReference') {
-                                       $this->currentFile = ResourceFactory::getInstance()->getFileReferenceObject($identifier);
-                               }
-                       } catch (ResourceDoesNotExistException $e) {
-                               $this->currentFile = NULL;
-                       }
-               }
-       }
-
-       /**
-        * Allow injecting content object class map.
-        *
-        * This method is private API, please use configuration
-        * $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] to add new content objects
-        *
-        * @internal
-        * @param array $contentObjectClassMap
-        */
-       public function setContentObjectClassMap(array $contentObjectClassMap) {
-               $this->contentObjectClassMap = $contentObjectClassMap;
-       }
-
-       /**
-        * Register a single content object name to class name
-        *
-        * This method is private API, please use configuration
-        * $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] to add new content objects
-        *
-        * @internal
-        * @param string $className
-        * @param string $contentObjectName
-        */
-       public function registerContentObjectClass($className, $contentObjectName) {
-               $this->contentObjectClassMap[$contentObjectName] = $className;
-       }
-
-       /**
-        * Class constructor.
-        * Well, it has to be called manually since it is not a real constructor function.
-        * So after making an instance of the class, call this function and pass to it a database record and the tablename from where the record is from. That will then become the "current" record loaded into memory and accessed by the .fields property found in eg. stdWrap.
-        *
-        * @param array $data The record data that is rendered.
-        * @param string $table The table that the data record is from.
-        * @return void
-        */
-       public function start($data, $table = '') {
-               $this->data = $data;
-               $this->table = $table;
-               $this->currentRecord = $table ? $table . ':' . $this->data['uid'] : '';
-               $this->parameters = array();
-               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
-                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
-                               $this->cObjHookObjectsRegistry[$classArr[0]] = $classArr[1];
-                       }
-               }
-               $this->stdWrapHookObjects = array();
-               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
-                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
-                               $hookObject = GeneralUtility::getUserObj($classData);
-                               if (!$hookObject instanceof ContentObjectStdWrapHookInterface) {
-                                       throw new \UnexpectedValueException($classData . ' must implement interface ' . ContentObjectStdWrapHookInterface::class, 1195043965);
-                               }
-                               $this->stdWrapHookObjects[] = $hookObject;
-                       }
-               }
-               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
-                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
-                               $postInitializationProcessor = GeneralUtility::getUserObj($classData);
-                               if (!$postInitializationProcessor instanceof ContentObjectPostInitHookInterface) {
-                                       throw new \UnexpectedValueException($classData . ' must implement interface ' . ContentObjectPostInitHookInterface::class, 1274563549);
-                               }
-                               $postInitializationProcessor->postProcessContentObjectInitialization($this);
-                       }
-               }
-       }
-
-       /**
-        * Returns the current table
-        *
-        * @return string
-        */
-       public function getCurrentTable() {
-               return $this->table;
-       }
-
-       /**
-        * Gets the 'getImgResource' hook objects.
-        * The first call initializes the accordant objects.
-        *
-        * @return array The 'getImgResource' hook objects (if any)
-        */
-       protected function getGetImgResourceHookObjects() {
-               if (!isset($this->getImgResourceHookObjects)) {
-                       $this->getImgResourceHookObjects = array();
-                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
-                               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
-                                       $hookObject = GeneralUtility::getUserObj($classData);
-                                       if (!$hookObject instanceof ContentObjectGetImageResourceHookInterface) {
-                                               throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetImageResourceHookInterface::class, 1218636383);
-                                       }
-                                       $this->getImgResourceHookObjects[] = $hookObject;
-                               }
-                       }
-               }
-               return $this->getImgResourceHookObjects;
-       }
-
-       /**
-        * Sets the internal variable parentRecord with information about current record.
-        * If the ContentObjectRender was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
-        *
-        * @param array $data The record array
-        * @param string $currentRecord This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
-        * @return void
-        * @access private
-        */
-       public function setParent($data, $currentRecord) {
-               $this->parentRecord = array(
-                       'data' => $data,
-                       'currentRecord' => $currentRecord
-               );
-       }
-
-       /***********************************************
-        *
-        * CONTENT_OBJ:
-        *
-        ***********************************************/
-       /**
-        * Returns the "current" value.
-        * The "current" value is just an internal variable that can be used by functions to pass a single value on to another function later in the TypoScript processing.
-        * It's like "load accumulator" in the good old C64 days... basically a "register" you can use as you like.
-        * The TSref will tell if functions are setting this value before calling some other object so that you know if it holds any special information.
-        *
-        * @return mixed The "current" value
-        */
-       public function getCurrentVal() {
-               return $this->data[$this->currentValKey];
-       }
-
-       /**
-        * Sets the "current" value.
-        *
-        * @param mixed $value The variable that you want to set as "current
-        * @return void
-        * @see getCurrentVal()
-        */
-       public function setCurrentVal($value) {
-               $this->data[$this->currentValKey] = $value;
-       }
-
-       /**
-        * Rendering of a "numerical array" of cObjects from TypoScript
-        * Will call ->cObjGetSingle() for each cObject found and accumulate the output.
-        *
-        * @param array $setup array with cObjects as values.
-        * @param string $addKey A prefix for the debugging information
-        * @return string Rendered output from the cObjects in the array.
-        * @see cObjGetSingle()
-        */
-       public function cObjGet($setup, $addKey = '') {
-               if (is_array($setup)) {
-                       $sKeyArray = TemplateService::sortedKeyList($setup);
-                       $content = '';
-                       foreach ($sKeyArray as $theKey) {
-                               $theValue = $setup[$theKey];
-                               if ((int)$theKey && strpos($theKey, '.') === FALSE) {
-                                       $conf = $setup[$theKey . '.'];
-                                       $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey);
-                               }
-                       }
-                       return $content;
-               }
-       }
-
-       /**
-        * Renders a content object
-        *
-        * @param string $name The content object name, eg. "TEXT" or "USER" or "IMAGE
-        * @param array $conf The array with TypoScript properties for the content object
-        * @param string $TSkey A string label used for the internal debugging tracking.
-        * @return string cObject output
-        * @throws \UnexpectedValueException
-        */
-       public function cObjGetSingle($name, $conf, $TSkey = '__') {
-               $content = '';
-               // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
-               $GLOBALS['TSFE']->cObjectDepthCounter--;
-               if ($GLOBALS['TSFE']->cObjectDepthCounter > 0) {
-                       $name = trim($name);
-                       if ($GLOBALS['TT']->LR) {
-                               $GLOBALS['TT']->push($TSkey, $name);
-                       }
-                       // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
-                       if ($name[0] === '<') {
-                               $key = trim(substr($name, 1));
-                               $cF = GeneralUtility::makeInstance(TypoScriptParser::class);
-                               // $name and $conf is loaded with the referenced values.
-                               $confOverride = is_array($conf) ? $conf : array();
-                               list($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
-                               $conf = array_replace_recursive(is_array($conf) ? $conf : array(), $confOverride);
-                               // Getting the cObject
-                               $GLOBALS['TT']->incStackPointer();
-                               $content .= $this->cObjGetSingle($name, $conf, $key);
-                               $GLOBALS['TT']->decStackPointer();
-                       } else {
-                               $hooked = FALSE;
-                               // Application defined cObjects
-                               if (!empty($this->cObjHookObjectsRegistry[$name])) {
-                                       if (empty($this->cObjHookObjectsArr[$name])) {
-                                               $this->cObjHookObjectsArr[$name] = GeneralUtility::getUserObj($this->cObjHookObjectsRegistry[$name]);
-                                       }
-                                       $hookObj = $this->cObjHookObjectsArr[$name];
-                                       if (method_exists($hookObj, 'cObjGetSingleExt')) {
-                                               $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
-                                               $hooked = TRUE;
-                                       }
-                               }
-                               if (!$hooked) {
-                                       $contentObject = $this->getContentObject($name);
-                                       if ($contentObject) {
-                                               $content .= $this->render($contentObject, $conf);
-                                       } else {
-                                               // Call hook functions for extra processing
-                                               if ($name && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
-                                                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
-                                                               $hookObject = GeneralUtility::getUserObj($classData);
-                                                               if (!$hookObject instanceof ContentObjectGetSingleHookInterface) {
-                                                                       throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetSingleHookInterface::class, 1195043731);
-                                                               }
-                                                               /** @var $hookObject ContentObjectGetSingleHookInterface */
-                                                               $content .= $hookObject->getSingleContentObject($name, (array)$conf, $TSkey, $this);
-                                                       }
-                                               } else {
-                                                       // Log error in AdminPanel
-                                                       $warning = sprintf('Content Object "%s" does not exist', $name);
-                                                       $GLOBALS['TT']->setTSlogMessage($warning, 2);
-                                               }
-                                       }
-                               }
-                       }
-                       if ($GLOBALS['TT']->LR) {
-                               $GLOBALS['TT']->pull($content);
-                       }
-               }
-               // Increasing on exit...
-               $GLOBALS['TSFE']->cObjectDepthCounter++;
-               return $content;
-       }
-
-       /**
-        * Returns a new content object of type $name.
-        * This content object needs to be registered as content object
-        * in $this->contentObjectClassMap
-        *
-        * @param string $name
-        * @return NULL|AbstractContentObject
-        * @throws ContentRenderingException
-        */
-       public function getContentObject($name) {
-               if (!isset($this->contentObjectClassMap[$name])) {
-                       return NULL;
-               }
-               $fullyQualifiedClassName = $this->contentObjectClassMap[$name];
-               $contentObject = GeneralUtility::makeInstance($fullyQualifiedClassName, $this);
-               if (!($contentObject instanceof AbstractContentObject)) {
-                       throw new ContentRenderingException(sprintf('Registered content object class name "%" must be an instance of AbstractContentObject, but is not!', $fullyQualifiedClassName), 1422564295);
-               }
-               return $contentObject;
-       }
-
-       /********************************************
-        *
-        * Functions rendering content objects (cObjects)
-        *
-        ********************************************/
-
-       /**
-        * Renders a content object by taking exception handling into consideration
-        *
-        * @param AbstractContentObject $contentObject Content object instance
-        * @param array $configuration Array of TypoScript properties
-        *
-        * @throws ContentRenderingException
-        * @throws \Exception
-        * @return string
-        */
-       public function render(AbstractContentObject $contentObject, $configuration = array()) {
-               $content = '';
-               try {
-                       $content .= $contentObject->render($configuration);
-               } catch (ContentRenderingException $exception) {
-                       // Content rendering Exceptions indicate a critical problem which should not be
-                       // caught e.g. when something went wrong with Exception handling itself
-                       throw $exception;
-               } catch (\Exception $exception) {
-                       $exceptionHandler = $this->createExceptionHandler($configuration);
-                       if ($exceptionHandler === NULL) {
-                               throw $exception;
-                       } else {
-                               $content = $exceptionHandler->handle($exception, $contentObject, $configuration);
-                       }
-               }
-               return $content;
-       }
-
-       /**
-        * Creates the content object exception handler from local content object configuration
-        * or, from global configuration if not explicitly disabled in local configuration
-        *
-        * @param array $configuration
-        * @return NULL|ExceptionHandlerInterface
-        * @throws ContentRenderingException
-        */
-       protected function createExceptionHandler($configuration = array()) {
-               $exceptionHandler = NULL;
-               $exceptionHandlerClassName = $this->determineExceptionHandlerClassName($configuration);
-               if (!empty($exceptionHandlerClassName)) {
-                       $exceptionHandler = GeneralUtility::makeInstance($exceptionHandlerClassName, $this->mergeExceptionHandlerConfiguration($configuration));
-                       if (!$exceptionHandler instanceof ExceptionHandlerInterface) {
-                               throw new ContentRenderingException('An exception handler was configured but the class does not exist or does not implement the ExceptionHandlerInterface', 1403653369);
-                       }
-               }
-
-               return $exceptionHandler;
-       }
-
-       /**
-        * Determine exception handler class name from global and content object configuration
-        *
-        * @param array $configuration
-        * @return string|NULL
-        */
-       protected function determineExceptionHandlerClassName($configuration) {
-               $exceptionHandlerClassName = NULL;
-               if (!isset($this->typoScriptFrontendController->config['config']['contentObjectExceptionHandler'])) {
-                       if (GeneralUtility::getApplicationContext()->isProduction()) {
-                               $exceptionHandlerClassName = '1';
-                       }
-               } else {
-                       $exceptionHandlerClassName = $this->typoScriptFrontendController->config['config']['contentObjectExceptionHandler'];
-               }
-
-               if (isset($configuration['exceptionHandler'])) {
-                       $exceptionHandlerClassName = $configuration['exceptionHandler'];
-               }
-
-               if ($exceptionHandlerClassName === '1') {
-                       $exceptionHandlerClassName = ProductionExceptionHandler::class;
-               }
-
-               return $exceptionHandlerClassName;
-       }
-
-       /**
-        * Merges global exception handler configuration with the one from the content object
-        * and returns the merged exception handler configuration
-        *
-        * @param array $configuration
-        * @return array
-        */
-       protected function mergeExceptionHandlerConfiguration($configuration) {
-               $exceptionHandlerConfiguration = array();
-               if (!empty($this->typoScriptFrontendController->config['config']['contentObjectExceptionHandler.'])) {
-                       $exceptionHandlerConfiguration = $this->typoScriptFrontendController->config['config']['contentObjectExceptionHandler.'];
-               }
-               if (!empty($configuration['exceptionHandler.'])) {
-                       $exceptionHandlerConfiguration = array_replace_recursive($exceptionHandlerConfiguration, $configuration['exceptionHandler.']);
-               }
-
-               return $exceptionHandlerConfiguration;
-       }
-       /**
-        * Rendering the cObject, FLOWPLAYER
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('FLOWPLAYER', $conf) instead
-        */
-       public function FLOWPLAYER($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('FLOWPLAYER'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, TEXT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('TEXT', $conf) instead
-        */
-       public function TEXT($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('TEXT'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, CLEARGIF
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('CLEARGIF', $conf) instead
-        */
-       public function CLEARGIF($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('CLEARGIF'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, COBJ_ARRAY / COA and COBJ_ARRAY_INT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @param string $ext If "INT" then the cObject is a "COBJ_ARRAY_INT" (non-cached), otherwise just "COBJ_ARRAY" (cached)
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('COA', $conf) or $cObj->cObjGetSingle('COA_INT', $conf) instead
-        */
-       public function COBJ_ARRAY($conf, $ext = '') {
-               GeneralUtility::logDeprecatedFunction();
-               if ($ext === 'INT') {
-                       return $this->render($this->getContentObject('COA_INT'), $conf);
-               } else {
-                       return $this->render($this->getContentObject('COA'), $conf);
-               }
-       }
-
-       /**
-        * Rendering the cObject, USER and USER_INT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @param string $ext If "INT" then the cObject is a "USER_INT" (non-cached), otherwise just "USER" (cached)
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('USER', $conf) or $cObj->cObjGetSingle('USER_INT', $conf) instead
-        */
-       public function USER($conf, $ext = '') {
-               GeneralUtility::logDeprecatedFunction();
-               if ($ext === 'INT') {
-                       return $this->render($this->getContentObject('USER_INT'), $conf);
-               } else {
-                       return $this->render($this->getContentObject('USER'), $conf);
-               }
-       }
-
-       /**
-        * Retrieves a type of object called as USER or USER_INT. Object can detect their
-        * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the
-        * current object execution. In all other cases it will return FALSE to indicate
-        * a call out of context.
-        *
-        * @return mixed One of OBJECTTYPE_ class constants or FALSE
-        */
-       public function getUserObjectType() {
-               return $this->userObjectType;
-       }
-
-       /**
-        * Sets the user object type
-        *
-        * @param mixed $userObjectType
-        * @return void
-        */
-       public function setUserObjectType($userObjectType) {
-               $this->userObjectType = $userObjectType;
-       }
-
-       /**
-        * Requests the current USER object to be converted to USER_INT.
-        *
-        * @return void
-        */
-       public function convertToUserIntObject() {
-               if ($this->userObjectType !== self::OBJECTTYPE_USER) {
-                       $GLOBALS['TT']->setTSlogMessage(ContentObjectRenderer::class . '::convertToUserIntObject() is called in the wrong context or for the wrong object type', 2);
-               } else {
-                       $this->doConvertToUserIntObject = TRUE;
-               }
-       }
-
-       /**
-        * Rendering the cObject, FILE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('FILE', $conf) instead
-        */
-       public function FILE($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('FILE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, FILES
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('FILES', $conf) instead
-        */
-       public function FILES($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('FILES'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, IMAGE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @see cImage()
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('IMAGE', $conf) instead
-        */
-       public function IMAGE($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('IMAGE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, IMG_RESOURCE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @see getImgResource()
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('IMG_RESOURCE', $conf) instead
-        */
-       public function IMG_RESOURCE($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('IMG_RESOURCE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, IMGTEXT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('IMGTEXT', $conf) instead
-        */
-       public function IMGTEXT($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('IMGTEXT'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, CONTENT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('CONTENT', $conf) instead
-        */
-       public function CONTENT($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('CONTENT'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, RECORDS
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('RECORDS', $conf) instead
-        */
-       public function RECORDS($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('RECORDS'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, HMENU
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('HMENU', $conf) instead
-        */
-       public function HMENU($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('HMENU'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, CTABLE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('CTABLE', $conf) instead
-        */
-       public function CTABLE($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('CTABLE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, OTABLE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('OTABLE', $conf) instead
-        */
-       public function OTABLE($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('OTABLE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, COLUMNS
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('COLUMNS', $conf) instead
-        */
-       public function COLUMNS($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('COLUMNS'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, HRULER
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('HRULER', $conf) instead
-        */
-       public function HRULER($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('HRULER'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, CASE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('CASE', $conf) instead
-        */
-       public function CASEFUNC($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('CASE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, LOAD_REGISTER and 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
-        * @param string $name If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER"
-        * @return string Empty string (the cObject only sets internal data!)
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('LOAD_REGISTER', $conf) and $cObj->cObjGetSingle('RESTORE_REGISTER', $conf) instead
-        */
-       public function LOAD_REGISTER($conf, $name) {
-               GeneralUtility::logDeprecatedFunction();
-               if ($name === 'RESTORE_REGISTER') {
-                       return $this->render($this->getContentObject('RESTORE_REGISTER'), $conf);
-               } else {
-                       return $this->render($this->getContentObject('LOAD_REGISTER'), $conf);
-               }
-       }
-
-       /**
-        * Rendering the cObject, FORM
-        *
-        * @param array $conf Array of TypoScript properties
-        * @param array $formData Alternative formdata overriding whatever comes from TypoScript
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('FORM', $conf) instead
-        */
-       public function FORM($conf, $formData = '') {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('FORM'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, SEARCHRESULT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('SEARCHRESULT', $conf) instead
-        */
-       public function SEARCHRESULT($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('SEARCHRESULT'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, TEMPLATE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @see substituteMarkerArrayCached()
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('TEMPLATE', $conf) instead
-        */
-       public function TEMPLATE($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('TEMPLATE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, FLUIDTEMPLATE
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string the HTML output
-        * @author Steffen Ritter <info@steffen-ritter.net>
-        * @author Benjamin Mack <benni@typo3.org>
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('FLUIDTEMPLATE', $conf) instead
-        */
-       protected function FLUIDTEMPLATE(array $conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('FLUIDTEMPLATE'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, MULTIMEDIA
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('MULTIMEDIA', $conf) instead
-        */
-       public function MULTIMEDIA($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('MULTIMEDIA'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, MEDIA
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('MEDIA', $conf) instead
-        */
-       public function MEDIA($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('MEDIA'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, SWFOBJECT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('SWFOBJECT', $conf) instead
-        */
-       public function SWFOBJECT($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('SWFOBJECT'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, QTOBJECT
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('QTOBJECT', $conf) instead
-        */
-       public function QTOBJECT($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('QTOBJECT'), $conf);
-       }
-
-       /**
-        * Rendering the cObject, SVG
-        *
-        * @param array $conf Array of TypoScript properties
-        * @return string Output
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8, use $cObj->cObjGetSingle('SVG', $conf) instead
-        */
-       public function SVG($conf) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->render($this->getContentObject('SVG'), $conf);
-       }
-
-       /************************************
-        *
-        * Various helper functions for content objects:
-        *
-        ************************************/
-       /**
-        * Converts a given config in Flexform to a conf-array
-        *
-        * @param string|array $flexData Flexform data
-        * @param array $conf Array to write the data into, by reference
-        * @param bool $recursive Is set if called recursive. Don't call function with this parameter, it's used inside the function only
-        * @return void
-        */
-       public function readFlexformIntoConf($flexData, &$conf, $recursive = FALSE) {
-               if ($recursive === FALSE && is_string($flexData)) {
-                       $flexData = GeneralUtility::xml2array($flexData, 'T3');
-               }
-               if (is_array($flexData) && isset($flexData['data']['sDEF']['lDEF'])) {
-                       $flexData = $flexData['data']['sDEF']['lDEF'];
-               }
-               if (!is_array($flexData)) {
-                       return;
-               }
-               foreach ($flexData as $key => $value) {
-                       if (!is_array($value)) {
-                               continue;
-                       }
-                       if (isset($value['el'])) {
-                               if (is_array($value['el']) && count($value['el']) > 0) {
-                                       foreach ($value['el'] as $ekey => $element) {
-                                               if (isset($element['vDEF'])) {
-                                                       $conf[$ekey] = $element['vDEF'];
-                                               } else {
-                                                       if (is_array($element)) {
-                                                               $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
-                                                       } else {
-                                                               $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
-                                                       }
-                                               }
-                                       }
-                               } else {
-                                       $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
-                               }
-                       }
-                       if (isset($value['vDEF'])) {
-                               $conf[$key] = $value['vDEF'];
-                       }
-               }
-       }
-
-       /**
-        * Returns all parents of the given PID (Page UID) list
-        *
-        * @param string $pidList A list of page Content-Element PIDs (Page UIDs) / stdWrap
-        * @param array $pidConf stdWrap array for the list
-        * @return string A list of PIDs
-        * @access private
-        */
-       public function getSlidePids($pidList, $pidConf) {
-               $pidList = isset($pidConf) ? trim($this->stdWrap($pidList, $pidConf)) : trim($pidList);
-               if ($pidList === '') {
-                       $pidList = 'this';
-               }
-               if (trim($pidList)) {
-                       $listArr = GeneralUtility::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $pidList));
-                       $listArr = $this->checkPidArray($listArr);
-               }
-               $pidList = array();
-               if (is_array($listArr) && count($listArr)) {
-                       foreach ($listArr as $uid) {
-                               $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
-                               if (!$page['is_siteroot']) {
-                                       $pidList[] = $page['pid'];
-                               }
-                       }
-               }
-               return implode(',', $pidList);
-       }
-
-       /**
-        * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
-        * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript.
-        * This function is called by "$this->cImage($conf['file'], $conf);" from IMAGE().
-        *
-        * @param string $file File TypoScript resource
-        * @param array $conf TypoScript configuration properties
-        * @return string <img> tag, (possibly wrapped in links and other HTML) if any image found.
-        * @access private
-        * @see IMAGE()
-        */
-       public function cImage($file, $conf) {
-               $info = $this->getImgResource($file, $conf['file.']);
-               $GLOBALS['TSFE']->lastImageInfo = $info;
-               if (!is_array($info)) {
-                       return '';
-               }
-               if (is_file(PATH_site . $info['3'])) {
-                       $source = $GLOBALS['TSFE']->absRefPrefix . GeneralUtility::rawUrlEncodeFP($info['3']);
-               } else {
-                       $source = $info[3];
-               }
-
-               $layoutKey = $this->stdWrap($conf['layoutKey'], $conf['layoutKey.']);
-               $imageTagTemplate = $this->getImageTagTemplate($layoutKey, $conf);
-               $sourceCollection = $this->getImageSourceCollection($layoutKey, $conf, $file);
-
-               // This array is used to collect the image-refs on the page...
-               $GLOBALS['TSFE']->imagesOnPage[] = $source;
-               $altParam = $this->getAltParam($conf);
-               $params = $this->stdWrapValue('params', $conf);
-               if ($params !== '' && $params{0} !== ' ') {
-                       $params = ' ' . $params;
-               }
-
-               $imageTagValues = array(
-                       'width' =>  $info[0],
-                       'height' => $info[1],
-                       'src' => htmlspecialchars($source),
-                       'params' => $params,
-                       'altParams' => $altParam,
-                       'border' =>  $this->getBorderAttr(' border="' . (int)$conf['border'] . '"'),
-                       'sourceCollection' => $sourceCollection,
-                       'selfClosingTagSlash' => (!empty($GLOBALS['TSFE']->xhtmlDoctype) ? ' /' : ''),
-               );
-
-               $theValue = $this->substituteMarkerArray($imageTagTemplate, $imageTagValues, '###|###', TRUE, TRUE);
-
-               $linkWrap = isset($conf['linkWrap.']) ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.']) : $conf['linkWrap'];
-               if ($linkWrap) {
-                       $theValue = $this->linkWrap($theValue, $linkWrap);
-               } elseif ($conf['imageLinkWrap']) {
-                       $originalFile = !empty($info['originalFile']) ? $info['originalFile'] : $info['origFile'];
-                       $theValue = $this->imageLinkWrap($theValue, $originalFile, $conf['imageLinkWrap.']);
-               }
-               $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
-               if ($wrap) {
-                       $theValue = $this->wrap($theValue, $conf['wrap']);
-               }
-               return $theValue;
-       }
-
-       /**
-        * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict, xhtml_11, xhtml_2 or html5
-        * or if the config parameter 'disableImgBorderAttr' is not set.
-        *
-        * @param string $borderAttr The border attribute
-        * @return string The border attribute
-        */
-       public function getBorderAttr($borderAttr) {
-               if (!GeneralUtility::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype) && $GLOBALS['TSFE']->config['config']['doctype'] != 'html5' && !$GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) {
-                       return $borderAttr;
-               }
-       }
-
-       /**
-        * Returns the html-template for rendering the image-Tag if no template is defined via typoscript the
-        * default <img> tag template is returned
-        *
-        * @param string $layoutKey rendering key
-        * @param array $conf TypoScript configuration properties
-        * @return string
-        */
-       public function getImageTagTemplate($layoutKey, $conf) {
-               if ($layoutKey && isset($conf['layout.']) && isset($conf['layout.'][$layoutKey . '.'])) {
-                       $imageTagLayout = $this->stdWrap($conf['layout.'][$layoutKey . '.']['element'], $conf['layout.'][$layoutKey . '.']['element.']);
-               } else {
-                       $imageTagLayout = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
-               }
-               return $imageTagLayout;
-       }
-
-       /**
-        * Render alternate sources for the image tag. If no source collection is given an empty string is returned.
-        *
-        * @param string $layoutKey rendering key
-        * @param array $conf TypoScript configuration properties
-        * @param string $file
-        * @throws \UnexpectedValueException
-        * @return string
-        */
-       public function getImageSourceCollection($layoutKey, $conf, $file) {
-               $sourceCollection = '';
-               if ($layoutKey && $conf['sourceCollection.'] && ($conf['layout.'][$layoutKey . '.']['source'] || $conf['layout.'][$layoutKey . '.']['source.'])) {
-
-                       // find active sourceCollection
-                       $activeSourceCollections = array();
-                       foreach ($conf['sourceCollection.'] as $sourceCollectionKey => $sourceCollectionConfiguration) {
-                               if (substr($sourceCollectionKey, -1) == '.') {
-                                       if (empty($sourceCollectionConfiguration['if.']) || $this->checkIf($sourceCollectionConfiguration['if.'])) {
-                                               $activeSourceCollections[] = $sourceCollectionConfiguration;
-                                       }
-                               }
-                       }
-
-                       // apply option split to configurations
-                       $srcLayoutOptionSplitted = $GLOBALS['TSFE']->tmpl->splitConfArray($conf['layout.'][$layoutKey . '.'], count($activeSourceCollections));
-
-                       // render sources
-                       foreach ($activeSourceCollections as $key => $sourceConfiguration) {
-                               $sourceLayout = $this->stdWrap($srcLayoutOptionSplitted[$key]['source'], $srcLayoutOptionSplitted[$key]['source.']);
-
-                               $sourceRenderConfiguration = array (
-                                       'file' => $file,
-                                       'file.' => $conf['file.']
-                               );
-
-                               if (isset($sourceConfiguration['pixelDensity'])) {
-                                       $pixelDensity = (int)$this->stdWrap($sourceConfiguration['pixelDensity'], $sourceConfiguration['pixelDensity.']);
-                               } else {
-                                       $pixelDensity = 1;
-                               }
-                               $dimensionKeys = array('width', 'height', 'maxW', 'minW', 'maxH', 'minH');
-                               foreach ($dimensionKeys as $dimensionKey) {
-                                       $dimension = $this->stdWrap($sourceConfiguration[$dimensionKey], $sourceConfiguration[$dimensionKey . '.']);
-                                       if (!$dimension) {
-                                               $dimension = $this->stdWrap($conf['file.'][$dimensionKey], $conf['file.'][$dimensionKey . '.']);
-                                       }
-                                       if ($dimension) {
-                                               if (strstr($dimension, 'c') !== FALSE && ($dimensionKey === 'width' || $dimensionKey === 'height')) {
-                                                       $dimensionParts = explode('c', $dimension, 2);
-                                                       $dimension = (int)($dimensionParts[0] * $pixelDensity) . 'c';
-                                                       if ($dimensionParts[1]) {
-                                                               $dimension .= $dimensionParts[1];
-                                                       }
-                                               } else {
-                                                       $dimension = (int)($dimension * $pixelDensity);
-                                               }
-                                               $sourceRenderConfiguration['file.'][$dimensionKey] = $dimension;
-                                               // Remove the stdWrap properties for dimension as they have been processed already above.
-                                               unset($sourceRenderConfiguration['file.'][$dimensionKey . '.']);
-                                       }
-                               }
-                               $sourceInfo = $this->getImgResource($sourceRenderConfiguration['file'], $sourceRenderConfiguration['file.']);
-                               if ($sourceInfo) {
-                                       $sourceConfiguration['width'] = $sourceInfo[0];
-                                       $sourceConfiguration['height'] = $sourceInfo[1];
-                                       $sourceConfiguration['src'] = htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . $sourceInfo[3]);
-                                       $sourceConfiguration['selfClosingTagSlash'] = (!empty($GLOBALS['TSFE']->xhtmlDoctype) ? ' /' : '');
-
-                                       $oneSourceCollection = $this->substituteMarkerArray($sourceLayout, $sourceConfiguration, '###|###', TRUE, TRUE);
-
-                                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'])) {
-                                               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'] as $classData) {
-                                                       $hookObject = GeneralUtility::getUserObj($classData);
-                                                       if (!$hookObject instanceof ContentObjectOneSourceCollectionHookInterface) {
-                                                               throw new \UnexpectedValueException(
-                                                                       '$hookObject must implement interface ' . ContentObjectOneSourceCollectionHookInterface::class,
-                                                                       1380007853
-                                                               );
-                                                       }
-                                                       $oneSourceCollection = $hookObject->getOneSourceCollection((array)$sourceRenderConfiguration, (array)$sourceConfiguration, $oneSourceCollection, $this);
-                                               }
-                                       }
-
-                                       $sourceCollection .= $oneSourceCollection;
-                               }
-                       }
-               }
-               return $sourceCollection;
-       }
-
-       /**
-        * Wraps the input string in link-tags that opens the image in a new window.
-        *
-        * @param string $string String to wrap, probably an <img> tag
-        * @param string|File|FileReference $imageFile The original image file
-        * @param array $conf TypoScript properties for the "imageLinkWrap" function
-        * @return string The input string, $string, wrapped as configured.
-        * @see cImage()
-        */
-       public function imageLinkWrap($string, $imageFile, $conf) {
-               $a1 = '';
-               $a2 = '';
-               $content = $string;
-               $enable = isset($conf['enable.']) ? $this->stdWrap($conf['enable'], $conf['enable.']) : $conf['enable'];
-               if ($enable) {
-                       $content = $this->typolink($string, $conf['typolink.']);
-                       if (isset($conf['file.'])) {
-                               $imageFile = $this->stdWrap($imageFile, $conf['file.']);
-                       }
-
-                       if ($imageFile instanceof File) {
-                               $file = $imageFile;
-                       } elseif ($imageFile instanceof FileReference) {
-                               $file = $imageFile->getOriginalFile();
-                       } else {
-                               if (MathUtility::canBeInterpretedAsInteger($imageFile)) {
-                                       $file = ResourceFactory::getInstance()->getFileObject((int)$imageFile);
-                               } else {
-                                       $file = ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($imageFile);
-                               }
-                       }
-
-                       // Create imageFileLink if not created with typolink
-                       if ($content == $string) {
-                               $parameterNames = array('width', 'height', 'effects', 'bodyTag', 'title', 'wrap');
-                               $parameters = array();
-                               $sample = isset($conf['sample.']) ? $this->stdWrap($conf['sample'], $conf['sample.']) : $conf['sample'];
-                               if ($sample) {
-                                       $parameters['sample'] = 1;
-                               }
-                               foreach ($parameterNames as $parameterName) {
-                                       if (isset($conf[$parameterName . '.'])) {
-                                               $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName . '.']);
-                                       }
-                                       if (isset($conf[$parameterName]) && $conf[$parameterName]) {
-                                               $parameters[$parameterName] = $conf[$parameterName];
-                                       }
-                               }
-                               $parametersEncoded = base64_encode(serialize($parameters));
-                               $hmac = GeneralUtility::hmac(implode('|', array($file->getUid(), $parametersEncoded)));
-                               $params = '&md5=' . $hmac;
-                               foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
-                                       $params .= '&parameters' . rawurlencode('[') . $index . rawurlencode(']') . '=' . rawurlencode($chunk);
-                               }
-                               $url = $GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . $file->getUid() . $params;
-                               $directImageLink = isset($conf['directImageLink.']) ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.']) : $conf['directImageLink'];
-                               if ($directImageLink) {
-                                       $imgResourceConf = array(
-                                               'file' => $imageFile,
-                                               'file.' => $conf
-                                       );
-                                       $url = $this->cObjGetSingle('IMG_RESOURCE', $imgResourceConf);
-                                       if (!$url) {
-                                               // If no imagemagick / gm is available
-                                               $url = $imageFile;
-                                       }
-                               }
-                               // Create TARGET-attribute only if the right doctype is used
-                               if (!GeneralUtility::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
-                                       $target = isset($conf['target.']) ? $this->stdWrap($conf['target'], $conf['target.']) : $conf['target'];
-                                       if ($target) {
-                                               $target = sprintf(' target="%s"', $target);
-                                       } else {
-                                               $target = ' target="thePicture"';
-                                       }
-                               } else {
-                                       $target = '';
-                               }
-                               $conf['JSwindow'] = isset($conf['JSwindow.']) ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.']) : $conf['JSwindow'];
-                               if ($conf['JSwindow']) {
-                                       if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
-                                               $altUrl = isset($conf['JSwindow.']['altUrl.']) ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.']) : $conf['JSwindow.']['altUrl'];
-                                               if ($altUrl) {
-                                                       $url = $altUrl . ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' . rawurlencode($imageFile) . $params);
-                                               }
-                                       }
-
-                                       $processedFile = $file->process('Image.CropScaleMask', $conf);
-                                       $JSwindowExpand = isset($conf['JSwindow.']['expand.']) ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.']) : $conf['JSwindow.']['expand'];
-                                       $offset = GeneralUtility::intExplode(',', $JSwindowExpand . ',');
-                                       $newWindow = isset($conf['JSwindow.']['newWindow.']) ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.']) : $conf['JSwindow.']['newWindow'];
-                                       $a1 = '<a href="' . htmlspecialchars($url) . '" onclick="' . htmlspecialchars(('openPic(\'' . $GLOBALS['TSFE']->baseUrlWrap($url) . '\',\'' . ($newWindow ? md5($url) : 'thePicture') . '\',\'width=' . ($processedFile->getProperty('width') + $offset[0]) . ',height=' . ($processedFile->getProperty('height') + $offset[1]) . ',status=0,menubar=0\'); return false;')) . '"' . $target . $GLOBALS['TSFE']->ATagParams . '>';
-                                       $a2 = '</a>';
-                                       $GLOBALS['TSFE']->setJS('openPic');
-                               } else {
-                                       $conf['linkParams.']['parameter'] = $url;
-                                       $string = $this->typoLink($string, $conf['linkParams.']);
-                               }
-                               if (isset($conf['stdWrap.'])) {
-                                       $string = $this->stdWrap($string, $conf['stdWrap.']);
-                               }
-                               $content = $a1 . $string . $a2;
-                       }
-               }
-               return $content;
-       }
-
-       /**
-        * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is.
-        *
-        * @param string $fName The filename, being a TypoScript resource data type
-        * @param string $addParams Additional parameters (attributes). Default is empty alt and title tags.
-        * @return string If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string
-        * @see FILE()
-        */
-       public function fileResource($fName, $addParams = 'alt="" title=""') {
-               $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName);
-               if ($incFile && file_exists($incFile)) {
-                       $fileinfo = GeneralUtility::split_fileref($incFile);
-                       if (GeneralUtility::inList('jpg,gif,jpeg,png', $fileinfo['fileext'])) {
-                               $imgFile = $incFile;
-                               $imgInfo = @getImageSize($imgFile);
-                               return '<img src="' . $GLOBALS['TSFE']->absRefPrefix . $imgFile . '" width="' . $imgInfo[0] . '" height="' . $imgInfo[1] . '"' . $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />';
-                       } elseif (filesize($incFile) < 1024 * 1024) {
-                               return $GLOBALS['TSFE']->tmpl->fileContent($incFile);
-                       }
-               }
-       }
-
-       /**
-        * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value.
-        * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content.
-        * Therefore you should call this function with the last-changed timestamp of any element you display.
-        *
-        * @param int $tstamp Unix timestamp (number of seconds since 1970)
-        * @return void
-        * @see TypoScriptFrontendController::setSysLastChanged()
-        */
-       public function lastChanged($tstamp) {
-               $tstamp = (int)$tstamp;
-               if ($tstamp > (int)$GLOBALS['TSFE']->register['SYS_LASTCHANGED']) {
-                       $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp;
-               }
-       }
-
-       /**
-        * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well.
-        * The "linkWrap" data type means that this function will find any integer encapsulated in {} (curly braces) in the first wrap part and substitute it with the corresponding page uid from the rootline where the found integer is pointing to the key in the rootline. See link below.
-        *
-        * @param string $content Input string
-        * @param string $wrap A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string
-        * @return string Wrapped output string
-        * @see wrap(), cImage(), FILE()
-        */
-       public function linkWrap($content, $wrap) {
-               $wrapArr = explode('|', $wrap);
-               if (preg_match('/\\{([0-9]*)\\}/', $wrapArr[0], $reg)) {
-                       if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) {
-                               $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
-                       }
-               }
-               return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
-       }
-
-       /**
-        * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element.
-        * From the $conf array it implements the properties "altText", "titleText" and "longdescURL"
-        *
-        * @param array $conf TypoScript configuration properties
-        * @param bool $longDesc If set, the longdesc attribute will be generated - must only be used for img elements!
-        * @return string Parameter string containing alt and title parameters (if any)
-        * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink()
-        */
-       public function getAltParam($conf, $longDesc = TRUE) {
-               $altText = isset($conf['altText.']) ? trim($this->stdWrap($conf['altText'], $conf['altText.'])) : trim($conf['altText']);
-               $titleText = isset($conf['titleText.']) ? trim($this->stdWrap($conf['titleText'], $conf['titleText.'])) : trim($conf['titleText']);
-               if (isset($conf['longdescURL.']) && $GLOBALS['TSFE']->config['config']['doctype'] != 'html5') {
-                       $longDesc = $this->typoLink_URL($conf['longdescURL.']);
-               } else {
-                       $longDesc = trim($conf['longdescURL']);
-               }
-               // "alt":
-               $altParam = ' alt="' . htmlspecialchars($altText) . '"';
-               // "title":
-               $emptyTitleHandling = 'useAlt';
-               $emptyTitleHandling = isset($conf['emptyTitleHandling.']) ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.']) : $conf['emptyTitleHandling'];
-               // Choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
-               if ($titleText || $emptyTitleHandling == 'keepEmpty') {
-                       $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
-               } elseif (!$titleText && $emptyTitleHandling == 'useAlt') {
-                       $altParam .= ' title="' . htmlspecialchars($altText) . '"';
-               }
-               // "longDesc" URL
-               if ($longDesc) {
-                       $altParam .= ' longdesc="' . htmlspecialchars(strip_tags($longDesc)) . '"';
-               }
-               return $altParam;
-       }
-
-       /**
-        * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields
-        *
-        * @param string $name Input string
-        * @return string the cleaned string
-        * @see FORM()
-        * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, the method is moved to FormContentObject
-        */
-       public function cleanFormName($name) {
-               GeneralUtility::logDeprecatedFunction();
-               // Turn data[x][y] into data:x:y:
-               $name = preg_replace('/\\[|\\]\\[?/', ':', trim($name));
-               // Remove illegal chars like _
-               return preg_replace('#[^:a-zA-Z0-9]#', '', $name);
-       }
-
-       /**
-        * An abstraction method to add parameters to an A tag.
-        * Uses the ATagParams property.
-        *
-        * @param array $conf TypoScript configuration properties
-        * @param bool $addGlobal If set, will add the global config.ATagParams to the link
-        * @return string String containing the parameters to the A tag (if non empty, with a leading space)
-        * @see IMGTEXT(), filelink(), makelinks(), typolink()
-        */
-       public function getATagParams($conf, $addGlobal = 1) {
-               $aTagParams = '';
-               if ($conf['ATagParams.']) {
-                       $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
-               } elseif ($conf['ATagParams']) {
-                       $aTagParams = ' ' . $conf['ATagParams'];
-               }
-               if ($addGlobal) {
-                       $aTagParams = ' ' . trim(($GLOBALS['TSFE']->ATagParams . $aTagParams));
-               }
-               // Extend params
-               if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'])) {
-                       $_params = array(
-                               'conf' => &$conf,
-                               'aTagParams' => &$aTagParams
-                       );
-                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'] as $objRef) {
-                               $processor =& GeneralUtility::getUserObj($objRef);
-                               $aTagParams = $processor->process($_params, $this);
-                       }
-               }
-
-               $aTagParams = trim($aTagParams);
-               if (!empty($aTagParams)) {
-                       $aTagParams = ' ' . $aTagParams;
-               }
-
-               return $aTagParams;
-       }
-
-       /**
-        * All extension links should ask this function for additional properties to their tags.
-        * Designed to add for instance an "onclick" property for site tracking systems.
-        *
-        * @param string $URL URL of the website
-        * @param string $TYPE
-        * @return string The additional tag properties
-        */
-       public function extLinkATagParams($URL, $TYPE) {
-               $out = '';
-               if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
-                       $extLinkATagParamsHandler = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']);
-                       if (method_exists($extLinkATagParamsHandler, 'main')) {
-                               $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
-                       }
-               }
-               return trim($out) ? ' ' . trim($out) : '';
-       }
-
-       /***********************************************
-        *
-        * HTML template processing functions
-        *
-        ***********************************************/
-       /**
-        * Returns a subpart from the input content stream.
-        * A subpart is a part of the input stream which is encapsulated in a
-        * string matching the input string, $marker. If this string is found
-        * inside of HTML comment tags the start/end points of the content block
-        * returned will be that right outside that comment block.
-        * Example: The contennt string is
-        * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?"
-        * If $marker is "###sub1###" then the content returned is
-        * " World. How are ". The input content string could just as well have
-        * been "Hello ###sub1### World. How are ###sub1### you?" and the result
-        * would be the same
-        * Wrapper for \TYPO3\CMS\Core\Html\HtmlParser::getSubpart which behaves identical
-        *
-        * @param string $content The content stream, typically HTML template content.
-        * @param string $marker The marker string, typically on the form "###[the marker string]###
-        * @return string The subpart found, if found.
-        */
-       public function getSubpart($content, $marker) {
-               return HtmlParser::getSubpart($content, $marker);
-       }
-
-       /**
-        * Substitute subpart in input template stream.
-        * This function substitutes a subpart in $content with the content of
-        * $subpartContent.
-        * Wrapper for \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart which behaves identical
-        *
-        * @param string $content The content stream, typically HTML template content.
-        * @param string $marker The marker string, typically on the form "###[the marker string]###
-        * @param mixed $subpartContent The content to insert instead of the subpart found. If a string, then just plain substitution happens (includes removing the HTML comments of the subpart if found). If $subpartContent happens to be an array, it's [0] and [1] elements are wrapped around the EXISTING content of the subpart (fetched by getSubpart()) thereby not removing the original content.
-        * @param bool $recursive If $recursive is set, the function calls itself with the content set to the remaining part of the content after the second marker. This means that proceding subparts are ALSO substituted!
-        * @return string The processed HTML content string.
-        */
-       public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) {
-               return HtmlParser::substituteSubpart($content, $marker, $subpartContent, $recursive);
-       }
-
-       /**
-        * Substitues multiple subparts at once
-        *
-        * @param string $content The content stream, typically HTML template content.
-        * @param array $subpartsContent The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content.
-        * @return string The processed HTML content string.
-        */
-       public function substituteSubpartArray($content, array $subpartsContent) {
-               return HtmlParser::substituteSubpartArray($content, $subpartsContent);
-       }
-
-       /**
-        * Substitutes a marker string in the input content
-        * (by a simple str_replace())
-        *
-        * @param string $content The content stream, typically HTML template content.
-        * @param string $marker The marker string, typically on the form "###[the marker string]###
-        * @param mixed $markContent The content to insert instead of the marker string found.
-        * @return string The processed HTML content string.
-        * @see substituteSubpart()
-        */
-       public function substituteMarker($content, $marker, $markContent) {
-               return HtmlParser::substituteMarker($content, $marker, $markContent);
-       }
-
-       /**
-        * Multi substitution function with caching.
-        *
-        * This function should be a one-stop substitution function for working
-        * with HTML-template. It does not substitute by str_replace but by
-        * splitting. This secures that the value inserted does not themselves
-        * contain markers or subparts.
-        *
-        * Note that the "caching" won't cache the content of the substition,
-        * but only the splitting of the template in various parts. So if you
-        * want only one cache-entry per template, make sure you always pass the
-        * exact same set of marker/subpart keys. Else you will be flooding the
-        * users cache table.
-        *
-        * This function takes three kinds of substitutions in one:
-        * $markContentArray is a regular marker-array where the 'keys' are
-        * substituted in $content with their values
-        *
-        * $subpartContentArray works exactly like markContentArray only is whole
-        * subparts substituted and not only a single marker.
-        *
-        * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where
-        * the subparts pointed to by the main key is wrapped with the 0/1 value
-        * alternating.
-        *
-        * @param string $content The content stream, typically HTML template content.
-        * @param array $markContentArray Regular marker-array where the 'keys' are substituted in $content with their values
-        * @param array $subpartContentArray Exactly like markContentArray only is whole subparts substituted and not only a single marker.
-        * @param array $wrappedSubpartContentArray An array of arrays with 0/1 keys where the subparts pointed to by the main key is wrapped with the 0/1 value alternating.
-        * @return string The output content stream
-        * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE()
-        */
-       public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) {
-               $GLOBALS['TT']->push('substituteMarkerArrayCached');
-               // If not arrays then set them
-               if (is_null($markContentArray)) {
-                       // Plain markers
-                       $markContentArray = array();
-               }
-               if (is_null($subpartContentArray)) {
-                       // Subparts being directly substituted
-                       $subpartContentArray = array();
-               }
-               if (is_null($wrappedSubpartContentArray)) {
-                       // Subparts being wrapped
-                       $wrappedSubpartContentArray = array();
-               }
-               // Finding keys and check hash:
-               $sPkeys = array_keys($subpartContentArray);
-               $wPkeys = array_keys($wrappedSubpartContentArray);
-               $aKeys = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys);
-               if (!count($aKeys)) {
-                       $GLOBALS['TT']->pull();
-                       return $content;
-               }
-               asort($aKeys);
-               $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array(
-                       $content,
-                       $aKeys
-               )));
-               if ($this->substMarkerCache[$storeKey]) {
-                       $storeArr = $this->substMarkerCache[$storeKey];
-                       $GLOBALS['TT']->setTSlogMessage('Cached', 0);
-               } else {
-                       $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey);
-                       if (is_array($storeArrDat)) {
-                               $storeArr = $storeArrDat;
-                               // Setting cache:
-                               $this->substMarkerCache[$storeKey] = $storeArr;
-                               $GLOBALS['TT']->setTSlogMessage('Cached from DB', 0);
-                       } else {
-                               // Initialize storeArr
-                               $storeArr = array();
-                               // Finding subparts and substituting them with the subpart as a marker
-                               foreach ($sPkeys as $sPK) {
-                                       $content = $this->substituteSubpart($content, $sPK, $sPK);
-                               }
-                               // Finding subparts and wrapping them with markers
-                               foreach ($wPkeys as $wPK) {
-                                       $content = $this->substituteSubpart($content, $wPK, array(
-                                               $wPK,
-                                               $wPK
-                                       ));
-                               }
-                               // Traverse keys and quote them for reg ex.
-                               foreach ($aKeys as $tK => $tV) {
-                                       $aKeys[$tK] = preg_quote($tV, '/');
-                               }
-                               $regex = '/' . implode('|', $aKeys) . '/';
-                               // Doing regex's
-                               $storeArr['c'] = preg_split($regex, $content);
-                               preg_match_all($regex, $content, $keyList);
-                               $storeArr['k'] = $keyList[0];
-                               // Setting cache:
-                               $this->substMarkerCache[$storeKey] = $storeArr;
-                               // Storing the cached data:
-                               $GLOBALS['TSFE']->sys_page->storeHash($storeKey, $storeArr, 'substMarkArrayCached');
-                               $GLOBALS['TT']->setTSlogMessage('Parsing', 0);
-                       }
-               }
-               // Substitution/Merging:
-               // Merging content types together, resetting
-               $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
-               $wSCA_reg = array();
-               $content = '';
-               // Traversing the keyList array and merging the static and dynamic content
-               foreach ($storeArr['k'] as $n => $keyN) {
-                       $content .= $storeArr['c'][$n];
-                       if (!is_array($valueArr[$keyN])) {
-                               $content .= $valueArr[$keyN];
-                       } else {
-                               $content .= $valueArr[$keyN][(int)$wSCA_reg[$keyN] % 2];
-                               $wSCA_reg[$keyN]++;
-                       }
-               }
-               $content .= $storeArr['c'][count($storeArr['k'])];
-               $GLOBALS['TT']->pull();
-               return $content;
-       }
-
-       /**
-        * Traverses the input $markContentArray array and for each key the marker
-        * by the same name (possibly wrapped and in upper case) will be
-        * substituted with the keys value in the array.
-        *
-        * This is very useful if you have a data-record to substitute in some
-        * content. In particular when you use the $wrap and $uppercase values to
-        * pre-process the markers. Eg. a key name like "myfield" could effectively
-        * be represented by the marker "###MYFIELD###" if the wrap value
-        * was "###|###" and the $uppercase boolean TRUE.
-        *
-        * @param string $content The content stream, typically HTML template content.
-        * @param array $markContentArray The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
-        * @param string $wrap A wrap value - [part 1] | [part 2] - for the markers before substitution
-        * @param bool $uppercase If set, all marker string substitution is done with upper-case markers.
-        * @param bool $deleteUnused If set, all unused marker are deleted.
-        * @return string The processed output stream
-        * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
-        */
-       public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
-               return HtmlParser::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
-       }
-
-       /**
-        * Substitute marker array in an array of values
-        *
-        * @param mixed $tree If string, then it just calls substituteMarkerArray. If array(and even multi-dim) then for each key/value pair the marker array will be substituted (by calling this function recursively)
-        * @param array $markContentArray The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content string/array values.
-        * @return mixed The processed input variable.
-        * @see substituteMarker()
-        */
-       public function substituteMarkerInObject(&$tree, array $markContentArray) {
-               if (is_array($tree)) {
-                       foreach ($tree as $key => $value) {
-                               $this->substituteMarkerInObject($tree[$key], $markContentArray);
-                       }
-               } else {
-                       $tree = $this->substituteMarkerArray($tree, $markContentArray);
-               }
-               return $tree;
-       }
-
-       /**
-        * Replaces all markers and subparts in a template with the content provided in the structured array.
-        *
-        * @param string $content
-        * @param array $markersAndSubparts
-        * @param string $wrap
-        * @param bool $uppercase
-        * @param bool $deleteUnused
-        * @return string
-        */
-       public function substituteMarkerAndSubpartArrayRecursive($content, array $markersAndSubparts, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
-               return HtmlParser::substituteMarkerAndSubpartArrayRecursive($content, $markersAndSubparts, $wrap, $uppercase, $deleteUnused);
-       }
-
-       /**
-        * Adds elements to the input $markContentArray based on the values from
-        * the fields from $fieldList found in $row
-        *
-        * @param array $markContentArray Array with key/values being marker-strings/substitution values.
-        * @param array $row An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray
-        * @param string $fieldList A list of fields from the $row array to add to the $markContentArray array. If empty all fields from $row will be added (unless they are integers)
-        * @param bool $nl2br If set, all values added to $markContentArray will be nl2br()'ed
-        * @param string $prefix Prefix string to the fieldname before it is added as a key in the $markContentArray. Notice that the keys added to the $markContentArray always start and end with "###
-        * @param bool $HSC If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance.
-        * @return array The modified $markContentArray
-        */
-       public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = TRUE, $prefix = 'FIELD_', $HSC = FALSE) {
-               if ($fieldList) {
-                       $fArr = GeneralUtility::trimExplode(',', $fieldList, TRUE);
-                       foreach ($fArr as $field) {
-                               $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field], !empty($GLOBALS['TSFE']->xhtmlDoctype)) : $row[$field];
-                       }
-               } else {
-                       if (is_array($row)) {
-                               foreach ($row as $field => $value) {
-                                       if (!MathUtility::canBeInterpretedAsInteger($field)) {
-                                               if ($HSC) {
-                                                       $value = htmlspecialchars($value);
-                                               }
-                                               $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value, !empty($GLOBALS['TSFE']->xhtmlDoctype)) : $value;
-                                       }
-                               }
-                       }
-               }
-               return $markContentArray;
-       }
-
-       /**
-        * Sets the current file object during iterations over files.
-        *
-        * @param File $fileObject The file object.
-        */
-       public function setCurrentFile($fileObject) {
-               $this->currentFile = $fileObject;
-       }
-
-       /**
-        * Gets the current file object during iterations over files.
-        *
-        * @return File The current file object.
-        */
-       public function getCurrentFile() {
-               return $this->currentFile;
-       }
-
-       /***********************************************
-        *
-        * "stdWrap" + sub functions
-        *
-        ***********************************************/
-       /**
-        * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript.
-        * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array(holding the TypoScript "stdWrap properties")
-        * See the link below for a complete list of properties and what they do. The order of the table with properties found in TSref (the link) follows the actual order of implementation in this function.
-        *
-        * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData
-        *
-        * @param string $content Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
-        * @param array $conf TypoScript "stdWrap properties".
-        * @return string The processed input value
-        */
-       public function stdWrap($content = '', $conf = array()) {
-               // If there is any hook object, activate all of the process and override functions.
-               // The hook interface ContentObjectStdWrapHookInterface takes care that all 4 methods exist.
-               if ($this->stdWrapHookObjects) {
-                       $conf['stdWrapPreProcess'] = 1;
-                       $conf['stdWrapOverride'] = 1;
-                       $conf['stdWrapProcess'] = 1;
-                       $conf['stdWrapPostProcess'] = 1;
-               }
-
-               if (!is_array($conf) || !$conf) {
-                       return $content;
-               }
-
-               // Cache handling
-               if (is_array($conf['cache.'])) {
-                       $conf['cache.']['key'] = $this->stdWrap($conf['cache.']['key'], $conf['cache.']['key.']);
-                       $conf['cache.']['tags'] = $this->stdWrap($conf['cache.']['tags'], $conf['cache.']['tags.']);
-                       $conf['cache.']['lifetime'] = $this->stdWrap($conf['cache.']['lifetime'], $conf['cache.']['lifetime.']);
-                       $conf['cacheRead'] = 1;
-                       $conf['cacheStore'] = 1;
-               }
-               // Check, which of the available stdWrap functions is needed for the current conf Array
-               // and keep only those but still in the same order
-               $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
-               // Functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
-               $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
-               // Additional Array to check whether a function has already been executed
-               $isExecuted = array();
-               // Additional switch to make sure 'required', 'if' and 'fieldRequired'
-               // will still stop rendering immediately in case they return FALSE
-               $this->stdWrapRecursionLevel++;
-               $this->stopRendering[$this->stdWrapRecursionLevel] = FALSE;
-               // execute each function in the predefined order
-               foreach ($sortedConf as $stdWrapName => $functionType) {
-                       // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
-                       if (!$isExecuted[$stdWrapName] && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
-                               $functionName = rtrim($stdWrapName, '.');
-                               $functionProperties = $functionName . '.';
-                               // If there is any code on the next level, check if it contains "official" stdWrap functions
-                               // if yes, execute them first - will make each function stdWrap aware
-                               // so additional stdWrap calls within the functions can be removed, since the result will be the same
-                               // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
-                               if ($functionName !== 'stdWrap' && !empty($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
-                                       if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
-                                               $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
-                                       }
-                               }
-                               // Check if key is still containing something, since it might have been changed by next level stdWrap before
-                               if ((isset($conf[$functionName]) || $conf[$functionProperties]) && ($functionType !== 'boolean' || $conf[$functionName])) {
-                                       // Get just that part of $conf that is needed for the particular function
-                                       $singleConf = array(
-                                               $functionName => $conf[$functionName],
-                                               $functionProperties => $conf[$functionProperties]
-                                       );
-                                       // In this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.''
-                                       if ($functionName === 'spaceBefore' || $functionName === 'spaceAfter') {
-                                               $singleConf['space.'] = $conf['space.'];
-                                       }
-                                       // Hand over the whole $conf array to the stdWrapHookObjects
-                                       if ($functionType === 'hook') {
-                                               $singleConf = $conf;
-                                       }
-                                       // Add both keys - with and without the dot - to the set of executed functions
-                                       $isExecuted[$functionName] = TRUE;
-                                       $isExecuted[$functionProperties] = TRUE;
-                                       // Call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
-                                       $functionName = 'stdWrap_' . $functionName;
-                                       $content = $this->{$functionName}($content, $singleConf);
-                               } elseif ($functionType == 'boolean' && !$conf[$functionName]) {
-                                       $isExecuted[$functionName] = TRUE;
-                                       $isExecuted[$functionProperties] = TRUE;
-                               }
-                       }
-               }
-               unset($this->stopRendering[$this->stdWrapRecursionLevel]);
-               $this->stdWrapRecursionLevel--;
-
-               return $content;
-       }
-
-       /**
-        * Gets a configuration value by passing them through stdWrap first and taking a default value if stdWrap doesn't yield a result.
-        *
-        * @param string $key The config variable key (from TS array).
-        * @param array $config The TypoScript array.
-        * @param string $defaultValue Optional default value.
-        * @return string Value of the config variable
-        */
-       public function stdWrapValue($key, array $config, $defaultValue = '') {
-               if (isset($config[$key])) {
-                       if (!isset($config[$key . '.'])) {
-                               return $config[$key];
-                       }
-               } elseif (isset($config[$key . '.'])) {
-                       $config[$key] = '';
-               } else {
-                       return $defaultValue;
-               }
-               $stdWrapped = $this->stdWrap($config[$key], $config[$key . '.']);
-               return $stdWrapped ?: $defaultValue;
-       }
-
-       /**
-        * stdWrap pre process hook
-        * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
-        * this hook will execute functions before any other stdWrap function can modify anything
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_stdWrapPreProcess($content = '', $conf = array()) {
-               foreach ($this->stdWrapHookObjects as $hookObject) {
-                       $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
-               }
-               return $content;
-       }
-
-       /**
-        * Check if content was cached before (depending on the given cache key)
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_cacheRead($content = '', $conf = array()) {
-               if (!empty($conf['cache.']['key'])) {
-                       /** @var $cacheFrontend \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend */
-                       $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
-                       if ($cacheFrontend && $cacheFrontend->has($conf['cache.']['key'])) {
-                               $content = $cacheFrontend->get($conf['cache.']['key']);
-                               $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
-                       }
-               }
-               return $content;
-       }
-
-       /**
-        * Add tags to page cache (comma-separated list)
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_addPageCacheTags($content = '', $conf = array()) {
-               $tags = isset($conf['addPageCacheTags.'])
-                       ? $this->stdWrap($conf['addPageCacheTags'], $conf['addPageCacheTags.'])
-                       : $conf['addPageCacheTags'];
-               if (!empty($tags)) {
-                       $cacheTags = GeneralUtility::trimExplode(',', $tags, TRUE);
-                       $GLOBALS['TSFE']->addCacheTags($cacheTags);
-               }
-               return $content;
-       }
-
-       /**
-        * setContentToCurrent
-        * actually it just does the contrary: Sets the value of 'current' based on current content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for setContentToCurrent.
-        * @return string The processed input value
-        */
-       public function stdWrap_setContentToCurrent($content = '', $conf = array()) {
-               $this->data[$this->currentValKey] = $content;
-               return $content;
-       }
-
-       /**
-        * setCurrent
-        * Sets the value of 'current' based on the outcome of stdWrap operations
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for setCurrent.
-        * @return string The processed input value
-        */
-       public function stdWrap_setCurrent($content = '', $conf = array()) {
-               $this->data[$this->currentValKey] = $conf['setCurrent'];
-               return $content;
-       }
-
-       /**
-        * lang
-        * Translates content based on the language currently used by the FE
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for lang.
-        * @return string The processed input value
-        */
-       public function stdWrap_lang($content = '', $conf = array()) {
-               if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) {
-                       $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']];
-               }
-               return $content;
-       }
-
-       /**
-        * data
-        * Gets content from different sources based on getText functions, makes use of alternativeData, when set
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for data.
-        * @return string The processed input value
-        */
-       public function stdWrap_data($content = '', $conf = array()) {
-               $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
-               // This must be unset directly after
-               $this->alternativeData = '';
-               return $content;
-       }
-
-       /**
-        * field
-        * Gets content from a DB field
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for field.
-        * @return string The processed input value
-        */
-       public function stdWrap_field($content = '', $conf = array()) {
-               return $this->getFieldVal($conf['field']);
-       }
-
-       /**
-        * current
-        * Gets content that has been perviously set as 'current'
-        * Can be set via setContentToCurrent or setCurrent or will be set automatically i.e. inside the split function
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for current.
-        * @return string The processed input value
-        */
-       public function stdWrap_current($content = '', $conf = array()) {
-               return $this->data[$this->currentValKey];
-       }
-
-       /**
-        * cObject
-        * Will replace the content with the value of a any official TypoScript cObject
-        * like TEXT, COA, HMENU
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for cObject.
-        * @return string The processed input value
-        */
-       public function stdWrap_cObject($content = '', $conf = array()) {
-               return $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject');
-       }
-
-       /**
-        * numRows
-        * Counts the number of returned records of a DB operation
-        * makes use of select internally
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for numRows.
-        * @return string The processed input value
-        */
-       public function stdWrap_numRows($content = '', $conf = array()) {
-               return $this->numRows($conf['numRows.']);
-       }
-
-       /**
-        * filelist
-        * Will create a list of files based on some additional parameters
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for filelist.
-        * @return string The processed input value
-        */
-       public function stdWrap_filelist($content = '', $conf = array()) {
-               return $this->filelist($conf['filelist']);
-       }
-
-       /**
-        * preUserFunc
-        * Will execute a user public function before the content will be modified by any other stdWrap function
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for preUserFunc.
-        * @return string The processed input value
-        */
-       public function stdWrap_preUserFunc($content = '', $conf = array()) {
-               return $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
-       }
-
-       /**
-        * stdWrap override hook
-        * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
-        * this hook will execute functions on existing content but still before the content gets modified or replaced
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_stdWrapOverride($content = '', $conf = array()) {
-               foreach ($this->stdWrapHookObjects as $hookObject) {
-                       $content = $hookObject->stdWrapOverride($content, $conf, $this);
-               }
-               return $content;
-       }
-
-       /**
-        * override
-        * Will override the current value of content with its own value'
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for override.
-        * @return string The processed input value
-        */
-       public function stdWrap_override($content = '', $conf = array()) {
-               if (trim($conf['override'])) {
-                       $content = $conf['override'];
-               }
-               return $content;
-       }
-
-       /**
-        * preIfEmptyListNum
-        * Gets a value off a CSV list before the following ifEmpty check
-        * Makes sure that the result of ifEmpty will be TRUE in case the CSV does not contain a value at the position given by preIfEmptyListNum
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for preIfEmptyListNum.
-        * @return string The processed input value
-        */
-       public function stdWrap_preIfEmptyListNum($content = '', $conf = array()) {
-               return $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']);
-       }
-
-       /**
-        * ifNull
-        * Will set content to a replacement value in case the value of content is NULL
-        *
-        * @param string|NULL $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for ifNull.
-        * @return string The processed input value
-        */
-       public function stdWrap_ifNull($content = '', $conf = array()) {
-               return $content !== NULL ? $content : $conf['ifNull'];
-       }
-
-       /**
-        * ifEmpty
-        * Will set content to a replacement value in case the trimmed value of content returns FALSE
-        * 0 (zero) will be replaced as well
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for ifEmpty.
-        * @return string The processed input value
-        */
-       public function stdWrap_ifEmpty($content = '', $conf = array()) {
-               if (!trim($content)) {
-                       $content = $conf['ifEmpty'];
-               }
-               return $content;
-       }
-
-       /**
-        * ifBlank
-        * Will set content to a replacement value in case the trimmed value of content has no length
-        * 0 (zero) will not be replaced
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for ifBlank.
-        * @return string The processed input value
-        */
-       public function stdWrap_ifBlank($content = '', $conf = array()) {
-               if (trim($content) === '') {
-                       $content = $conf['ifBlank'];
-               }
-               return $content;
-       }
-
-       /**
-        * listNum
-        * Gets a value off a CSV list after ifEmpty check
-        * Might return an empty value in case the CSV does not contain a value at the position given by listNum
-        * Use preIfEmptyListNum to avoid that behaviour
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for listNum.
-        * @return string The processed input value
-        */
-       public function stdWrap_listNum($content = '', $conf = array()) {
-               return $this->listNum($content, $conf['listNum'], $conf['listNum.']['splitChar']);
-       }
-
-       /**
-        * trim
-        * Cuts off any whitespace at the beginning and the end of the content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for trim.
-        * @return string The processed input value
-        */
-       public function stdWrap_trim($content = '', $conf = array()) {
-               return trim($content);
-       }
-
-       /**
-        * strPad
-        * Will return a string padded left/right/on both sides, based on configuration given as stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for strPad.
-        * @return string The processed input value
-        */
-       public function stdWrap_strPad($content = '', $conf = array()) {
-               // Must specify a length in conf for this to make sense
-               $length = 0;
-               // Padding with space is PHP-default
-               $padWith = ' ';
-               // Padding on the right side is PHP-default
-               $padType = STR_PAD_RIGHT;
-               if (!empty($conf['strPad.']['length'])) {
-                       $length = isset($conf['strPad.']['length.']) ? $this->stdWrap($conf['strPad.']['length'], $conf['strPad.']['length.']) : $conf['strPad.']['length'];
-                       $length = (int)$length;
-               }
-               if (isset($conf['strPad.']['padWith']) && (string)$conf['strPad.']['padWith'] !== '') {
-                       $padWith = isset($conf['strPad.']['padWith.']) ? $this->stdWrap($conf['strPad.']['padWith'], $conf['strPad.']['padWith.']) : $conf['strPad.']['padWith'];
-               }
-               if (!empty($conf['strPad.']['type'])) {
-                       $type = isset($conf['strPad.']['type.']) ? $this->stdWrap($conf['strPad.']['type'], $conf['strPad.']['type.']) : $conf['strPad.']['type'];
-                       if (strtolower($type) === 'left') {
-                               $padType = STR_PAD_LEFT;
-                       } elseif (strtolower($type) === 'both') {
-                               $padType = STR_PAD_BOTH;
-                       }
-               }
-               $content = str_pad($content, $length, $padWith, $padType);
-               return $content;
-       }
-
-       /**
-        * stdWrap
-        * A recursive call of the stdWrap function set
-        * This enables the user to execute stdWrap functions in another than the predefined order
-        * It modifies the content, not the property
-        * while the new feature of chained stdWrap functions modifies the property and not the content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for stdWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_stdWrap($content = '', $conf = array()) {
-               return $this->stdWrap($content, $conf['stdWrap.']);
-       }
-
-       /**
-        * stdWrap process hook
-        * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
-        * this hook executes functions directly after the recursive stdWrap function call but still before the content gets modified
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_stdWrapProcess($content = '', $conf = array()) {
-               foreach ($this->stdWrapHookObjects as $hookObject) {
-                       $content = $hookObject->stdWrapProcess($content, $conf, $this);
-               }
-               return $content;
-       }
-
-       /**
-        * required
-        * Will immediately stop rendering and return an empty value
-        * when there is no content at this point
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for required.
-        * @return string The processed input value
-        */
-       public function stdWrap_required($content = '', $conf = array()) {
-               if ((string)$content === '') {
-                       $content = '';
-                       $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
-               }
-               return $content;
-       }
-
-       /**
-        * if
-        * Will immediately stop rendering and return an empty value
-        * when the result of the checks returns FALSE
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for if.
-        * @return string The processed input value
-        */
-       public function stdWrap_if($content = '', $conf = array()) {
-               if (empty($conf['if.']) || $this->checkIf($conf['if.'])) {
-                       return $content;
-               }
-               $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
-               return '';
-       }
-
-       /**
-        * fieldRequired
-        * Will immediately stop rendering and return an empty value
-        * when there is no content in the field given by fieldRequired
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for fieldRequired.
-        * @return string The processed input value
-        */
-       public function stdWrap_fieldRequired($content = '', $conf = array()) {
-               if (!trim($this->data[$conf['fieldRequired']])) {
-                       $content = '';
-                       $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
-               }
-               return $content;
-       }
-
-       /**
-        * csConv
-        * Will convert the current chracter set of the content to the one given in csConv
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for csConv.
-        * @return string The processed input value
-        */
-       public function stdWrap_csConv($content = '', $conf = array()) {
-               return $GLOBALS['TSFE']->csConv($content, $conf['csConv']);
-       }
-
-       /**
-        * parseFunc
-        * Will parse the content based on functions given as stdWrap properties
-        * Heavily used together with RTE based content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for parseFunc.
-        * @return string The processed input value
-        */
-       public function stdWrap_parseFunc($content = '', $conf = array()) {
-               return $this->parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
-       }
-
-       /**
-        * HTMLparser
-        * Will parse HTML content based on functions given as stdWrap properties
-        * Heavily used together with RTE based content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for HTMLparser.
-        * @return string The processed input value
-        */
-       public function stdWrap_HTMLparser($content = '', $conf = array()) {
-               if (is_array($conf['HTMLparser.'])) {
-                       $content = $this->HTMLparser_TSbridge($content, $conf['HTMLparser.']);
-               }
-               return $content;
-       }
-
-       /**
-        * split
-        * Will split the content by a given token and treat the results separately
-        * Automatically fills 'current' with a single result
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for split.
-        * @return string The processed input value
-        */
-       public function stdWrap_split($content = '', $conf = array()) {
-               return $this->splitObj($content, $conf['split.']);
-       }
-
-       /**
-        * replacement
-        * Will execute replacements on the content (optionally with preg-regex)
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for replacement.
-        * @return string The processed input value
-        */
-       public function stdWrap_replacement($content = '', $conf = array()) {
-               return $this->replacement($content, $conf['replacement.']);
-       }
-
-       /**
-        * prioriCalc
-        * Will use the content as a mathematical term and calculate the result
-        * Can be set to 1 to just get a calculated value or 'intval' to get the integer of the result
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for prioriCalc.
-        * @return string The processed input value
-        */
-       public function stdWrap_prioriCalc($content = '', $conf = array()) {
-               $content = MathUtility::calculateWithParentheses($content);
-               if ($conf['prioriCalc'] == 'intval') {
-                       $content = (int)$content;
-               }
-               return $content;
-       }
-
-       /**
-        * char
-        * Will return a character based on its position within the current character set
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for char.
-        * @return string The processed input value
-        */
-       public function stdWrap_char($content = '', $conf = array()) {
-               return chr((int)$conf['char']);
-       }
-
-       /**
-        * intval
-        * Will return an integer value of the current content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for intval.
-        * @return string The processed input value
-        */
-       public function stdWrap_intval($content = '', $conf = array()) {
-               return (int)$content;
-       }
-
-       /**
-        * Will return a hashed value of the current content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for hash.
-        * @return string The processed input value
-        * @link http://php.net/manual/de/function.hash-algos.php for a list of supported hash algorithms
-        */
-       public function stdWrap_hash($content = '', array $conf = array()) {
-               $algorithm = isset($conf['hash.']) ? $this->stdWrap($conf['hash'], $conf['hash.']) : $conf['hash'];
-               if (function_exists('hash') && in_array($algorithm, hash_algos())) {
-                       $content = hash($algorithm, $content);
-               } else {
-                       // Non-existing hashing algorithm
-                       $content = '';
-               }
-               return $content;
-       }
-
-       /**
-        * stdWrap_round will return a rounded number with ceil(), floor() or round(), defaults to round()
-        * Only the english number format is supported . (dot) as decimal point
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for round.
-        * @return string The processed input value
-        */
-       public function stdWrap_round($content = '', $conf = array()) {
-               return $this->round($content, $conf['round.']);
-       }
-
-       /**
-        * numberFormat
-        * Will return a formatted number based on configuration given as stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for numberFormat.
-        * @return string The processed input value
-        */
-       public function stdWrap_numberFormat($content = '', $conf = array()) {
-               return $this->numberFormat($content, $conf['numberFormat.']);
-       }
-
-       /**
-        * expandList
-        * Will return a formatted number based on configuration given as stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for expandList.
-        * @return string The processed input value
-        */
-       public function stdWrap_expandList($content = '', $conf = array()) {
-               return GeneralUtility::expandList($content);
-       }
-
-       /**
-        * date
-        * Will return a formatted date based on configuration given according to PHP date/gmdate properties
-        * Will return gmdate when the property GMT returns TRUE
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for date.
-        * @return string The processed input value
-        */
-       public function stdWrap_date($content = '', $conf = array()) {
-               // Check for zero length string to mimic default case of date/gmdate.
-               $content = $content == '' ? $GLOBALS['EXEC_TIME'] : (int)$content;
-               $content = $conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content);
-               return $content;
-       }
-
-       /**
-        * strftime
-        * Will return a formatted date based on configuration given according to PHP strftime/gmstrftime properties
-        * Will return gmstrftime when the property GMT returns TRUE
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for strftime.
-        * @return string The processed input value
-        */
-       public function stdWrap_strftime($content = '', $conf = array()) {
-                       // Check for zero length string to mimic default case of strtime/gmstrftime
-               $content = $content == '' ? $GLOBALS['EXEC_TIME'] : (int)$content;
-               $content = $conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content);
-               $tmp_charset = $conf['strftime.']['charset'] ? $conf['strftime.']['charset'] : $GLOBALS['TSFE']->localeCharset;
-               if ($tmp_charset) {
-                       $content = $GLOBALS['TSFE']->csConv($content, $tmp_charset);
-               }
-               return $content;
-       }
-
-       /**
-        * strtotime
-        * Will return a timestamp based on configuration given according to PHP strtotime
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for strtotime.
-        * @return string The processed input value
-        */
-       public function stdWrap_strtotime($content = '', $conf = array()) {
-               if ($conf['strtotime'] !== '1') {
-                       $content .= ' ' . $conf['strtotime'];
-               }
-               return strtotime($content, $GLOBALS['EXEC_TIME']);
-       }
-
-       /**
-        * age
-        * Will return the age of a given timestamp based on configuration given by stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for age.
-        * @return string The processed input value
-        */
-       public function stdWrap_age($content = '', $conf = array()) {
-               return $this->calcAge($GLOBALS['EXEC_TIME'] - $content, $conf['age']);
-       }
-
-       /**
-        * case
-        * Will transform the content to be upper or lower case only
-        * Leaves HTML tags untouched
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for case.
-        * @return string The processed input value
-        */
-       public function stdWrap_case($content = '', $conf = array()) {
-               return $this->HTMLcaseshift($content, $conf['case']);
-       }
-
-       /**
-        * bytes
-        * Will return the size of a given number in Bytes       *
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for bytes.
-        * @return string The processed input value
-        */
-       public function stdWrap_bytes($content = '', $conf = array()) {
-               return GeneralUtility::formatSize($content, $conf['bytes.']['labels']);
-       }
-
-       /**
-        * substring
-        * Will return a substring based on position information given by stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for substring.
-        * @return string The processed input value
-        */
-       public function stdWrap_substring($content = '', $conf = array()) {
-               return $this->substring($content, $conf['substring']);
-       }
-
-       /**
-        * removeBadHTML
-        * Removes HTML tags based on stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for removeBadHTML.
-        * @return string The processed input value
-        */
-       public function stdWrap_removeBadHTML($content = '', $conf = array()) {
-               return $this->removeBadHTML($content, $conf['removeBadHTML.']);
-       }
-
-       /**
-        * cropHTML
-        * Crops content to a given size while leaving HTML tags untouched
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for cropHTML.
-        * @return string The processed input value
-        */
-       public function stdWrap_cropHTML($content = '', $conf = array()) {
-               return $this->cropHTML($content, $conf['cropHTML']);
-       }
-
-       /**
-        * stripHtml
-        * Copmletely removes HTML tags from content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for stripHtml.
-        * @return string The processed input value
-        */
-       public function stdWrap_stripHtml($content = '', $conf = array()) {
-               return strip_tags($content);
-       }
-
-       /**
-        * crop
-        * Crops content to a given size without caring about HTML tags
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for crop.
-        * @return string The processed input value
-        */
-       public function stdWrap_crop($content = '', $conf = array()) {
-               return $this->crop($content, $conf['crop']);
-       }
-
-       /**
-        * rawUrlEncode
-        * Encodes content to be used within URLs
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for rawUrlEncode.
-        * @return string The processed input value
-        */
-       public function stdWrap_rawUrlEncode($content = '', $conf = array()) {
-               return rawurlencode($content);
-       }
-
-       /**
-        * htmlSpecialChars
-        * Transforms HTML tags to readable text by replacing special characters with their HTML entity
-        * When preserveEntities returns TRUE, existing entities will be left untouched
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for htmlSpecalChars.
-        * @return string The processed input value
-        */
-       public function stdWrap_htmlSpecialChars($content = '', $conf = array()) {
-               if (!empty($conf['htmlSpecialChars.']['preserveEntities'])) {
-                       $content = htmlspecialchars($content, ENT_COMPAT, 'UTF-8', FALSE);
-               } else {
-                       $content = htmlspecialchars($content);
-               }
-               return $content;
-       }
-
-       /**
-        * encodeForJavaScriptValue
-        * Escapes content to be used inside JavaScript strings. No quotes are added around the value
-        * as this can easily be done in TypoScript
-        *
-        * @param string $content Input value undergoing processing in this function
-        * @param array $conf stdWrap properties for encodeForJavaScriptValue
-        * @return string The processed input value
-        */
-       public function stdWrap_encodeForJavaScriptValue($content = '', $conf = array()) {
-               return GeneralUtility::quoteJSvalue($content);
-       }
-
-       /**
-        * doubleBrTag
-        * Searches for double line breaks and replaces them with the given value
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for doubleBrTag.
-        * @return string The processed input value
-        */
-       public function stdWrap_doubleBrTag($content = '', $conf = array()) {
-               return preg_replace('/
+class ContentObjectRenderer
+{
+    /**
+     * @var array
+     */
+    public $align = array(
+        'center',
+        'right',
+        'left'
+    );
+
+    /**
+     * stdWrap functions in their correct order
+     *
+     * @see stdWrap()
+     */
+    public $stdWrapOrder = array(
+        'stdWrapPreProcess' => 'hook',
+        // this is a placeholder for the first Hook
+        'cacheRead' => 'hook',
+        // this is a placeholder for checking if the content is available in cache
+        'setContentToCurrent' => 'boolean',
+        'setContentToCurrent.' => 'array',
+        'addPageCacheTags' => 'string',
+        'addPageCacheTags.' => 'array',
+        'setCurrent' => 'string',
+        'setCurrent.' => 'array',
+        'lang.' => 'array',
+        'data' => 'getText',
+        'data.' => 'array',
+        'field' => 'fieldName',
+        'field.' => 'array',
+        'current' => 'boolean',
+        'current.' => 'array',
+        'cObject' => 'cObject',
+        'cObject.' => 'array',
+        'numRows.' => 'array',
+        'filelist' => 'dir',
+        'filelist.' => 'array',
+        'preUserFunc' => 'functionName',
+        'stdWrapOverride' => 'hook',
+        // this is a placeholder for the second Hook
+        'override' => 'string',
+        'override.' => 'array',
+        'preIfEmptyListNum' => 'listNum',
+        'preIfEmptyListNum.' => 'array',
+        'ifNull' => 'string',
+        'ifNull.' => 'array',
+        'ifEmpty' => 'string',
+        'ifEmpty.' => 'array',
+        'ifBlank' => 'string',
+        'ifBlank.' => 'array',
+        'listNum' => 'listNum',
+        'listNum.' => 'array',
+        'trim' => 'boolean',
+        'trim.' => 'array',
+        'strPad.' => 'array',
+        'stdWrap' => 'stdWrap',
+        'stdWrap.' => 'array',
+        'stdWrapProcess' => 'hook',
+        // this is a placeholder for the third Hook
+        'required' => 'boolean',
+        'required.' => 'array',
+        'if.' => 'array',
+        'fieldRequired' => 'fieldName',
+        'fieldRequired.' => 'array',
+        'csConv' => 'string',
+        'csConv.' => 'array',
+        'parseFunc' => 'objectpath',
+        'parseFunc.' => 'array',
+        'HTMLparser' => 'boolean',
+        'HTMLparser.' => 'array',
+        'split.' => 'array',
+        'replacement.' => 'array',
+        'prioriCalc' => 'boolean',
+        'prioriCalc.' => 'array',
+        'char' => 'integer',
+        'char.' => 'array',
+        'intval' => 'boolean',
+        'intval.' => 'array',
+        'hash' => 'string',
+        'hash.' => 'array',
+        'round' => 'boolean',
+        'round.' => 'array',
+        'numberFormat.' => 'array',
+        'expandList' => 'boolean',
+        'expandList.' => 'array',
+        'date' => 'dateconf',
+        'date.' => 'array',
+        'strtotime' => 'strtotimeconf',
+        'strtotime.' => 'array',
+        'strftime' => 'strftimeconf',
+        'strftime.' => 'array',
+        'age' => 'boolean',
+        'age.' => 'array',
+        'case' => 'case',
+        'case.' => 'array',
+        'bytes' => 'boolean',
+        'bytes.' => 'array',
+        'substring' => 'parameters',
+        'substring.' => 'array',
+        'removeBadHTML' => 'boolean',
+        'removeBadHTML.' => 'array',
+        'cropHTML' => 'crop',
+        'cropHTML.' => 'array',
+        'stripHtml' => 'boolean',
+        'stripHtml.' => 'array',
+        'crop' => 'crop',
+        'crop.' => 'array',
+        'rawUrlEncode' => 'boolean',
+        'rawUrlEncode.' => 'array',
+        'htmlSpecialChars' => 'boolean',
+        'htmlSpecialChars.' => 'array',
+        'encodeForJavaScriptValue' => 'boolean',
+        'encodeForJavaScriptValue.' => 'array',
+        'doubleBrTag' => 'string',
+        'doubleBrTag.' => 'array',
+        'br' => 'boolean',
+        'br.' => 'array',
+        'brTag' => 'string',
+        'brTag.' => 'array',
+        'encapsLines.' => 'array',
+        'keywords' => 'boolean',
+        'keywords.' => 'array',
+        'innerWrap' => 'wrap',
+        'innerWrap.' => 'array',
+        'innerWrap2' => 'wrap',
+        'innerWrap2.' => 'array',
+        'fontTag' => 'wrap',
+        'fontTag.' => 'array',
+        'addParams.' => 'array',
+        'filelink.' => 'array',
+        'preCObject' => 'cObject',
+        'preCObject.' => 'array',
+        'postCObject' => 'cObject',
+        'postCObject.' => 'array',
+        'wrapAlign' => 'align',
+        'wrapAlign.' => 'array',
+        'typolink.' => 'array',
+        'TCAselectItem.' => 'array',
+        'space' => 'space',
+        'space.' => 'array',
+        'spaceBefore' => 'int',
+        'spaceBefore.' => 'array',
+        'spaceAfter' => 'int',
+        'spaceAfter.' => 'array',
+        'wrap' => 'wrap',
+        'wrap.' => 'array',
+        'noTrimWrap' => 'wrap',
+        'noTrimWrap.' => 'array',
+        'wrap2' => 'wrap',
+        'wrap2.' => 'array',
+        'dataWrap' => 'dataWrap',
+        'dataWrap.' => 'array',
+        'prepend' => 'cObject',
+        'prepend.' => 'array',
+        'append' => 'cObject',
+        'append.' => 'array',
+        'wrap3' => 'wrap',
+        'wrap3.' => 'array',
+        'orderedStdWrap' => 'stdWrap',
+        'orderedStdWrap.' => 'array',
+        'outerWrap' => 'wrap',
+        'outerWrap.' => 'array',
+        'insertData' => 'boolean',
+        'insertData.' => 'array',
+        'postUserFunc' => 'functionName',
+        'postUserFuncInt' => 'functionName',
+        'prefixComment' => 'string',
+        'prefixComment.' => 'array',
+        'editIcons' => 'string',
+        'editIcons.' => 'array',
+        'editPanel' => 'boolean',
+        'editPanel.' => 'array',
+        'cacheStore' => 'hook',
+        // this is a placeholder for storing the content in cache
+        'stdWrapPostProcess' => 'hook',
+        // this is a placeholder for the last Hook
+        'debug' => 'boolean',
+        'debug.' => 'array',
+        'debugFunc' => 'boolean',
+        'debugFunc.' => 'array',
+        'debugData' => 'boolean',
+        'debugData.' => 'array'
+    );
+
+    /**
+     * Class names for accordant content object names
+     *
+     * @var array
+     */
+    protected $contentObjectClassMap = array();
+
+    /**
+     * Holds ImageMagick parameters and extensions used for compression
+     *
+     * @var array
+     * @see IMGTEXT()
+     */
+    public $image_compression = array(
+        10 => array(
+            'params' => '',
+            'ext' => 'gif'
+        ),
+        11 => array(
+            'params' => '-colors 128',
+            'ext' => 'gif'
+        ),
+        12 => array(
+            'params' => '-colors 64',
+            'ext' => 'gif'
+        ),
+        13 => array(
+            'params' => '-colors 32',
+            'ext' => 'gif'
+        ),
+        14 => array(
+            'params' => '-colors 16',
+            'ext' => 'gif'
+        ),
+        15 => array(
+            'params' => '-colors 8',
+            'ext' => 'gif'
+        ),
+        20 => array(
+            'params' => '-quality 100',
+            'ext' => 'jpg'
+        ),
+        21 => array(
+            'params' => '-quality 90',
+            'ext' => 'jpg'
+        ),
+        22 => array(
+            'params' => '-quality 80',
+            'ext' => 'jpg'
+        ),
+        23 => array(
+            'params' => '-quality 70',
+            'ext' => 'jpg'
+        ),
+        24 => array(
+            'params' => '-quality 60',
+            'ext' => 'jpg'
+        ),
+        25 => array(
+            'params' => '-quality 50',
+            'ext' => 'jpg'
+        ),
+        26 => array(
+            'params' => '-quality 40',
+            'ext' => 'jpg'
+        ),
+        27 => array(
+            'params' => '-quality 30',
+            'ext' => 'jpg'
+        ),
+        28 => array(
+            'params' => '-quality 20',
+            'ext' => 'jpg'
+        ),
+        30 => array(
+            'params' => '-colors 256',
+            'ext' => 'png'
+        ),
+        31 => array(
+            'params' => '-colors 128',
+            'ext' => 'png'
+        ),
+        32 => array(
+            'params' => '-colors 64',
+            'ext' => 'png'
+        ),
+        33 => array(
+            'params' => '-colors 32',
+            'ext' => 'png'
+        ),
+        34 => array(
+            'params' => '-colors 16',
+            'ext' => 'png'
+        ),
+        35 => array(
+            'params' => '-colors 8',
+            'ext' => 'png'
+        ),
+        39 => array(
+            'params' => '',
+            'ext' => 'png'
+        )
+    );
+
+    /**
+     * ImageMagick parameters for image effects
+     *
+     * @var array
+     * @see IMGTEXT()
+     */
+    public $image_effects = array(
+        1 => '-rotate 90',
+        2 => '-rotate 270',
+        3 => '-rotate 180',
+        10 => '-colorspace GRAY',
+        11 => '-sharpen 70',
+        20 => '-normalize',
+        23 => '-contrast',
+        25 => '-gamma 1.3',
+        26 => '-gamma 0.8'
+    );
+
+    /**
+     * Loaded with the current data-record.
+     *
+     * If the instance of this class is used to render records from the database those records are found in this array.
+     * The function stdWrap has TypoScript properties that fetch field-data from this array.
+     *
+     * @var array
+     * @see start()
+     */
+    public $data = array();
+
+    /**
+     * @var string
+     */
+    protected $table = '';
+
+    /**
+     * Used for backup
+     *
+     * @var array
+     */
+    public $oldData = array();
+
+    /**
+     * If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
+     *
+     * @var string
+     */
+    public $alternativeData = '';
+
+    /**
+     * Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
+     *
+     * @var array
+     */
+    public $parameters = array();
+
+    /**
+     * @var string
+     */
+    public $currentValKey = 'currentValue_kidjls9dksoje';
+
+    /**
+     * This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation.
+     * Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
+     *
+     * @var string
+     */
+    public $currentRecord = '';
+
+    /**
+     * Set in RecordsContentObject and ContentContentObject to the current number of records selected in a query.
+     *
+     * @var int
+     */
+    public $currentRecordTotal = 0;
+
+    /**
+     * Incremented in RecordsContentObject and ContentContentObject before each record rendering.
+     *
+     * @var int
+     */
+    public $currentRecordNumber = 0;
+
+    /**
+     * Incremented in RecordsContentObject and ContentContentObject before each record rendering.
+     *
+     * @var int
+     */
+    public $parentRecordNumber = 0;
+
+    /**
+     * If the ContentObjectRender was started from ContentContentObject, RecordsContentObject or SearchResultContentObject this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
+     *
+     * @var array
+     */
+    public $parentRecord = array();
+
+    /**
+     * Is set to 1 if the instance of this cObj is executed from a *_INT plugin (see pagegen, bottom of document)
+     *
+     * @var bool
+     */
+    public $INT_include = 0;
+
+    /**
+     * This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request.
+     *
+     * @var array
+     */
+    public $checkPid_cache = array();
+
+    /**
+     * @var string
+     */
+    public $checkPid_badDoktypeList = '255';
+
+    /**
+     * This will be set by typoLink() to the url of the most recent link created.
+     *
+     * @var string
+     */
+    public $lastTypoLinkUrl = '';
+
+    /**
+     * DO. link target.
+     *
+     * @var string
+     */
+    public $lastTypoLinkTarget = '';
+
+    /**
+     * @var array
+     */
+    public $lastTypoLinkLD = array();
+
+    /**
+     * Caching substituteMarkerArrayCached function
+     *
+     * @var array
+     */
+    public $substMarkerCache = array();
+
+    /**
+     * array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
+     *
+     * @var array
+     */
+    public $recordRegister = array();
+
+    /**
+     * Additionally registered content object types and class names
+     *
+     * @var array
+     */
+    protected $cObjHookObjectsRegistry = array();
+
+    /**
+     * @var array
+     */
+    public $cObjHookObjectsArr = array();
+
+    /**
+     * Containing hook objects for stdWrap
+     *
+     * @var array
+     */
+    protected $stdWrapHookObjects = array();
+
+    /**
+     * Containing hook objects for getImgResource
+     *
+     * @var array
+     */
+    protected $getImgResourceHookObjects;
+
+    /**
+     * @var File Current file objects (during iterations over files)
+     */
+    protected $currentFile = null;
+
+    /**
+     * Set to TRUE by doConvertToUserIntObject() if USER object wants to become USER_INT
+     */
+    public $doConvertToUserIntObject = false;
+
+    /**
+     * Indicates current object type. Can hold one of OBJECTTYPE_ constants or FALSE.
+     * The value is set and reset inside USER() function. Any time outside of
+     * USER() it is FALSE.
+     */
+    protected $userObjectType = false;
+
+    /**
+     * @var array
+     */
+    protected $stopRendering = array();
+
+    /**
+     * @var int
+     */
+    protected $stdWrapRecursionLevel = 0;
+
+    /**
+     * @var TypoScriptFrontendController
+     */
+    protected $typoScriptFrontendController;
+
+    /**
+     * @var MarkerBasedTemplateService
+     */
+    protected $templateService;
+
+    /**
+     * Indicates that object type is USER.
+     *
+     * @see ContentObjectRender::$userObjectType
+     */
+    const OBJECTTYPE_USER_INT = 1;
+    /**
+     * Indicates that object type is USER.
+     *
+     * @see ContentObjectRender::$userObjectType
+     */
+    const OBJECTTYPE_USER = 2;
+
+    /**
+     * @param TypoScriptFrontendController $typoScriptFrontendController
+     */
+    public function __construct(TypoScriptFrontendController $typoScriptFrontendController = null)
+    {
+        $this->typoScriptFrontendController = $typoScriptFrontendController;
+        $this->contentObjectClassMap = $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'];
+        $this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
+    }
+
+    /**
+     * Prevent several objects from being serialized.
+     * If currentFile is set, it is either a File or a FileReference object. As the object itself can't be serialized,
+     * we have store a hash and restore the object in __wakeup()
+     *
+     * @return array
+     */
+    public function __sleep()
+    {
+        $vars = get_object_vars($this);
+        unset($vars['typoScriptFrontendController']);
+        if ($this->currentFile instanceof FileReference) {
+            $this->currentFile = 'FileReference:' . $this->currentFile->getUid();
+        } elseif ($this->currentFile instanceof File) {
+            $this->currentFile = 'File:' . $this->currentFile->getIdentifier();
+        } else {
+            unset($vars['currentFile']);
+        }
+        return array_keys($vars);
+    }
+
+    /**
+     * Restore currentFile from hash.
+     * If currentFile references a File, the identifier equals file identifier.
+     * If it references a FileReference the identifier equals the uid of the reference.
+     */
+    public function __wakeup()
+    {
+        if (isset($GLOBALS['TSFE'])) {
+            $this->typoScriptFrontendController = $GLOBALS['TSFE'];
+        }
+        if ($this->currentFile !== null && is_string($this->currentFile)) {
+            list($objectType, $identifier) = explode(':', $this->currentFile, 2);
+            try {
+                if ($objectType === 'File') {
+                    $this->currentFile = ResourceFactory::getInstance()->retrieveFileOrFolderObject($identifier);
+                } elseif ($objectType === 'FileReference') {
+                    $this->currentFile = ResourceFactory::getInstance()->getFileReferenceObject($identifier);
+                }
+            } catch (ResourceDoesNotExistException $e) {
+                $this->currentFile = null;
+            }
+        }
+    }
+
+    /**
+     * Allow injecting content object class map.
+     *
+     * This method is private API, please use configuration
+     * $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] to add new content objects
+     *
+     * @internal
+     * @param array $contentObjectClassMap
+     */
+    public function setContentObjectClassMap(array $contentObjectClassMap)
+    {
+        $this->contentObjectClassMap = $contentObjectClassMap;
+    }
+
+    /**
+     * Register a single content object name to class name
+     *
+     * This method is private API, please use configuration
+     * $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] to add new content objects
+     *
+     * @internal
+     * @param string $className
+     * @param string $contentObjectName
+     */
+    public function registerContentObjectClass($className, $contentObjectName)
+    {
+        $this->contentObjectClassMap[$contentObjectName] = $className;
+    }
+
+    /**
+     * Class constructor.
+     * Well, it has to be called manually since it is not a real constructor function.
+     * So after making an instance of the class, call this function and pass to it a database record and the tablename from where the record is from. That will then become the "current" record loaded into memory and accessed by the .fields property found in eg. stdWrap.
+     *
+     * @param array $data The record data that is rendered.
+     * @param string $table The table that the data record is from.
+     * @return void
+     */
+    public function start($data, $table = '')
+    {
+        $this->data = $data;
+        $this->table = $table;
+        $this->currentRecord = $table !== '' ? $table . ':' . $this->data['uid'] : '';
+        $this->parameters = array();
+        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
+                $this->cObjHookObjectsRegistry[$classArr[0]] = $classArr[1];
+            }
+        }
+        $this->stdWrapHookObjects = array();
+        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
+                $hookObject = GeneralUtility::getUserObj($classData);
+                if (!$hookObject instanceof ContentObjectStdWrapHookInterface) {
+                    throw new \UnexpectedValueException($classData . ' must implement interface ' . ContentObjectStdWrapHookInterface::class, 1195043965);
+                }
+                $this->stdWrapHookObjects[] = $hookObject;
+            }
+        }
+        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
+                $postInitializationProcessor = GeneralUtility::getUserObj($classData);
+                if (!$postInitializationProcessor instanceof ContentObjectPostInitHookInterface) {
+                    throw new \UnexpectedValueException($classData . ' must implement interface ' . ContentObjectPostInitHookInterface::class, 1274563549);
+                }
+                $postInitializationProcessor->postProcessContentObjectInitialization($this);
+            }
+        }
+    }
+
+    /**
+     * Returns the current table
+     *
+     * @return string
+     */
+    public function getCurrentTable()
+    {
+        return $this->table;
+    }
+
+    /**
+     * Gets the 'getImgResource' hook objects.
+     * The first call initializes the accordant objects.
+     *
+     * @return array The 'getImgResource' hook objects (if any)
+     */
+    protected function getGetImgResourceHookObjects()
+    {
+        if (!isset($this->getImgResourceHookObjects)) {
+            $this->getImgResourceHookObjects = array();
+            if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
+                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
+                    $hookObject = GeneralUtility::getUserObj($classData);
+                    if (!$hookObject instanceof ContentObjectGetImageResourceHookInterface) {
+                        throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetImageResourceHookInterface::class, 1218636383);
+                    }
+                    $this->getImgResourceHookObjects[] = $hookObject;
+                }
+            }
+        }
+        return $this->getImgResourceHookObjects;
+    }
+
+    /**
+     * Sets the internal variable parentRecord with information about current record.
+     * If the ContentObjectRender was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
+     *
+     * @param array $data The record array
+     * @param string $currentRecord This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
+     * @return void
+     * @access private
+     */
+    public function setParent($data, $currentRecord)
+    {
+        $this->parentRecord = array(
+            'data' => $data,
+            'currentRecord' => $currentRecord
+        );
+    }
+
+    /***********************************************
+     *
+     * CONTENT_OBJ:
+     *
+     ***********************************************/
+    /**
+     * Returns the "current" value.
+     * The "current" value is just an internal variable that can be used by functions to pass a single value on to another function later in the TypoScript processing.
+     * It's like "load accumulator" in the good old C64 days... basically a "register" you can use as you like.
+     * The TSref will tell if functions are setting this value before calling some other object so that you know if it holds any special information.
+     *
+     * @return mixed The "current" value
+     */
+    public function getCurrentVal()
+    {
+        return $this->data[$this->currentValKey];
+    }
+
+    /**
+     * Sets the "current" value.
+     *
+     * @param mixed $value The variable that you want to set as "current
+     * @return void
+     * @see getCurrentVal()
+     */
+    public function setCurrentVal($value)
+    {
+        $this->data[$this->currentValKey] = $value;
+    }
+
+    /**
+     * Rendering of a "numerical array" of cObjects from TypoScript
+     * Will call ->cObjGetSingle() for each cObject found and accumulate the output.
+     *
+     * @param array $setup array with cObjects as values.
+     * @param string $addKey A prefix for the debugging information
+     * @return string Rendered output from the cObjects in the array.
+     * @see cObjGetSingle()
+     */
+    public function cObjGet($setup, $addKey = '')
+    {
+        if (!is_array($setup)) {
+            return '';
+        }
+        $sKeyArray = TemplateService::sortedKeyList($setup);
+        $content = '';
+        foreach ($sKeyArray as $theKey) {
+            $theValue = $setup[$theKey];
+            if ((int)$theKey && strpos($theKey, '.') === false) {
+                $conf = $setup[$theKey . '.'];
+                $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey);
+            }
+        }
+        return $content;
+    }
+
+    /**
+     * Renders a content object
+     *
+     * @param string $name The content object name, eg. "TEXT" or "USER" or "IMAGE
+     * @param array $conf The array with TypoScript properties for the content object
+     * @param string $TSkey A string label used for the internal debugging tracking.
+     * @return string cObject output
+     * @throws \UnexpectedValueException
+     */
+    public function cObjGetSingle($name, $conf, $TSkey = '__')
+    {
+        $content = '';
+        // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
+        $this->getTypoScriptFrontendController()->cObjectDepthCounter--;
+        if ($this->getTypoScriptFrontendController()->cObjectDepthCounter > 0) {
+            $timeTracker = $this->getTimeTracker();
+            $name = trim($name);
+            if ($timeTracker->LR) {
+                $timeTracker->push($TSkey, $name);
+            }
+            // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
+            if ($name[0] === '<') {
+                $key = trim(substr($name, 1));
+                $cF = GeneralUtility::makeInstance(TypoScriptParser::class);
+                // $name and $conf is loaded with the referenced values.
+                $confOverride = is_array($conf) ? $conf : array();
+                list($name, $conf) = $cF->getVal($key, $this->getTypoScriptFrontendController()->tmpl->setup);
+                $conf = array_replace_recursive(is_array($conf) ? $conf : array(), $confOverride);
+                // Getting the cObject
+                $timeTracker->incStackPointer();
+                $content .= $this->cObjGetSingle($name, $conf, $key);
+                $timeTracker->decStackPointer();
+            } else {
+                $hooked = false;
+                // Application defined cObjects
+                if (!empty($this->cObjHookObjectsRegistry[$name])) {
+                    if (empty($this->cObjHookObjectsArr[$name])) {
+                        $this->cObjHookObjectsArr[$name] = GeneralUtility::getUserObj($this->cObjHookObjectsRegistry[$name]);
+                    }
+                    $hookObj = $this->cObjHookObjectsArr[$name];
+                    if (method_exists($hookObj, 'cObjGetSingleExt')) {
+                        $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
+                        $hooked = true;
+                    }
+                }
+                if (!$hooked) {
+                    $contentObject = $this->getContentObject($name);
+                    if ($contentObject) {
+                        $content .= $this->render($contentObject, $conf);
+                    } else {
+                        // Call hook functions for extra processing
+                        if ($name && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
+                            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
+                                $hookObject = GeneralUtility::getUserObj($classData);
+                                if (!$hookObject instanceof ContentObjectGetSingleHookInterface) {
+                                    throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetSingleHookInterface::class, 1195043731);
+                                }
+                                /** @var $hookObject ContentObjectGetSingleHookInterface */
+                                $content .= $hookObject->getSingleContentObject($name, (array)$conf, $TSkey, $this);
+                            }
+                        } else {
+                            // Log error in AdminPanel
+                            $warning = sprintf('Content Object "%s" does not exist', $name);
+                            $timeTracker->setTSlogMessage($warning, 2);
+                        }
+                    }
+                }
+            }
+            if ($timeTracker->LR) {
+                $timeTracker->pull($content);
+            }
+        }
+        // Increasing on exit...
+        $this->getTypoScriptFrontendController()->cObjectDepthCounter++;
+        return $content;
+    }
+
+    /**
+     * Returns a new content object of type $name.
+     * This content object needs to be registered as content object
+     * in $this->contentObjectClassMap
+     *
+     * @param string $name
+     * @return NULL|AbstractContentObject
+     * @throws ContentRenderingException
+     */
+    public function getContentObject($name)
+    {
+        if (!isset($this->contentObjectClassMap[$name])) {
+            return null;
+        }
+        $fullyQualifiedClassName = $this->contentObjectClassMap[$name];
+        $contentObject = GeneralUtility::makeInstance($fullyQualifiedClassName, $this);
+        if (!($contentObject instanceof AbstractContentObject)) {
+            throw new ContentRenderingException(sprintf('Registered content object class name "%" must be an instance of AbstractContentObject, but is not!', $fullyQualifiedClassName), 1422564295);
+        }
+        return $contentObject;
+    }
+
+    /********************************************
+     *
+     * Functions rendering content objects (cObjects)
+     *
+     ********************************************/
+
+    /**
+     * Renders a content object by taking exception and cache handling
+     * into consideration
+     *
+     * @param AbstractContentObject $contentObject Content object instance
+     * @param array $configuration Array of TypoScript properties
+     *
+     * @throws ContentRenderingException
+     * @throws \Exception
+     * @return string
+     */
+    public function render(AbstractContentObject $contentObject, $configuration = array())
+    {
+        $content = '';
+
+        // Evaluate possible cache and return
+        $cacheConfiguration = isset($configuration['cache.']) ? $configuration['cache.'] : null;
+        if ($cacheConfiguration !== null) {
+            unset($configuration['cache.']);
+            $cache = $this->getFromCache($cacheConfiguration);
+            if ($cache !== false) {
+                return $cache;
+            }
+        }
+
+        // Render content
+        try {
+            $content .= $contentObject->render($configuration);
+        } catch (ContentRenderingException $exception) {
+            // Content rendering Exceptions indicate a critical problem which should not be
+            // caught e.g. when something went wrong with Exception handling itself
+            throw $exception;
+        } catch (\Exception $exception) {
+            $exceptionHandler = $this->createExceptionHandler($configuration);
+            if ($exceptionHandler === null) {
+                throw $exception;
+            } else {
+                $content = $exceptionHandler->handle($exception, $contentObject, $configuration);
+            }
+        }
+
+        // Store cache
+        if ($cacheConfiguration !== null) {
+            $key = $this->calculateCacheKey($cacheConfiguration);
+            if (!empty($key)) {
+                /** @var $cacheFrontend \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend */
+                $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
+                $tags = $this->calculateCacheTags($cacheConfiguration);
+                $lifetime = $this->calculateCacheLifetime($cacheConfiguration);
+                $cacheFrontend->set($key, $content, $tags, $lifetime);
+            }
+        }
+
+        return $content;
+    }
+
+    /**
+     * Creates the content object exception handler from local content object configuration
+     * or, from global configuration if not explicitly disabled in local configuration
+     *
+     * @param array $configuration
+     * @return NULL|ExceptionHandlerInterface
+     * @throws ContentRenderingException
+     */
+    protected function createExceptionHandler($configuration = array())
+    {
+        $exceptionHandler = null;
+        $exceptionHandlerClassName = $this->determineExceptionHandlerClassName($configuration);
+        if (!empty($exceptionHandlerClassName)) {
+            $exceptionHandler = GeneralUtility::makeInstance($exceptionHandlerClassName, $this->mergeExceptionHandlerConfiguration($configuration));
+            if (!$exceptionHandler instanceof ExceptionHandlerInterface) {
+                throw new ContentRenderingException('An exception handler was configured but the class does not exist or does not implement the ExceptionHandlerInterface', 1403653369);
+            }
+        }
+
+        return $exceptionHandler;
+    }
+
+    /**
+     * Determine exception handler class name from global and content object configuration
+     *
+     * @param array $configuration
+     * @return string|NULL
+     */
+    protected function determineExceptionHandlerClassName($configuration)
+    {
+        $exceptionHandlerClassName = null;
+        $tsfe = $this->getTypoScriptFrontendController();
+        if (!isset($tsfe->config['config']['contentObjectExceptionHandler'])) {
+            if (GeneralUtility::getApplicationContext()->isProduction()) {
+                $exceptionHandlerClassName = '1';
+            }
+        } else {
+            $exceptionHandlerClassName = $tsfe->config['config']['contentObjectExceptionHandler'];
+        }
+
+        if (isset($configuration['exceptionHandler'])) {
+            $exceptionHandlerClassName = $configuration['exceptionHandler'];
+        }
+
+        if ($exceptionHandlerClassName === '1') {
+            $exceptionHandlerClassName = ProductionExceptionHandler::class;
+        }
+
+        return $exceptionHandlerClassName;
+    }
+
+    /**
+     * Merges global exception handler configuration with the one from the content object
+     * and returns the merged exception handler configuration
+     *
+     * @param array $configuration
+     * @return array
+     */
+    protected function mergeExceptionHandlerConfiguration($configuration)
+    {
+        $exceptionHandlerConfiguration = array();
+        $tsfe = $this->getTypoScriptFrontendController();
+        if (!empty($tsfe->config['config']['contentObjectExceptionHandler.'])) {
+            $exceptionHandlerConfiguration = $tsfe->config['config']['contentObjectExceptionHandler.'];
+        }
+        if (!empty($configuration['exceptionHandler.'])) {
+            $exceptionHandlerConfiguration = array_replace_recursive($exceptionHandlerConfiguration, $configuration['exceptionHandler.']);
+        }
+
+        return $exceptionHandlerConfiguration;
+    }
+
+    /**
+     * Retrieves a type of object called as USER or USER_INT. Object can detect their
+     * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the
+     * current object execution. In all other cases it will return FALSE to indicate
+     * a call out of context.
+     *
+     * @return mixed One of OBJECTTYPE_ class constants or FALSE
+     */
+    public function getUserObjectType()
+    {
+        return $this->userObjectType;
+    }
+
+    /**
+     * Sets the user object type
+     *
+     * @param mixed $userObjectType
+     * @return void
+     */
+    public function setUserObjectType($userObjectType)
+    {
+        $this->userObjectType = $userObjectType;
+    }
+
+    /**
+     * Requests the current USER object to be converted to USER_INT.
+     *
+     * @return void
+     */
+    public function convertToUserIntObject()
+    {
+        if ($this->userObjectType !== self::OBJECTTYPE_USER) {
+            $this->getTimeTracker()->setTSlogMessage(ContentObjectRenderer::class . '::convertToUserIntObject() is called in the wrong context or for the wrong object type', 2);
+        } else {
+            $this->doConvertToUserIntObject = true;
+        }
+    }
+
+    /************************************
+     *
+     * Various helper functions for content objects:
+     *
+     ************************************/
+    /**
+     * Converts a given config in Flexform to a conf-array
+     *
+     * @param string|array $flexData Flexform data
+     * @param array $conf Array to write the data into, by reference
+     * @param bool $recursive Is set if called recursive. Don't call function with this parameter, it's used inside the function only
+     * @return void
+     */
+    public function readFlexformIntoConf($flexData, &$conf, $recursive = false)
+    {
+        if ($recursive === false && is_string($flexData)) {
+            $flexData = GeneralUtility::xml2array($flexData, 'T3');
+        }
+        if (is_array($flexData) && isset($flexData['data']['sDEF']['lDEF'])) {
+            $flexData = $flexData['data']['sDEF']['lDEF'];
+        }
+        if (!is_array($flexData)) {
+            return;
+        }
+        foreach ($flexData as $key => $value) {
+            if (!is_array($value)) {
+                continue;
+            }
+            if (isset($value['el'])) {
+                if (is_array($value['el']) && !empty($value['el'])) {
+                    foreach ($value['el'] as $ekey => $element) {
+                        if (isset($element['vDEF'])) {
+                            $conf[$ekey] = $element['vDEF'];
+                        } else {
+                            if (is_array($element)) {
+                                $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], true);
+                            } else {
+                                $this->readFlexformIntoConf($element, $conf[$key][$ekey], true);
+                            }
+                        }
+                    }
+                } else {
+                    $this->readFlexformIntoConf($value['el'], $conf[$key], true);
+                }
+            }
+            if (isset($value['vDEF'])) {
+                $conf[$key] = $value['vDEF'];
+            }
+        }
+    }
+
+    /**
+     * Returns all parents of the given PID (Page UID) list
+     *
+     * @param string $pidList A list of page Content-Element PIDs (Page UIDs) / stdWrap
+     * @param array $pidConf stdWrap array for the list
+     * @return string A list of PIDs
+     * @access private
+     */
+    public function getSlidePids($pidList, $pidConf)
+    {
+        $pidList = isset($pidConf) ? trim($this->stdWrap($pidList, $pidConf)) : trim($pidList);
+        if ($pidList === '') {
+            $pidList = 'this';
+        }
+        $tsfe = $this->getTypoScriptFrontendController();
+        $listArr = null;
+        if (trim($pidList)) {
+            $listArr = GeneralUtility::intExplode(',', str_replace('this', $tsfe->contentPid, $pidList));
+            $listArr = $this->checkPidArray($listArr);
+        }
+        $pidList = array();
+        if (is_array($listArr) && !empty($listArr)) {
+            foreach ($listArr as $uid) {
+                $page = $tsfe->sys_page->getPage($uid);
+                if (!$page['is_siteroot']) {
+                    $pidList[] = $page['pid'];
+                }
+            }
+        }
+        return implode(',', $pidList);
+    }
+
+    /**
+     * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
+     * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript.
+     * This function is called by "$this->cImage($conf['file'], $conf);" from IMAGE().
+     *
+     * @param string $file File TypoScript resource
+     * @param array $conf TypoScript configuration properties
+     * @return string <img> tag, (possibly wrapped in links and other HTML) if any image found.
+     * @access private
+     * @see IMAGE()
+     */
+    public function cImage($file, $conf)
+    {
+        $tsfe = $this->getTypoScriptFrontendController();
+        $info = $this->getImgResource($file, $conf['file.']);
+        $tsfe->lastImageInfo = $info;
+        if (!is_array($info)) {
+            return '';
+        }
+        if (is_file(PATH_site . $info['3'])) {
+            $source = $tsfe->absRefPrefix . GeneralUtility::rawUrlEncodeFP($info['3']);
+        } else {
+            $source = $info[3];
+        }
+
+        $layoutKey = $this->stdWrap($conf['layoutKey'], $conf['layoutKey.']);
+        $imageTagTemplate = $this->getImageTagTemplate($layoutKey, $conf);
+        $sourceCollection = $this->getImageSourceCollection($layoutKey, $conf, $file);
+
+        // This array is used to collect the image-refs on the page...
+        $tsfe->imagesOnPage[] = $source;
+        $altParam = $this->getAltParam($conf);
+        $params = $this->stdWrapValue('params', $conf);
+        if ($params !== '' && $params[0] !== ' ') {
+            $params = ' ' . $params;
+        }
+
+        $imageTagValues = array(
+            'width' =>  (int)$info[0],
+            'height' => (int)$info[1],
+            'src' => htmlspecialchars($source),
+            'params' => $params,
+            'altParams' => $altParam,
+            'border' =>  $this->getBorderAttr(' border="' . (int)$conf['border'] . '"'),
+            'sourceCollection' => $sourceCollection,
+            'selfClosingTagSlash' => (!empty($tsfe->xhtmlDoctype) ? ' /' : ''),
+        );
+
+        $theValue = $this->substituteMarkerArray($imageTagTemplate, $imageTagValues, '###|###', true, true);
+
+        $linkWrap = isset($conf['linkWrap.']) ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.']) : $conf['linkWrap'];
+        if ($linkWrap) {
+            $theValue = $this->linkWrap($theValue, $linkWrap);
+        } elseif ($conf['imageLinkWrap']) {
+            $originalFile = !empty($info['originalFile']) ? $info['originalFile'] : $info['origFile'];
+            $theValue = $this->imageLinkWrap($theValue, $originalFile, $conf['imageLinkWrap.']);
+        }
+        $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
+        if ((string)$wrap !== '') {
+            $theValue = $this->wrap($theValue, $conf['wrap']);
+        }
+        return $theValue;
+    }
+
+    /**
+     * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict, xhtml_11 or html5
+     * or if the config parameter 'disableImgBorderAttr' is not set.
+     *
+     * @param string $borderAttr The border attribute
+     * @return string The border attribute
+     */
+    public function getBorderAttr($borderAttr)
+    {
+        $tsfe = $this->getTypoScriptFrontendController();
+        $docType = $tsfe->xhtmlDoctype;
+        if (
+            $docType !== 'xhtml_strict' && $docType !== 'xhtml_11'
+            && $tsfe->config['config']['doctype'] !== 'html5'
+            && !$tsfe->config['config']['disableImgBorderAttr']
+        ) {
+            return $borderAttr;
+        }
+        return '';
+    }
+
+    /**
+     * Returns the html-template for rendering the image-Tag if no template is defined via typoscript the
+     * default <img> tag template is returned
+     *
+     * @param string $layoutKey rendering key
+     * @param array $conf TypoScript configuration properties
+     * @return string
+     */
+    public function getImageTagTemplate($layoutKey, $conf)
+    {
+        if ($layoutKey && isset($conf['layout.']) && isset($conf['layout.'][$layoutKey . '.'])) {
+            $imageTagLayout = $this->stdWrap($conf['layout.'][$layoutKey . '.']['element'], $conf['layout.'][$layoutKey . '.']['element.']);
+        } else {
+            $imageTagLayout = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
+        }
+        return $imageTagLayout;
+    }
+
+    /**
+     * Render alternate sources for the image tag. If no source collection is given an empty string is returned.
+     *
+     * @param string $layoutKey rendering key
+     * @param array $conf TypoScript configuration properties
+     * @param string $file
+     * @throws \UnexpectedValueException
+     * @return string
+     */
+    public function getImageSourceCollection($layoutKey, $conf, $file)
+    {
+        $sourceCollection = '';
+        if ($layoutKey && $conf['sourceCollection.'] && ($conf['layout.'][$layoutKey . '.']['source'] || $conf['layout.'][$layoutKey . '.']['source.'])) {
+
+            // find active sourceCollection
+            $activeSourceCollections = array();
+            foreach ($conf['sourceCollection.'] as $sourceCollectionKey => $sourceCollectionConfiguration) {
+                if (substr($sourceCollectionKey, -1) === '.') {
+                    if (empty($sourceCollectionConfiguration['if.']) || $this->checkIf($sourceCollectionConfiguration['if.'])) {
+                        $activeSourceCollections[] = $sourceCollectionConfiguration;
+                    }
+                }
+            }
+
+            // apply option split to configurations
+            $tsfe = $this->getTypoScriptFrontendController();
+            $srcLayoutOptionSplitted = $tsfe->tmpl->splitConfArray($conf['layout.'][$layoutKey . '.'], count($activeSourceCollections));
+
+            // render sources
+            foreach ($activeSourceCollections as $key => $sourceConfiguration) {
+                $sourceLayout = $this->stdWrap($srcLayoutOptionSplitted[$key]['source'], $srcLayoutOptionSplitted[$key]['source.']);
+
+                $sourceRenderConfiguration = array(
+                    'file' => $file,
+                    'file.' => $conf['file.']
+                );
+
+                if (isset($sourceConfiguration['quality']) || isset($sourceConfiguration['quality.'])) {
+                    $imageQuality = isset($sourceConfiguration['quality']) ? $sourceConfiguration['quality'] : '';
+                    if (isset($sourceConfiguration['quality.'])) {
+                        $imageQuality = $this->stdWrap($sourceConfiguration['quality'], $sourceConfiguration['quality.']);
+                    }
+                    if ($imageQuality) {
+                        $sourceRenderConfiguration['file.']['params'] = '-quality ' . (int)$imageQuality;
+                    }
+                }
+
+                if (isset($sourceConfiguration['pixelDensity'])) {
+                    $pixelDensity = (int)$this->stdWrap($sourceConfiguration['pixelDensity'], $sourceConfiguration['pixelDensity.']);
+                } else {
+                    $pixelDensity = 1;
+                }
+                $dimensionKeys = array('width', 'height', 'maxW', 'minW', 'maxH', 'minH');
+                foreach ($dimensionKeys as $dimensionKey) {
+                    $dimension = $this->stdWrap($sourceConfiguration[$dimensionKey], $sourceConfiguration[$dimensionKey . '.']);
+                    if (!$dimension) {
+                        $dimension = $this->stdWrap($conf['file.'][$dimensionKey], $conf['file.'][$dimensionKey . '.']);
+                    }
+                    if ($dimension) {
+                        if (strstr($dimension, 'c') !== false && ($dimensionKey === 'width' || $dimensionKey === 'height')) {
+                            $dimensionParts = explode('c', $dimension, 2);
+                            $dimension = ((int)$dimensionParts[0] * $pixelDensity) . 'c';
+                            if ($dimensionParts[1]) {
+                                $dimension .= $dimensionParts[1];
+                            }
+                        } else {
+                            $dimension = (int)$dimension * $pixelDensity;
+                        }
+                        $sourceRenderConfiguration['file.'][$dimensionKey] = $dimension;
+                        // Remove the stdWrap properties for dimension as they have been processed already above.
+                        unset($sourceRenderConfiguration['file.'][$dimensionKey . '.']);
+                    }
+                }
+                $sourceInfo = $this->getImgResource($sourceRenderConfiguration['file'], $sourceRenderConfiguration['file.']);
+                if ($sourceInfo) {
+                    $sourceConfiguration['width'] = $sourceInfo[0];
+                    $sourceConfiguration['height'] = $sourceInfo[1];
+                    $urlPrefix = '';
+                    if (parse_url($sourceInfo[3], PHP_URL_HOST) === null) {
+                        $urlPrefix = $tsfe->absRefPrefix;
+                    }
+                    $sourceConfiguration['src'] = htmlspecialchars($urlPrefix . $sourceInfo[3]);
+                    $sourceConfiguration['selfClosingTagSlash'] = !empty($tsfe->xhtmlDoctype) ? ' /' : '';
+
+                    $oneSourceCollection = $this->substituteMarkerArray($sourceLayout, $sourceConfiguration, '###|###', true, true);
+
+                    if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'])) {
+                        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'] as $classData) {
+                            $hookObject = GeneralUtility::getUserObj($classData);
+                            if (!$hookObject instanceof ContentObjectOneSourceCollectionHookInterface) {
+                                throw new \UnexpectedValueException(
+                                    '$hookObject must implement interface ' . ContentObjectOneSourceCollectionHookInterface::class,
+                                    1380007853
+                                );
+                            }
+                            $oneSourceCollection = $hookObject->getOneSourceCollection((array)$sourceRenderConfiguration, (array)$sourceConfiguration, $oneSourceCollection, $this);
+                        }
+                    }
+
+                    $sourceCollection .= $oneSourceCollection;
+                }
+            }
+        }
+        return $sourceCollection;
+    }
+
+    /**
+     * Wraps the input string in link-tags that opens the image in a new window.
+     *
+     * @param string $string String to wrap, probably an <img> tag
+     * @param string|File|FileReference $imageFile The original image file
+     * @param array $conf TypoScript properties for the "imageLinkWrap" function
+     * @return string The input string, $string, wrapped as configured.
+     * @see cImage()
+     */
+    public function imageLinkWrap($string, $imageFile, $conf)
+    {
+        $string = (string)$string;
+        $enable = isset($conf['enable.']) ? $this->stdWrap($conf['enable'], $conf['enable.']) : $conf['enable'];
+        if (!$enable) {
+            return $string;
+        }
+        $content = (string)$this->typoLink($string, $conf['typolink.']);
+        if (isset($conf['file.'])) {
+            $imageFile = $this->stdWrap($imageFile, $conf['file.']);
+        }
+
+        if ($imageFile instanceof File) {
+            $file = $imageFile;
+        } elseif ($imageFile instanceof FileReference) {
+            $file = $imageFile->getOriginalFile();
+        } else {
+            if (MathUtility::canBeInterpretedAsInteger($imageFile)) {
+                $file = ResourceFactory::getInstance()->getFileObject((int)$imageFile);
+            } else {
+                $file = ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($imageFile);
+            }
+        }
+
+        // Create imageFileLink if not created with typolink
+        if ($content === $string) {
+            $parameterNames = array('width', 'height', 'effects', 'bodyTag', 'title', 'wrap');
+            $parameters = array();
+            $sample = isset($conf['sample.']) ? $this->stdWrap($conf['sample'], $conf['sample.']) : $conf['sample'];
+            if ($sample) {
+                $parameters['sample'] = 1;
+            }
+            foreach ($parameterNames as $parameterName) {
+                if (isset($conf[$parameterName . '.'])) {
+                    $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName . '.']);
+                }
+                if (isset($conf[$parameterName]) && $conf[$parameterName]) {
+                    $parameters[$parameterName] = $conf[$parameterName];
+                }
+            }
+            $parametersEncoded = base64_encode(serialize($parameters));
+            $hmac = GeneralUtility::hmac(implode('|', array($file->getUid(), $parametersEncoded)));
+            $params = '&md5=' . $hmac;
+            foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
+                $params .= '&parameters' . rawurlencode('[') . $index . rawurlencode(']') . '=' . rawurlencode($chunk);
+            }
+            $url = $this->getTypoScriptFrontendController()->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . $file->getUid() . $params;
+            $directImageLink = isset($conf['directImageLink.']) ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.']) : $conf['directImageLink'];
+            if ($directImageLink) {
+                $imgResourceConf = array(
+                    'file' => $imageFile,
+                    'file.' => $conf
+                );
+                $url = $this->cObjGetSingle('IMG_RESOURCE', $imgResourceConf);
+                if (!$url) {
+                    // If no imagemagick / gm is available
+                    $url = $imageFile;
+                }
+            }
+            // Create TARGET-attribute only if the right doctype is used
+            $target = '';
+            $xhtmlDocType = $this->getTypoScriptFrontendController()->xhtmlDoctype;
+            if ($xhtmlDocType !== 'xhtml_strict' && $xhtmlDocType !== 'xhtml_11') {
+                $target = isset($conf['target.'])
+                    ? (string)$this->stdWrap($conf['target'], $conf['target.'])
+                    : (string)$conf['target'];
+                if ($target === '') {
+                    $target = 'thePicture';
+                }
+            }
+            $a1 = '';
+            $a2 = '';
+            $conf['JSwindow'] = isset($conf['JSwindow.']) ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.']) : $conf['JSwindow'];
+            if ($conf['JSwindow']) {
+                if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
+                    $altUrl = isset($conf['JSwindow.']['altUrl.']) ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.']) : $conf['JSwindow.']['altUrl'];
+                    if ($altUrl) {
+                        $url = $altUrl . ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' . rawurlencode($imageFile) . $params);
+                    }
+                }
+
+                $processedFile = $file->process('Image.CropScaleMask', $conf);
+                $JSwindowExpand = isset($conf['JSwindow.']['expand.']) ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.']) : $conf['JSwindow.']['expand'];
+                $offset = GeneralUtility::intExplode(',', $JSwindowExpand . ',');
+                $newWindow = isset($conf['JSwindow.']['newWindow.']) ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.']) : $conf['JSwindow.']['newWindow'];
+                $onClick = 'openPic('
+                    . GeneralUtility::quoteJSvalue($this->getTypoScriptFrontendController()->baseUrlWrap($url)) . ','
+                    . '\'' . ($newWindow ? md5($url) : 'thePicture') . '\','
+                    . GeneralUtility::quoteJSvalue('width=' . ($processedFile->getProperty('width') + $offset[0])
+                        . ',height=' . ($processedFile->getProperty('height') + $offset[1]) . ',status=0,menubar=0')
+                    . '); return false;';
+                $a1 = '<a href="' . htmlspecialchars($url) . '"'
+                    . ' onclick="' . htmlspecialchars($onClick) . '"'
+                    . ($target !== '' ? ' target="' . $target . '"' : '')
+                    . $this->getTypoScriptFrontendController()->ATagParams . '>';
+                $a2 = '</a>';
+                $this->getTypoScriptFrontendController()->setJS('openPic');
+            } else {
+                $conf['linkParams.']['parameter'] = $url;
+                $string = $this->typoLink($string, $conf['linkParams.']);
+            }
+            if (isset($conf['stdWrap.'])) {
+                $string = $this->stdWrap($string, $conf['stdWrap.']);
+            }
+            $content = $a1 . $string . $a2;
+        }
+        return $content;
+    }
+
+    /**
+     * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is.
+     *
+     * @param string $fName The filename, being a TypoScript resource data type
+     * @param string $addParams Additional parameters (attributes). Default is empty alt and title tags.
+     * @return string If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string
+     * @see FILE()
+     */
+    public function fileResource($fName, $addParams = 'alt="" title=""')
+    {
+        $tsfe = $this->getTypoScriptFrontendController();
+        $incFile = $tsfe->tmpl->getFileName($fName);
+        if ($incFile && file_exists($incFile)) {
+            $fileInfo = GeneralUtility::split_fileref($incFile);
+            $extension = $fileInfo['fileext'];
+            if ($extension === 'jpg' || $extension === 'jpeg' || $extension === 'gif' || $extension === 'png') {
+                $imgFile = $incFile;
+                $imgInfo = @getImageSize($imgFile);
+                return '<img src="' . $tsfe->absRefPrefix . $imgFile . '" width="' . (int)$imgInfo[0] . '" height="' . (int)$imgInfo[1] . '"' . $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />';
+            } elseif (filesize($incFile) < 1024 * 1024) {
+                return $tsfe->tmpl->fileContent($incFile);
+            }
+        }
+        return '';
+    }
+
+    /**
+     * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value.
+     * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content.
+     * Therefore you should call this function with the last-changed timestamp of any element you display.
+     *
+     * @param int $tstamp Unix timestamp (number of seconds since 1970)
+     * @return void
+     * @see TypoScriptFrontendController::setSysLastChanged()
+     */
+    public function lastChanged($tstamp)
+    {
+        $tstamp = (int)$tstamp;
+        $tsfe = $this->getTypoScriptFrontendController();
+        if ($tstamp > (int)$tsfe->register['SYS_LASTCHANGED']) {
+            $tsfe->register['SYS_LASTCHANGED'] = $tstamp;
+        }
+    }
+
+    /**
+     * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well.
+     * The "linkWrap" data type means that this function will find any integer encapsulated in {} (curly braces) in the first wrap part and substitute it with the corresponding page uid from the rootline where the found integer is pointing to the key in the rootline. See link below.
+     *
+     * @param string $content Input string
+     * @param string $wrap A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string
+     * @return string Wrapped output string
+     * @see wrap(), cImage(), FILE()
+     */
+    public function linkWrap($content, $wrap)
+    {
+        $wrapArr = explode('|', $wrap);
+        if (preg_match('/\\{([0-9]*)\\}/', $wrapArr[0], $reg)) {
+            if ($uid = $this->getTypoScriptFrontendController()->tmpl->rootLine[$reg[1]]['uid']) {
+                $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
+            }
+        }
+        return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
+    }
+
+    /**
+     * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element.
+     * From the $conf array it implements the properties "altText", "titleText" and "longdescURL"
+     *
+     * @param array $conf TypoScript configuration properties
+     * @param bool $longDesc If set, the longdesc attribute will be generated - must only be used for img elements!
+     * @return string Parameter string containing alt and title parameters (if any)
+     * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink()
+     */
+    public function getAltParam($conf, $longDesc = true)
+    {
+        $altText = isset($conf['altText.']) ? trim($this->stdWrap($conf['altText'], $conf['altText.'])) : trim($conf['altText']);
+        $titleText = isset($conf['titleText.']) ? trim($this->stdWrap($conf['titleText'], $conf['titleText.'])) : trim($conf['titleText']);
+        if (isset($conf['longdescURL.']) && $this->getTypoScriptFrontendController()->config['config']['doctype'] != 'html5') {
+            $longDescUrl = $this->typoLink_URL($conf['longdescURL.']);
+        } else {
+            $longDescUrl = trim($conf['longdescURL']);
+        }
+        $longDescUrl = strip_tags($longDescUrl);
+
+        // "alt":
+        $altParam = ' alt="' . htmlspecialchars($altText) . '"';
+        // "title":
+        $emptyTitleHandling = isset($conf['emptyTitleHandling.']) ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.']) : $conf['emptyTitleHandling'];
+        // Choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
+        if ($titleText || $emptyTitleHandling === 'keepEmpty') {
+            $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
+        } elseif (!$titleText && $emptyTitleHandling === 'useAlt') {
+            $altParam .= ' title="' . htmlspecialchars($altText) . '"';
+        }
+        // "longDesc" URL
+        if ($longDesc && !empty($longDescUrl)) {
+            $altParam .= ' longdesc="' . htmlspecialchars($longDescUrl) . '"';
+        }
+        return $altParam;
+    }
+
+    /**
+     * An abstraction method to add parameters to an A tag.
+     * Uses the ATagParams property.
+     *
+     * @param array $conf TypoScript configuration properties
+     * @param bool|int $addGlobal If set, will add the global config.ATagParams to the link
+     * @return string String containing the parameters to the A tag (if non empty, with a leading space)
+     * @see IMGTEXT(), filelink(), makelinks(), typolink()
+     */
+    public function getATagParams($conf, $addGlobal = 1)
+    {
+        $aTagParams = '';
+        if ($conf['ATagParams.']) {
+            $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
+        } elseif ($conf['ATagParams']) {
+            $aTagParams = ' ' . $conf['ATagParams'];
+        }
+        if ($addGlobal) {
+            $aTagParams = ' ' . trim($this->getTypoScriptFrontendController()->ATagParams . $aTagParams);
+        }
+        // Extend params
+        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'])) {
+            $_params = array(
+                'conf' => &$conf,
+                'aTagParams' => &$aTagParams
+            );
+            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'] as $objRef) {
+                $processor =& GeneralUtility::getUserObj($objRef);
+                $aTagParams = $processor->process($_params, $this);
+            }
+        }
+
+        $aTagParams = trim($aTagParams);
+        if (!empty($aTagParams)) {
+            $aTagParams = ' ' . $aTagParams;
+        }
+
+        return $aTagParams;
+    }
+
+    /**
+     * All extension links should ask this function for additional properties to their tags.
+     * Designed to add for instance an "onclick" property for site tracking systems.
+     *
+     * @param string $URL URL of the website
+     * @param string $TYPE
+     * @return string The additional tag properties
+     */
+    public function extLinkATagParams($URL, $TYPE)
+    {
+        $out = '';
+        if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
+            $extLinkATagParamsHandler = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']);
+            if (method_exists($extLinkATagParamsHandler, 'main')) {
+                $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
+            }
+        }
+        return trim($out) ? ' ' . trim($out) : '';
+    }
+
+    /***********************************************
+     *
+     * HTML template processing functions
+     *
+     ***********************************************/
+    /**
+     * Returns a subpart from the input content stream.
+     * A subpart is a part of the input stream which is encapsulated in a
+     * string matching the input string, $marker. If this string is found
+     * inside of HTML comment tags the start/end points of the content block
+     * returned will be that right outside that comment block.
+     * Example: The contennt string is
+     * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?"
+     * If $marker is "###sub1###" then the content returned is
+     * " World. How are ". The input content string could just as well have
+     * been "Hello ###sub1### World. How are ###sub1### you?" and the result
+     * would be the same
+     * Wrapper for \TYPO3\CMS\Core\Utility\MarkerBasedTemplateService::getSubpart which behaves identical
+     *
+     * @param string $content The content stream, typically HTML template content.
+     * @param string $marker The marker string, typically on the form "###[the marker string]###
+     * @return string The subpart found, if found.
+     */
+    public function getSubpart($content, $marker)
+    {
+        return $this->templateService->getSubpart($content, $marker);
+    }
+
+    /**
+     * Substitute subpart in input template stream.
+     * This function substitutes a subpart in $content with the content of
+     * $subpartContent.
+     * Wrapper for \TYPO3\CMS\Core\Utility\MarkerBasedTemplateService::substituteSubpart which behaves identical
+     *
+     * @param string $content The content stream, typically HTML template content.
+     * @param string $marker The marker string, typically on the form "###[the marker string]###
+     * @param mixed $subpartContent The content to insert instead of the subpart found. If a string, then just plain substitution happens (includes removing the HTML comments of the subpart if found). If $subpartContent happens to be an array, it's [0] and [1] elements are wrapped around the EXISTING content of the subpart (fetched by getSubpart()) thereby not removing the original content.
+     * @param bool|int $recursive If $recursive is set, the function calls itself with the content set to the remaining part of the content after the second marker. This means that proceding subparts are ALSO substituted!
+     * @return string The processed HTML content string.
+     */
+    public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1)
+    {
+        return $this->templateService->substituteSubpart($content, $marker, $subpartContent, $recursive);
+    }
+
+    /**
+     * Substitues multiple subparts at once
+     *
+     * @param string $content The content stream, typically HTML template content.
+     * @param array $subpartsContent The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content.
+     * @return string The processed HTML content string.
+     */
+    public function substituteSubpartArray($content, array $subpartsContent)
+    {
+        return $this->templateService->substituteSubpartArray($content, $subpartsContent);
+    }
+
+    /**
+     * Substitutes a marker string in the input content
+     * (by a simple str_replace())
+     *
+     * @param string $content The content stream, typically HTML template content.
+     * @param string $marker The marker string, typically on the form "###[the marker string]###
+     * @param mixed $markContent The content to insert instead of the marker string found.
+     * @return string The processed HTML content string.
+     * @see substituteSubpart()
+     */
+    public function substituteMarker($content, $marker, $markContent)
+    {
+        return $this->templateService->substituteMarker($content, $marker, $markContent);
+    }
+
+    /**
+     * Multi substitution function with caching.
+     *
+     * This function should be a one-stop substitution function for working
+     * with HTML-template. It does not substitute by str_replace but by
+     * splitting. This secures that the value inserted does not themselves
+     * contain markers or subparts.
+     *
+     * Note that the "caching" won't cache the content of the substition,
+     * but only the splitting of the template in various parts. So if you
+     * want only one cache-entry per template, make sure you always pass the
+     * exact same set of marker/subpart keys. Else you will be flooding the
+     * user's cache table.
+     *
+     * This function takes three kinds of substitutions in one:
+     * $markContentArray is a regular marker-array where the 'keys' are
+     * substituted in $content with their values
+     *
+     * $subpartContentArray works exactly like markContentArray only is whole
+     * subparts substituted and not only a single marker.
+     *
+     * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where
+     * the subparts pointed to by the main key is wrapped with the 0/1 value
+     * alternating.
+     *
+     * @param string $content The content stream, typically HTML template content.
+     * @param array $markContentArray Regular marker-array where the 'keys' are substituted in $content with their values
+     * @param array $subpartContentArray Exactly like markContentArray only is whole subparts substituted and not only a single marker.
+     * @param array $wrappedSubpartContentArray An array of arrays with 0/1 keys where the subparts pointed to by the main key is wrapped with the 0/1 value alternating.
+     * @return string The output content stream
+     * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE()
+     */
+    public function substituteMarkerArrayCached($content, array $markContentArray = null, array $subpartContentArray = null, array $wrappedSubpartContentArray = null)
+    {
+        $timeTracker = $this->getTimeTracker();
+        $timeTracker->push('substituteMarkerArrayCached');
+        // If not arrays then set them
+        if (is_null($markContentArray)) {
+            // Plain markers
+            $markContentArray = array();
+        }
+        if (is_null($subpartContentArray)) {
+            // Subparts being directly substituted
+            $subpartContentArray = array();
+        }
+        if (is_null($wrappedSubpartContentArray)) {
+            // Subparts being wrapped
+            $wrappedSubpartContentArray = array();
+        }
+        // Finding keys and check hash:
+        $sPkeys = array_keys($subpartContentArray);
+        $wPkeys = array_keys($wrappedSubpartContentArray);
+        $keysToReplace = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys);
+        if (empty($keysToReplace)) {
+            $timeTracker->pull();
+            return $content;
+        }
+        asort($keysToReplace);
+        $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array($content, $keysToReplace)));
+        if ($this->substMarkerCache[$storeKey]) {
+            $storeArr = $this->substMarkerCache[$storeKey];
+            $timeTracker->setTSlogMessage('Cached', 0);
+        } else {
+            $storeArrDat = $this->getTypoScriptFrontendController()->sys_page->getHash($storeKey);
+            if (is_array($storeArrDat)) {
+                $storeArr = $storeArrDat;
+                // Setting cache:
+                $this->substMarkerCache[$storeKey] = $storeArr;
+                $timeTracker->setTSlogMessage('Cached from DB', 0);
+            } else {
+                // Finding subparts and substituting them with the subpart as a marker
+                foreach ($sPkeys as $sPK) {
+                    $content = $this->substituteSubpart($content, $sPK, $sPK);
+                }
+                // Finding subparts and wrapping them with markers
+                foreach ($wPkeys as $wPK) {
+                    $content = $this->substituteSubpart($content, $wPK, array(
+                        $wPK,
+                        $wPK
+                    ));
+                }
+
+                $storeArr = array();
+                // search all markers in the content
+                $result = preg_match_all('/###([^#](?:[^#]*+|#{1,2}[^#])+)###/', $content, $markersInContent);
+                if ($result !== false && !empty($markersInContent[1])) {
+                    $keysToReplaceFlipped = array_flip($keysToReplace);
+                    $regexKeys = array();
+                    $wrappedKeys = array();
+                    // Traverse keys and quote them for reg ex.
+                    foreach ($markersInContent[1] as $key) {
+                        if (isset($keysToReplaceFlipped['###' . $key . '###'])) {
+                            $regexKeys[] = preg_quote($key, '/');
+                            $wrappedKeys[] = '###' . $key . '###';
+                        }
+                    }
+                    $regex = '/###(?:' . implode('|', $regexKeys) . ')###/';
+                    $storeArr['c'] = preg_split($regex, $content); // contains all content parts around markers
+                    $storeArr['k'] = $wrappedKeys; // contains all markers incl. ###
+                    // Setting cache:
+                    $this->substMarkerCache[$storeKey] = $storeArr;
+                    // Storing the cached data:
+                    $this->getTypoScriptFrontendController()->sys_page->storeHash($storeKey, $storeArr, 'substMarkArrayCached');
+                }
+                $timeTracker->setTSlogMessage('Parsing', 0);
+            }
+        }
+        if (!empty($storeArr['k']) && is_array($storeArr['k'])) {
+            // Substitution/Merging:
+            // Merging content types together, resetting
+            $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
+            $wSCA_reg = array();
+            $content = '';
+            // Traversing the keyList array and merging the static and dynamic content
+            foreach ($storeArr['k'] as $n => $keyN) {
+                // add content before marker
+                $content .= $storeArr['c'][$n];
+                if (!is_array($valueArr[$keyN])) {
+                    // fetch marker replacement from $markContentArray or $subpartContentArray
+                    $content .= $valueArr[$keyN];
+                } else {
+                    if (!isset($wSCA_reg[$keyN])) {
+                        $wSCA_reg[$keyN] = 0;
+                    }
+                    // fetch marker replacement from $wrappedSubpartContentArray
+                    $content .= $valueArr[$keyN][$wSCA_reg[$keyN] % 2];
+                    $wSCA_reg[$keyN]++;
+                }
+            }
+            // add remaining content
+            $content .= $storeArr['c'][count($storeArr['k'])];
+        }
+        $timeTracker->pull();
+        return $content;
+    }
+
+    /**
+     * Traverses the input $markContentArray array and for each key the marker
+     * by the same name (possibly wrapped and in upper case) will be
+     * substituted with the keys value in the array.
+     *
+     * This is very useful if you have a data-record to substitute in some
+     * content. In particular when you use the $wrap and $uppercase values to
+     * pre-process the markers. Eg. a key name like "myfield" could effectively
+     * be represented by the marker "###MYFIELD###" if the wrap value
+     * was "###|###" and the $uppercase boolean TRUE.
+     *
+     * @param string $content The content stream, typically HTML template content.
+     * @param array $markContentArray The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
+     * @param string $wrap A wrap value - [part 1] | [part 2] - for the markers before substitution
+     * @param bool $uppercase If set, all marker string substitution is done with upper-case markers.
+     * @param bool $deleteUnused If set, all unused marker are deleted.
+     * @return string The processed output stream
+     * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
+     */
+    public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = false, $deleteUnused = false)
+    {
+        return $this->templateService->substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
+    }
+
+    /**
+     * Substitute marker array in an array of values
+     *
+     * @param mixed $tree If string, then it just calls substituteMarkerArray. If array(and even multi-dim) then for each key/value pair the marker array will be substituted (by calling this function recursively)
+     * @param array $markContentArray The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content string/array values.
+     * @return mixed The processed input variable.
+     * @see substituteMarker()
+     */
+    public function substituteMarkerInObject(&$tree, array $markContentArray)
+    {
+        if (is_array($tree)) {
+            foreach ($tree as $key => $value) {
+                $this->substituteMarkerInObject($tree[$key], $markContentArray);
+            }
+        } else {
+            $tree = $this->substituteMarkerArray($tree, $markContentArray);
+        }
+        return $tree;
+    }
+
+    /**
+     * Replaces all markers and subparts in a template with the content provided in the structured array.
+     *
+     * @param string $content
+     * @param array $markersAndSubparts
+     * @param string $wrap
+     * @param bool $uppercase
+     * @param bool $deleteUnused
+     * @return string
+     */
+    public function substituteMarkerAndSubpartArrayRecursive($content, array $markersAndSubparts, $wrap = '', $uppercase = false, $deleteUnused = false)
+    {
+        return $this->templateService->substituteMarkerAndSubpartArrayRecursive($content, $markersAndSubparts, $wrap, $uppercase, $deleteUnused);
+    }
+
+    /**
+     * Adds elements to the input $markContentArray based on the values from
+     * the fields from $fieldList found in $row
+     *
+     * @param array $markContentArray Array with key/values being marker-strings/substitution values.
+     * @param array $row An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray
+     * @param string $fieldList A list of fields from the $row array to add to the $markContentArray array. If empty all fields from $row will be added (unless they are integers)
+     * @param bool $nl2br If set, all values added to $markContentArray will be nl2br()'ed
+     * @param string $prefix Prefix string to the fieldname before it is added as a key in the $markContentArray. Notice that the keys added to the $markContentArray always start and end with "###
+     * @param bool $HSC If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance.
+     * @return array The modified $markContentArray
+     */
+    public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = true, $prefix = 'FIELD_', $HSC = false)
+    {
+        $tsfe = $this->getTypoScriptFrontendController();
+        if ($fieldList) {
+            $fArr = GeneralUtility::trimExplode(',', $fieldList, true);
+            foreach ($fArr as $field) {
+                $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field], !empty($tsfe->xhtmlDoctype)) : $row[$field];
+            }
+        } else {
+            if (is_array($row)) {
+                foreach ($row as $field => $value) {
+                    if (!MathUtility::canBeInterpretedAsInteger($field)) {
+                        if ($HSC) {
+                            $value = htmlspecialchars($value);
+                        }
+                        $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value, !empty($tsfe->xhtmlDoctype)) : $value;
+                    }
+                }
+            }
+        }
+        return $markContentArray;
+    }
+
+    /**
+     * Sets the current file object during iterations over files.
+     *
+     * @param File $fileObject The file object.
+     */
+    public function setCurrentFile($fileObject)
+    {
+        $this->currentFile = $fileObject;
+    }
+
+    /**
+     * Gets the current file object during iterations over files.
+     *
+     * @return File The current file object.
+     */
+    public function getCurrentFile()
+    {
+        return $this->currentFile;
+    }
+
+    /***********************************************
+     *
+     * "stdWrap" + sub functions
+     *
+     ***********************************************/
+    /**
+     * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript.
+     * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array(holding the TypoScript "stdWrap properties")
+     * See the link below for a complete list of properties and what they do. The order of the table with properties found in TSref (the link) follows the actual order of implementation in this function.
+     *
+     * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData
+     *
+     * @param string $content Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
+     * @param array $conf TypoScript "stdWrap properties".
+     * @return string The processed input value
+     */
+    public function stdWrap($content = '', $conf = array())
+    {
+        $content = (string)$content;
+        // If there is any hook object, activate all of the process and override functions.
+        // The hook interface ContentObjectStdWrapHookInterface takes care that all 4 methods exist.
+        if ($this->stdWrapHookObjects) {
+            $conf['stdWrapPreProcess'] = 1;
+            $conf['stdWrapOverride'] = 1;
+            $conf['stdWrapProcess'] = 1;
+            $conf['stdWrapPostProcess'] = 1;
+        }
+
+        if (!is_array($conf) || !$conf) {
+            return $content;
+        }
+
+        // Cache handling
+        if (is_array($conf['cache.'])) {
+            $conf['cache.']['key'] = $this->stdWrap($conf['cache.']['key'], $conf['cache.']['key.']);
+            $conf['cache.']['tags'] = $this->stdWrap($conf['cache.']['tags'], $conf['cache.']['tags.']);
+            $conf['cache.']['lifetime'] = $this->stdWrap($conf['cache.']['lifetime'], $conf['cache.']['lifetime.']);
+            $conf['cacheRead'] = 1;
+            $conf['cacheStore'] = 1;
+        }
+        // Check, which of the available stdWrap functions is needed for the current conf Array
+        // and keep only those but still in the same order
+        $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
+        // Functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
+        $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
+        // Additional Array to check whether a function has already been executed
+        $isExecuted = array();
+        // Additional switch to make sure 'required', 'if' and 'fieldRequired'
+        // will still stop rendering immediately in case they return FALSE
+        $this->stdWrapRecursionLevel++;
+        $this->stopRendering[$this->stdWrapRecursionLevel] = false;
+        // execute each function in the predefined order
+        foreach ($sortedConf as $stdWrapName => $functionType) {
+            // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
+            if (!$isExecuted[$stdWrapName] && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
+                $functionName = rtrim($stdWrapName, '.');
+                $functionProperties = $functionName . '.';
+                // If there is any code on the next level, check if it contains "official" stdWrap functions
+                // if yes, execute them first - will make each function stdWrap aware
+                // so additional stdWrap calls within the functions can be removed, since the result will be the same
+                // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
+                if ($functionName !== 'stdWrap' && !empty($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
+                    if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
+                        $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
+                    }
+                }
+                // Check if key is still containing something, since it might have been changed by next level stdWrap before
+                if ((isset($conf[$functionName]) || $conf[$functionProperties]) && ($functionType !== 'boolean' || $conf[$functionName])) {
+                    // Get just that part of $conf that is needed for the particular function
+                    $singleConf = array(
+                        $functionName => $conf[$functionName],
+                        $functionProperties => $conf[$functionProperties]
+                    );
+                    // In this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.''
+                    if ($functionName === 'spaceBefore' || $functionName === 'spaceAfter') {
+                        $singleConf['space.'] = $conf['space.'];
+                    }
+                    // Hand over the whole $conf array to the stdWrapHookObjects
+                    if ($functionType === 'hook') {
+                        $singleConf = $conf;
+                    }
+                    // Add both keys - with and without the dot - to the set of executed functions
+                    $isExecuted[$functionName] = true;
+                    $isExecuted[$functionProperties] = true;
+                    // Call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
+                    $functionName = 'stdWrap_' . $functionName;
+                    $content = $this->{$functionName}($content, $singleConf);
+                } elseif ($functionType === 'boolean' && !$conf[$functionName]) {
+                    $isExecuted[$functionName] = true;
+                    $isExecuted[$functionProperties] = true;
+                }
+            }
+        }
+        unset($this->stopRendering[$this->stdWrapRecursionLevel]);
+        $this->stdWrapRecursionLevel--;
+
+        return $content;
+    }
+
+    /**
+     * Gets a configuration value by passing them through stdWrap first and taking a default value if stdWrap doesn't yield a result.
+     *
+     * @param string $key The config variable key (from TS array).
+     * @param array $config The TypoScript array.
+     * @param string $defaultValue Optional default value.
+     * @return string Value of the config variable
+     */
+    public function stdWrapValue($key, array $config, $defaultValue = '')
+    {
+        if (isset($config[$key])) {
+            if (!isset($config[$key . '.'])) {
+                return $config[$key];
+            }
+        } elseif (isset($config[$key . '.'])) {
+            $config[$key] = '';
+        } else {
+            return $defaultValue;
+        }
+        $stdWrapped = $this->stdWrap($config[$key], $config[$key . '.']);
+        return $stdWrapped ?: $defaultValue;
+    }
+
+    /**
+     * stdWrap pre process hook
+     * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
+     * this hook will execute functions before any other stdWrap function can modify anything
+     *
+     * @param string $content Input value undergoing processing in these functions.
+     * @param array $conf All stdWrap properties, not just the ones for a particular function.
+     * @return string The processed input value
+     */
+    public function stdWrap_stdWrapPreProcess($content = '', $conf = array())
+    {
+        foreach ($this->stdWrapHookObjects as $hookObject) {
+            /** @var ContentObjectStdWrapHookInterface $hookObject */
+            $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
+        }
+        return $content;
+    }
+
+    /**
+     * Check if content was cached before (depending on the given cache key)
+     *
+     * @param string $content Input value undergoing processing in these functions.
+     * @param array $conf All stdWrap properties, not just the ones for a particular function.
+     * @return string The processed input value
+     */
+    public function stdWrap_cacheRead($content = '', $conf = array())
+    {
+        if (!isset($conf['cache.'])) {
+            return $content;
+        }
+        $result = $this->getFromCache($conf['cache.']);
+        return $result === false ? $content : $result;
+    }
+
+    /**
+     * Add tags to page cache (comma-separated list)
+     *
+     * @param string $content Input value undergoing processing in these functions.
+     * @param array $conf All stdWrap properties, not just the ones for a particular function.
+     * @return string The processed input value
+     */
+    public function stdWrap_addPageCacheTags($content = '', $conf = array())
+    {
+        $tags = isset($conf['addPageCacheTags.'])
+            ? $this->stdWrap($conf['addPageCacheTags'], $conf['addPageCacheTags.'])
+            : $conf['addPageCacheTags'];
+        if (!empty($tags)) {
+            $cacheTags = GeneralUtility::trimExplode(',', $tags, true);
+            $this->getTypoScriptFrontendController()->addCacheTags($cacheTags);
+        }
+        return $content;
+    }
+
+    /**
+     * setContentToCurrent
+     * actually it just does the contrary: Sets the value of 'current' based on current content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_setContentToCurrent($content = '')
+    {
+        $this->data[$this->currentValKey] = $content;
+        return $content;
+    }
+
+    /**
+     * setCurrent
+     * Sets the value of 'current' based on the outcome of stdWrap operations
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for setCurrent.
+     * @return string The processed input value
+     */
+    public function stdWrap_setCurrent($content = '', $conf = array())
+    {
+        $this->data[$this->currentValKey] = $conf['setCurrent'];
+        return $content;
+    }
+
+    /**
+     * lang
+     * Translates content based on the language currently used by the FE
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for lang.
+     * @return string The processed input value
+     */
+    public function stdWrap_lang($content = '', $conf = array())
+    {
+        $tsfe = $this->getTypoScriptFrontendController();
+        if (isset($conf['lang.']) && $tsfe->config['config']['language'] && isset($conf['lang.'][$tsfe->config['config']['language']])) {
+            $content = $conf['lang.'][$tsfe->config['config']['language']];
+        }
+        return $content;
+    }
+
+    /**
+     * data
+     * Gets content from different sources based on getText functions, makes use of alternativeData, when set
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for data.
+     * @return string The processed input value
+     */
+    public function stdWrap_data($content = '', $conf = array())
+    {
+        $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
+        // This must be unset directly after
+        $this->alternativeData = '';
+        return $content;
+    }
+
+    /**
+     * field
+     * Gets content from a DB field
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for field.
+     * @return string The processed input value
+     */
+    public function stdWrap_field($content = '', $conf = array())
+    {
+        return $this->getFieldVal($conf['field']);
+    }
+
+    /**
+     * current
+     * Gets content that has been perviously set as 'current'
+     * Can be set via setContentToCurrent or setCurrent or will be set automatically i.e. inside the split function
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for current.
+     * @return string The processed input value
+     */
+    public function stdWrap_current($content = '', $conf = array())
+    {
+        return $this->data[$this->currentValKey];
+    }
+
+    /**
+     * cObject
+     * Will replace the content with the value of an official TypoScript cObject
+     * like TEXT, COA, HMENU
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for cObject.
+     * @return string The processed input value
+     */
+    public function stdWrap_cObject($content = '', $conf = array())
+    {
+        return $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject');
+    }
+
+    /**
+     * numRows
+     * Counts the number of returned records of a DB operation
+     * makes use of select internally
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for numRows.
+     * @return string The processed input value
+     */
+    public function stdWrap_numRows($content = '', $conf = array())
+    {
+        return $this->numRows($conf['numRows.']);
+    }
+
+    /**
+     * filelist
+     * Will create a list of files based on some additional parameters
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for filelist.
+     * @return string The processed input value
+     */
+    public function stdWrap_filelist($content = '', $conf = array())
+    {
+        return $this->filelist($conf['filelist']);
+    }
+
+    /**
+     * preUserFunc
+     * Will execute a user public function before the content will be modified by any other stdWrap function
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for preUserFunc.
+     * @return string The processed input value
+     */
+    public function stdWrap_preUserFunc($content = '', $conf = array())
+    {
+        return $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
+    }
+
+    /**
+     * stdWrap override hook
+     * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
+     * this hook will execute functions on existing content but still before the content gets modified or replaced
+     *
+     * @param string $content Input value undergoing processing in these functions.
+     * @param array $conf All stdWrap properties, not just the ones for a particular function.
+     * @return string The processed input value
+     */
+    public function stdWrap_stdWrapOverride($content = '', $conf = array())
+    {
+        foreach ($this->stdWrapHookObjects as $hookObject) {
+            /** @var ContentObjectStdWrapHookInterface $hookObject */
+            $content = $hookObject->stdWrapOverride($content, $conf, $this);
+        }
+        return $content;
+    }
+
+    /**
+     * override
+     * Will override the current value of content with its own value'
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for override.
+     * @return string The processed input value
+     */
+    public function stdWrap_override($content = '', $conf = array())
+    {
+        if (trim($conf['override'])) {
+            $content = $conf['override'];
+        }
+        return $content;
+    }
+
+    /**
+     * preIfEmptyListNum
+     * Gets a value off a CSV list before the following ifEmpty check
+     * Makes sure that the result of ifEmpty will be TRUE in case the CSV does not contain a value at the position given by preIfEmptyListNum
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for preIfEmptyListNum.
+     * @return string The processed input value
+     */
+    public function stdWrap_preIfEmptyListNum($content = '', $conf = array())
+    {
+        return $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']);
+    }
+
+    /**
+     * ifNull
+     * Will set content to a replacement value in case the value of content is NULL
+     *
+     * @param string|NULL $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for ifNull.
+     * @return string The processed input value
+     */
+    public function stdWrap_ifNull($content = '', $conf = array())
+    {
+        return $content !== null ? $content : $conf['ifNull'];
+    }
+
+    /**
+     * ifEmpty
+     * Will set content to a replacement value in case the trimmed value of content returns FALSE
+     * 0 (zero) will be replaced as well
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for ifEmpty.
+     * @return string The processed input value
+     */
+    public function stdWrap_ifEmpty($content = '', $conf = array())
+    {
+        if (!trim($content)) {
+            $content = $conf['ifEmpty'];
+        }
+        return $content;
+    }
+
+    /**
+     * ifBlank
+     * Will set content to a replacement value in case the trimmed value of content has no length
+     * 0 (zero) will not be replaced
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for ifBlank.
+     * @return string The processed input value
+     */
+    public function stdWrap_ifBlank($content = '', $conf = array())
+    {
+        if (trim($content) === '') {
+            $content = $conf['ifBlank'];
+        }
+        return $content;
+    }
+
+    /**
+     * listNum
+     * Gets a value off a CSV list after ifEmpty check
+     * Might return an empty value in case the CSV does not contain a value at the position given by listNum
+     * Use preIfEmptyListNum to avoid that behaviour
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for listNum.
+     * @return string The processed input value
+     */
+    public function stdWrap_listNum($content = '', $conf = array())
+    {
+        return $this->listNum($content, $conf['listNum'], $conf['listNum.']['splitChar']);
+    }
+
+    /**
+     * trim
+     * Cuts off any whitespace at the beginning and the end of the content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_trim($content = '')
+    {
+        return trim($content);
+    }
+
+    /**
+     * strPad
+     * Will return a string padded left/right/on both sides, based on configuration given as stdWrap properties
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for strPad.
+     * @return string The processed input value
+     */
+    public function stdWrap_strPad($content = '', $conf = array())
+    {
+        // Must specify a length in conf for this to make sense
+        $length = 0;
+        // Padding with space is PHP-default
+        $padWith = ' ';
+        // Padding on the right side is PHP-default
+        $padType = STR_PAD_RIGHT;
+        if (!empty($conf['strPad.']['length'])) {
+            $length = isset($conf['strPad.']['length.']) ? $this->stdWrap($conf['strPad.']['length'], $conf['strPad.']['length.']) : $conf['strPad.']['length'];
+            $length = (int)$length;
+        }
+        if (isset($conf['strPad.']['padWith']) && (string)$conf['strPad.']['padWith'] !== '') {
+            $padWith = isset($conf['strPad.']['padWith.']) ? $this->stdWrap($conf['strPad.']['padWith'], $conf['strPad.']['padWith.']) : $conf['strPad.']['padWith'];
+        }
+        if (!empty($conf['strPad.']['type'])) {
+            $type = isset($conf['strPad.']['type.']) ? $this->stdWrap($conf['strPad.']['type'], $conf['strPad.']['type.']) : $conf['strPad.']['type'];
+            if (strtolower($type) === 'left') {
+                $padType = STR_PAD_LEFT;
+            } elseif (strtolower($type) === 'both') {
+                $padType = STR_PAD_BOTH;
+            }
+        }
+        return str_pad($content, $length, $padWith, $padType);
+    }
+
+    /**
+     * stdWrap
+     * A recursive call of the stdWrap function set
+     * This enables the user to execute stdWrap functions in another than the predefined order
+     * It modifies the content, not the property
+     * while the new feature of chained stdWrap functions modifies the property and not the content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for stdWrap.
+     * @return string The processed input value
+     */
+    public function stdWrap_stdWrap($content = '', $conf = array())
+    {
+        return $this->stdWrap($content, $conf['stdWrap.']);
+    }
+
+    /**
+     * stdWrap process hook
+     * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
+     * this hook executes functions directly after the recursive stdWrap function call but still before the content gets modified
+     *
+     * @param string $content Input value undergoing processing in these functions.
+     * @param array $conf All stdWrap properties, not just the ones for a particular function.
+     * @return string The processed input value
+     */
+    public function stdWrap_stdWrapProcess($content = '', $conf = array())
+    {
+        foreach ($this->stdWrapHookObjects as $hookObject) {
+            /** @var ContentObjectStdWrapHookInterface $hookObject */
+            $content = $hookObject->stdWrapProcess($content, $conf, $this);
+        }
+        return $content;
+    }
+
+    /**
+     * required
+     * Will immediately stop rendering and return an empty value
+     * when there is no content at this point
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_required($content = '')
+    {
+        if ((string)$content === '') {
+            $content = '';
+            $this->stopRendering[$this->stdWrapRecursionLevel] = true;
+        }
+        return $content;
+    }
+
+    /**
+     * if
+     * Will immediately stop rendering and return an empty value
+     * when the result of the checks returns FALSE
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for if.
+     * @return string The processed input value
+     */
+    public function stdWrap_if($content = '', $conf = array())
+    {
+        if (empty($conf['if.']) || $this->checkIf($conf['if.'])) {
+            return $content;
+        }
+        $this->stopRendering[$this->stdWrapRecursionLevel] = true;
+        return '';
+    }
+
+    /**
+     * fieldRequired
+     * Will immediately stop rendering and return an empty value
+     * when there is no content in the field given by fieldRequired
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for fieldRequired.
+     * @return string The processed input value
+     */
+    public function stdWrap_fieldRequired($content = '', $conf = array())
+    {
+        if (!trim($this->data[$conf['fieldRequired']])) {
+            $content = '';
+            $this->stopRendering[$this->stdWrapRecursionLevel] = true;
+        }
+        return $content;
+    }
+
+    /**
+     * csConv
+     * Will convert the current chracter set of the content to the one given in csConv
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for csConv.
+     * @return string The processed input value
+     */
+    public function stdWrap_csConv($content = '', $conf = array())
+    {
+        return $this->getTypoScriptFrontendController()->csConv($content, $conf['csConv']);
+    }
+
+    /**
+     * parseFunc
+     * Will parse the content based on functions given as stdWrap properties
+     * Heavily used together with RTE based content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for parseFunc.
+     * @return string The processed input value
+     */
+    public function stdWrap_parseFunc($content = '', $conf = array())
+    {
+        return $this->parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
+    }
+
+    /**
+     * HTMLparser
+     * Will parse HTML content based on functions given as stdWrap properties
+     * Heavily used together with RTE based content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for HTMLparser.
+     * @return string The processed input value
+     */
+    public function stdWrap_HTMLparser($content = '', $conf = array())
+    {
+        if (is_array($conf['HTMLparser.'])) {
+            $content = $this->HTMLparser_TSbridge($content, $conf['HTMLparser.']);
+        }
+        return $content;
+    }
+
+    /**
+     * split
+     * Will split the content by a given token and treat the results separately
+     * Automatically fills 'current' with a single result
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for split.
+     * @return string The processed input value
+     */
+    public function stdWrap_split($content = '', $conf = array())
+    {
+        return $this->splitObj($content, $conf['split.']);
+    }
+
+    /**
+     * replacement
+     * Will execute replacements on the content (optionally with preg-regex)
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for replacement.
+     * @return string The processed input value
+     */
+    public function stdWrap_replacement($content = '', $conf = array())
+    {
+        return $this->replacement($content, $conf['replacement.']);
+    }
+
+    /**
+     * prioriCalc
+     * Will use the content as a mathematical term and calculate the result
+     * Can be set to 1 to just get a calculated value or 'intval' to get the integer of the result
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for prioriCalc.
+     * @return string The processed input value
+     */
+    public function stdWrap_prioriCalc($content = '', $conf = array())
+    {
+        $content = MathUtility::calculateWithParentheses($content);
+        if ($conf['prioriCalc'] === 'intval') {
+            $content = (int)$content;
+        }
+        return $content;
+    }
+
+    /**
+     * char
+     * Will return a character based on its position within the current character set
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for char.
+     * @return string The processed input value
+     */
+    public function stdWrap_char($content = '', $conf = array())
+    {
+        return chr((int)$conf['char']);
+    }
+
+    /**
+     * intval
+     * Will return an integer value of the current content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_intval($content = '')
+    {
+        return (int)$content;
+    }
+
+    /**
+     * Will return a hashed value of the current content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for hash.
+     * @return string The processed input value
+     * @link http://php.net/manual/de/function.hash-algos.php for a list of supported hash algorithms
+     */
+    public function stdWrap_hash($content = '', array $conf = array())
+    {
+        $algorithm = isset($conf['hash.']) ? $this->stdWrap($conf['hash'], $conf['hash.']) : $conf['hash'];
+        if (function_exists('hash') && in_array($algorithm, hash_algos())) {
+            return hash($algorithm, $content);
+        }
+        // Non-existing hashing algorithm
+        return '';
+    }
+
+    /**
+     * stdWrap_round will return a rounded number with ceil(), floor() or round(), defaults to round()
+     * Only the english number format is supported . (dot) as decimal point
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for round.
+     * @return string The processed input value
+     */
+    public function stdWrap_round($content = '', $conf = array())
+    {
+        return $this->round($content, $conf['round.']);
+    }
+
+    /**
+     * numberFormat
+     * Will return a formatted number based on configuration given as stdWrap properties
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for numberFormat.
+     * @return string The processed input value
+     */
+    public function stdWrap_numberFormat($content = '', $conf = array())
+    {
+        return $this->numberFormat($content, $conf['numberFormat.']);
+    }
+
+    /**
+     * expandList
+     * Will return a formatted number based on configuration given as stdWrap properties
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_expandList($content = '')
+    {
+        return GeneralUtility::expandList($content);
+    }
+
+    /**
+     * date
+     * Will return a formatted date based on configuration given according to PHP date/gmdate properties
+     * Will return gmdate when the property GMT returns TRUE
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for date.
+     * @return string The processed input value
+     */
+    public function stdWrap_date($content = '', $conf = array())
+    {
+        // Check for zero length string to mimic default case of date/gmdate.
+        $content = (string)$content === '' ? $GLOBALS['EXEC_TIME'] : (int)$content;
+        $content = $conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content);
+        return $content;
+    }
+
+    /**
+     * strftime
+     * Will return a formatted date based on configuration given according to PHP strftime/gmstrftime properties
+     * Will return gmstrftime when the property GMT returns TRUE
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for strftime.
+     * @return string The processed input value
+     */
+    public function stdWrap_strftime($content = '', $conf = array())
+    {
+        // Check for zero length string to mimic default case of strtime/gmstrftime
+        $content = (string)$content === '' ? $GLOBALS['EXEC_TIME'] : (int)$content;
+        $content = $conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content);
+        if (!empty($conf['strftime.']['charset'])) {
+            $content = $this->getTypoScriptFrontendController()->csConv($content, $conf['strftime.']['charset']);
+        }
+        return $content;
+    }
+
+    /**
+     * strtotime
+     * Will return a timestamp based on configuration given according to PHP strtotime
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for strtotime.
+     * @return string The processed input value
+     */
+    public function stdWrap_strtotime($content = '', $conf = array())
+    {
+        if ($conf['strtotime'] !== '1') {
+            $content .= ' ' . $conf['strtotime'];
+        }
+        return strtotime($content, $GLOBALS['EXEC_TIME']);
+    }
+
+    /**
+     * age
+     * Will return the age of a given timestamp based on configuration given by stdWrap properties
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for age.
+     * @return string The processed input value
+     */
+    public function stdWrap_age($content = '', $conf = array())
+    {
+        return $this->calcAge((int)$GLOBALS['EXEC_TIME'] - (int)$content, $conf['age']);
+    }
+
+    /**
+     * case
+     * Will transform the content to be upper or lower case only
+     * Leaves HTML tags untouched
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for case.
+     * @return string The processed input value
+     */
+    public function stdWrap_case($content = '', $conf = array())
+    {
+        return $this->HTMLcaseshift($content, $conf['case']);
+    }
+
+    /**
+     * bytes
+     * Will return the size of a given number in Bytes  *
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for bytes.
+     * @return string The processed input value
+     */
+    public function stdWrap_bytes($content = '', $conf = array())
+    {
+        return GeneralUtility::formatSize($content, $conf['bytes.']['labels'], $conf['bytes.']['base']);
+    }
+
+    /**
+     * substring
+     * Will return a substring based on position information given by stdWrap properties
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for substring.
+     * @return string The processed input value
+     */
+    public function stdWrap_substring($content = '', $conf = array())
+    {
+        return $this->substring($content, $conf['substring']);
+    }
+
+    /**
+     * removeBadHTML
+     * Removes HTML tags based on stdWrap properties
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_removeBadHTML($content = '')
+    {
+        return $this->removeBadHTML($content);
+    }
+
+    /**
+     * cropHTML
+     * Crops content to a given size while leaving HTML tags untouched
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for cropHTML.
+     * @return string The processed input value
+     */
+    public function stdWrap_cropHTML($content = '', $conf = array())
+    {
+        return $this->cropHTML($content, $conf['cropHTML']);
+    }
+
+    /**
+     * stripHtml
+     * Copmletely removes HTML tags from content
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_stripHtml($content = '')
+    {
+        return strip_tags($content);
+    }
+
+    /**
+     * crop
+     * Crops content to a given size without caring about HTML tags
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for crop.
+     * @return string The processed input value
+     */
+    public function stdWrap_crop($content = '', $conf = array())
+    {
+        return $this->crop($content, $conf['crop']);
+    }
+
+    /**
+     * rawUrlEncode
+     * Encodes content to be used within URLs
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @return string The processed input value
+     */
+    public function stdWrap_rawUrlEncode($content = '')
+    {
+        return rawurlencode($content);
+    }
+
+    /**
+     * htmlSpecialChars
+     * Transforms HTML tags to readable text by replacing special characters with their HTML entity
+     * When preserveEntities returns TRUE, existing entities will be left untouched
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for htmlSpecalChars.
+     * @return string The processed input value
+     */
+    public function stdWrap_htmlSpecialChars($content = '', $conf = array())
+    {
+        if (!empty($conf['htmlSpecialChars.']['preserveEntities'])) {
+            $content = htmlspecialchars($content, ENT_COMPAT, 'UTF-8', false);
+        } else {
+            $content = htmlspecialchars($content);
+        }
+        return $content;
+    }
+
+    /**
+     * encodeForJavaScriptValue
+     * Escapes content to be used inside JavaScript strings. No quotes are added around the value
+     * as this can easily be done in TypoScript
+     *
+     * @param string $content Input value undergoing processing in this function
+     * @return string The processed input value
+     */
+    public function stdWrap_encodeForJavaScriptValue($content = '')
+    {
+        return GeneralUtility::quoteJSvalue($content);
+    }
+
+    /**
+     * doubleBrTag
+     * Searches for double line breaks and replaces them with the given value
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for doubleBrTag.
+     * @return string The processed input value
+     */
+    public function stdWrap_doubleBrTag($content = '', $conf = array())
+    {
+        return preg_replace('/
 ?
 [       ]*
 ?
 /', $conf['doubleBrTag'], $content);
-       }
-
-       /**
-        * br
-        * Searches for single line breaks and replaces them with a <br />/<br> tag
-        * according to the doctype
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for br.
-        * @return string The processed input value
-        */
-       public function stdWrap_br($content = '', $conf = array()) {
-               return nl2br($content, !empty($GLOBALS['TSFE']->xhtmlDoctype));
-       }
-
-       /**
-        * brTag
-        * Searches for single line feeds and replaces them with the given value
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for brTag.
-        * @return string The processed input value
-        */
-       public function stdWrap_brTag($content = '', $conf = array()) {
-               return str_replace(LF, $conf['brTag'], $content);
-       }
-
-       /**
-        * encapsLines
-        * Modifies text blocks by searching for lines which are not surrounded by HTML tags yet
-        * and wrapping them with values given by stdWrap properties
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for erncapsLines.
-        * @return string The processed input value
-        */
-       public function stdWrap_encapsLines($content = '', $conf = array()) {
-               return $this->encaps_lineSplit($content, $conf['encapsLines.']);
-       }
-
-       /**
-        * keywords
-        * Transforms content into a CSV list to be used i.e. as keywords within a meta tag
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for keywords.
-        * @return string The processed input value
-        */
-       public function stdWrap_keywords($content = '', $conf = array()) {
-               return $this->keywords($content);
-       }
-
-       /**
-        * innerWrap
-        * First of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for innerWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_innerWrap($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['innerWrap']);
-       }
-
-       /**
-        * innerWrap2
-        * Second of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for innerWrap2.
-        * @return string The processed input value
-        */
-       public function stdWrap_innerWrap2($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['innerWrap2']);
-       }
-
-       /**
-        * fontTag
-        * A wrap formerly used to apply font tags to format the content
-        * Still used by lib.stdheader although real font tags are not state of the art anymore
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for fontTag.
-        * @return string The processed input value
-        */
-       public function stdWrap_fontTag($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['fontTag']);
-       }
-
-       /**
-        * addParams
-        * Adds tag attributes to any content that is a tag
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for addParams.
-        * @return string The processed input value
-        */
-       public function stdWrap_addParams($content = '', $conf = array()) {
-               return $this->addParams($content, $conf['addParams.']);
-       }
-
-       /**
-        * textStyle
-        * Wraps content in font tags
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for textStyle.
-        * @return string The processed input value
-        */
-       public function stdWrap_textStyle($content = '', $conf = array()) {
-               return $this->textStyle($content, $conf['textStyle.']);
-       }
-
-       /**
-        * tableStyle
-        * Wraps content with table tags
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for tableStyle.
-        * @return string The processed input value
-        */
-       public function stdWrap_tableStyle($content = '', $conf = array()) {
-               return $this->tableStyle($content, $conf['tableStyle.']);
-       }
-
-       /**
-        * filelink
-        * Used to make lists of links to files
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for filelink.
-        * @return string The processed input value
-        */
-       public function stdWrap_filelink($content = '', $conf = array()) {
-               return $this->filelink($content, $conf['filelink.']);
-       }
-
-       /**
-        * preCObject
-        * A content object that is prepended to the current content but between the innerWraps and the rest of the wraps
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for preCObject.
-        * @return string The processed input value
-        */
-       public function stdWrap_preCObject($content = '', $conf = array()) {
-               return $this->cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content;
-       }
-
-       /**
-        * postCObject
-        * A content object that is appended to the current content but between the innerWraps and the rest of the wraps
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for postCObject.
-        * @return string The processed input value
-        */
-       public function stdWrap_postCObject($content = '', $conf = array()) {
-               return $content . $this->cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject');
-       }
-
-       /**
-        * wrapAlign
-        * Wraps content with a div container having the style attribute text-align set to the given value
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for wrapAlign.
-        * @return string The processed input value
-        */
-       public function stdWrap_wrapAlign($content = '', $conf = array()) {
-               $wrapAlign = trim($conf['wrapAlign']);
-               if ($wrapAlign) {
-                       $content = $this->wrap($content, '<div style="text-align:' . $wrapAlign . ';">|</div>');
-               }
-               return $content;
-       }
-
-       /**
-        * typolink
-        * Wraps the content with a link tag
-        * URLs and other attributes are created automatically by the values given in the stdWrap properties
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for typolink.
-        * @return string The processed input value
-        */
-       public function stdWrap_typolink($content = '', $conf = array()) {
-               return $this->typolink($content, $conf['typolink.']);
-       }
-
-       /**
-        * TCAselectItem
-        * Returns a list of options available for a given field in the DB which has to be of the type select
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for TCAselectItem.
-        * @return string The processed input value
-        */
-       public function stdWrap_TCAselectItem($content = '', $conf = array()) {
-               if (is_array($conf['TCAselectItem.'])) {
-                       $content = $this->TCAlookup($content, $conf['TCAselectItem.']);
-               }
-               return $content;
-       }
-
-       /**
-        * spaceBefore
-        * Will add space before the current content
-        * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to TRUE
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for spaceBefore and space.
-        * @return string The processed input value
-        */
-       public function stdWrap_spaceBefore($content = '', $conf = array()) {
-               return $this->wrapSpace($content, trim($conf['spaceBefore']) . '|', $conf['space.']);
-       }
-
-       /**
-        * spaceAfter
-        * Will add space after the current content
-        * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to TRUE
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for spaceAfter and space.
-        * @return string The processed input value
-        */
-       public function stdWrap_spaceAfter($content = '', $conf = array()) {
-               return $this->wrapSpace($content, '|' . trim($conf['spaceAfter']), $conf['space.']);
-       }
-
-       /**
-        * space
-        * Will add space before or after the current content
-        * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to TRUE
-        * See wrap
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for space.
-        * @return string The processed input value
-        */
-       public function stdWrap_space($content = '', $conf = array()) {
-               return $this->wrapSpace($content, trim($conf['space']), $conf['space.']);
-       }
-
-       /**
-        * wrap
-        * This is the "mother" of all wraps
-        * Third of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * Basically it will put additional content before and after the current content using a split character as a placeholder for the current content
-        * The default split character is | but it can be replaced with other characters by the property splitChar
-        * Any other wrap that does not have own splitChar settings will be using the default split char though
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for wrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_wrap($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['wrap'], $conf['wrap.']['splitChar'] ? $conf['wrap.']['splitChar'] : '|');
-       }
-
-       /**
-        * noTrimWrap
-        * Fourth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * The major difference to any other wrap is, that this one can make use of whitespace without trimming  *
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for noTrimWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_noTrimWrap($content = '', $conf = array()) {
-               $splitChar = isset($conf['noTrimWrap.']['splitChar.'])
-                       ? $this->stdWrap($conf['noTrimWrap.']['splitChar'], $conf['noTrimWrap.']['splitChar.'])
-                       : $conf['noTrimWrap.']['splitChar'];
-               if ($splitChar === NULL || $splitChar === '') {
-                       $splitChar = '|';
-               }
-               $content = $this->noTrimWrap(
-                       $content,
-                       $conf['noTrimWrap'],
-                       $splitChar
-               );
-               return $content;
-       }
-
-       /**
-        * wrap2
-        * Fifth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * The default split character is | but it can be replaced with other characters by the property splitChar
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for wrap2.
-        * @return string The processed input value
-        */
-       public function stdWrap_wrap2($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['wrap2'], $conf['wrap2.']['splitChar'] ? $conf['wrap2.']['splitChar'] : '|');
-       }
-
-       /**
-        * dataWrap
-        * Sixth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * Can fetch additional content the same way data does (i.e. {field:whatever}) and apply it to the wrap before that is applied to the content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for dataWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_dataWrap($content = '', $conf = array()) {
-               return $this->dataWrap($content, $conf['dataWrap']);
-       }
-
-       /**
-        * prepend
-        * A content object that will be prepended to the current content after most of the wraps have already been applied
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for prepend.
-        * @return string The processed input value
-        */
-       public function stdWrap_prepend($content = '', $conf = array()) {
-               return $this->cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content;
-       }
-
-       /**
-        * append
-        * A content object that will be appended to the current content after most of the wraps have already been applied
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for append.
-        * @return string The processed input value
-        */
-       public function stdWrap_append($content = '', $conf = array()) {
-               return $content . $this->cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append');
-       }
-
-       /**
-        * wrap3
-        * Seventh of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        * The default split character is | but it can be replaced with other characters by the property splitChar
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for wrap3.
-        * @return string The processed input value
-        */
-       public function stdWrap_wrap3($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['wrap3'], $conf['wrap3.']['splitChar'] ? $conf['wrap3.']['splitChar'] : '|');
-       }
-
-       /**
-        * orderedStdWrap
-        * Calls stdWrap for each entry in the provided array
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for orderedStdWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_orderedStdWrap($content = '', $conf = array()) {
-               $sortedKeysArray = TemplateService::sortedKeyList($conf['orderedStdWrap.'], TRUE);
-               foreach ($sortedKeysArray as $key) {
-                       $content = $this->stdWrap($content, $conf['orderedStdWrap.'][$key . '.']);
-               }
-               return $content;
-       }
-
-       /**
-        * outerWrap
-        * Eighth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for outerWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_outerWrap($content = '', $conf = array()) {
-               return $this->wrap($content, $conf['outerWrap']);
-       }
-
-       /**
-        * insertData
-        * Can fetch additional content the same way data does and replaces any occurrence of {field:whatever} with this content
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for insertData.
-        * @return string The processed input value
-        */
-       public function stdWrap_insertData($content = '', $conf = array()) {
-               return $this->insertData($content);
-       }
-
-       /**
-        * offsetWrap
-        * Creates a so called offset table around the content
-        * Still here for historical reasons even not used too much nowadays
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for offsetWrap.
-        * @return string The processed input value
-        */
-       public function stdWrap_offsetWrap($content = '', $conf = array()) {
-               $controlTable = GeneralUtility::makeInstance(OffsetTableContentObject::class);
-               if ($conf['offsetWrap.']['tableParams'] || $conf['offsetWrap.']['tableParams.']) {
-                       $controlTable->tableParams = isset($conf['offsetWrap.']['tableParams.']) ? $this->stdWrap($conf['offsetWrap.']['tableParams'], $conf['offsetWrap.']['tableParams.']) : $conf['offsetWrap.']['tableParams'];
-               }
-               if ($conf['offsetWrap.']['tdParams'] || $conf['offsetWrap.']['tdParams.']) {
-                       $controlTable->tdParams = ' ' . (isset($conf['offsetWrap.']['tdParams.']) ? $this->stdWrap($conf['offsetWrap.']['tdParams'], $conf['offsetWrap.']['tdParams.']) : $conf['offsetWrap.']['tdParams']);
-               }
-               $content = $controlTable->start($content, $conf['offsetWrap']);
-               if ($conf['offsetWrap.']['stdWrap.']) {
-                       $content = $this->stdWrap($content, $conf['offsetWrap.']['stdWrap.']);
-               }
-               return $content;
-       }
-
-       /**
-        * postUserFunc
-        * Will execute a user function after the content has been modified by any other stdWrap function
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for postUserFunc.
-        * @return string The processed input value
-        */
-       public function stdWrap_postUserFunc($content = '', $conf = array()) {
-               return $this->callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content);
-       }
-
-       /**
-        * postUserFuncInt
-        * Will execute a user function after the content has been created and each time it is fetched from Cache
-        * The result of this function itself will not be cached
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for postUserFuncInt.
-        * @return string The processed input value
-        */
-       public function stdWrap_postUserFuncInt($content = '', $conf = array()) {
-               $substKey = 'INT_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
-               $GLOBALS['TSFE']->config['INTincScript'][$substKey] = array(
-                       'content' => $content,
-                       'postUserFunc' => $conf['postUserFuncInt'],
-                       'conf' => $conf['postUserFuncInt.'],
-                       'type' => 'POSTUSERFUNC',
-                       'cObj' => serialize($this)
-               );
-               $content = '<!--' . $substKey . '-->';
-               return $content;
-       }
-
-       /**
-        * prefixComment
-        * Will add HTML comments to the content to make it easier to identify certain content elements within the HTML output later on
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for prefixComment.
-        * @return string The processed input value
-        */
-       public function stdWrap_prefixComment($content = '', $conf = array()) {
-               if (!$GLOBALS['TSFE']->config['config']['disablePrefixComment'] && !empty($conf['prefixComment'])) {
-                       $content = $this->prefixComment($conf['prefixComment'], array(), $content);
-               }
-               return $content;
-       }
-
-       /**
-        * editIcons
-        * Will render icons for frontend editing as long as there is a BE user logged in
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for editIcons.
-        * @return string The processed input value
-        */
-       public function stdWrap_editIcons($content = '', $conf = array()) {
-               if ($GLOBALS['TSFE']->beUserLogin && $conf['editIcons']) {
-                       if (!is_array($conf['editIcons.'])) {
-                               $conf['editIcons.'] = array();
-                       }
-                       $content = $this->editIcons($content, $conf['editIcons'], $conf['editIcons.']);
-               }
-               return $content;
-       }
-
-       /**
-        * editPanel
-        * Will render the edit panel for frontend editing as long as there is a BE user logged in
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for editPanel.
-        * @return string The processed input value
-        */
-       public function stdWrap_editPanel($content = '', $conf = array()) {
-               if ($GLOBALS['TSFE']->beUserLogin) {
-                       $content = $this->editPanel($content, $conf['editPanel.']);
-               }
-               return $content;
-       }
-
-       /**
-        * Store content into cache
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_cacheStore($content = '', $conf = array()) {
-               if (!empty($conf['cache.']['key'])) {
-                       /** @var $cacheFrontend \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend */
-                       $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
-                       if ($cacheFrontend) {
-                               $tags = !empty($conf['cache.']['tags']) ? GeneralUtility::trimExplode(',', $conf['cache.']['tags']) : array();
-                               if (strtolower($conf['cache.']['lifetime']) == 'unlimited') {
-                                       // unlimited
-                                       $lifetime = 0;
-                               } elseif (strtolower($conf['cache.']['lifetime']) == 'default') {
-                                       // default lifetime
-                                       $lifetime = NULL;
-                               } elseif ((int)$conf['cache.']['lifetime'] > 0) {
-                                       // lifetime in seconds
-                                       $lifetime = (int)$conf['cache.']['lifetime'];
-                               } else {
-                                       // default lifetime
-                                       $lifetime = NULL;
-                               }
-                               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'])) {
-                                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'] as $_funcRef) {
-                                               $params = array(
-                                                       'key' => $conf['cache.']['key'],
-                                                       'content' => $content,
-                                                       'lifetime' => $lifetime,
-                                                       'tags' => $tags
-                                               );
-                                               GeneralUtility::callUserFunction($_funcRef, $params, $this);
-                                       }
-                               }
-                               $cacheFrontend->set($conf['cache.']['key'], $content, $tags, $lifetime);
-                       }
-               }
-               return $content;
-       }
-
-       /**
-        * stdWrap post process hook
-        * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
-        * this hook executes functions at after the content has been modified by the rest of the stdWrap functions but still before debugging
-        *
-        * @param string $content Input value undergoing processing in these functions.
-        * @param array $conf All stdWrap properties, not just the ones for a particular function.
-        * @return string The processed input value
-        */
-       public function stdWrap_stdWrapPostProcess($content = '', $conf = array()) {
-               foreach ($this->stdWrapHookObjects as $hookObject) {
-                       $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
-               }
-               return $content;
-       }
-
-       /**
-        * debug
-        * Will output the content as readable HTML code
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for debug.
-        * @return string The processed input value
-        */
-       public function stdWrap_debug($content = '', $conf = array()) {
-               return '<pre>' . htmlspecialchars($content) . '</pre>';
-       }
-
-       /**
-        * debugFunc
-        * Will output the content in a debug table
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for debugFunc.
-        * @return string The processed input value
-        */
-       public function stdWrap_debugFunc($content = '', $conf = array()) {
-               debug($conf['debugFunc'] == 2 ? array(
-                       $content
-               ) : $content);
-               return $content;
-       }
-
-       /**
-        * debugData
-        * Will output the data used by the current record in a debug table
-        *
-        * @param string $content Input value undergoing processing in this function.
-        * @param array $conf stdWrap properties for debugData.
-        * @return string The processed input value
-        */
-       public function stdWrap_debugData($content = '', $conf = array()) {
-               debug($this->data, '$cObj->data:');
-               if (is_array($this->alternativeData)) {
-                       debug($this->alternativeData, '$this->alternativeData');
-               }
-               return $content;
-       }
-
-       /**
-        * Returns number of rows selected by the query made by the properties set.
-        * Implements the stdWrap "numRows" property
-        *
-        * @param array $conf TypoScript properties for the property (see link to "numRows")
-        * @return int The number of rows found by the select (FALSE on error)
-        * @access private
-        * @see stdWrap()
-        */
-       public function numRows($conf) {
-               $result = FALSE;
-               $conf['select.']['selectFields'] = 'count(*)';
-               $res = $this->exec_getQuery($conf['table'], $conf['select.']);
-               if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
-                       $GLOBALS['TT']->setTSlogMessage($error, 3);
-               } else {
-                       $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
-                       $result = (int)$row[0];
-               }
-               $GLOBALS['TYPO3_DB']->sql_free_result($res);
-               return $result;
-       }
-
-       /**
-        * Exploding a string by the $char value (if integer its an ASCII value) and returning index $listNum
-        *
-        * @param string $content String to explode
-        * @param string $listNum Index-number. You can place the word "last" in it and it will be substituted with the pointer to the last value. You can use math operators like "+-/*" (passed to calc())
-        * @param string $char Either a string used to explode the content string or an integer value which will then be changed into a character, eg. "10" for a linebreak char.
-        * @return string
-        */
-       public function listNum($content, $listNum, $char) {
-               $char = $char ?: ',';
-               if (MathUtility::canBeInterpretedAsInteger($char)) {
-                       $char = chr($char);
-               }
-               $temp = explode($char, $content);
-               $last = '' . (count($temp) - 1);
-               // Take a random item if requested
-               if ($listNum === 'rand') {
-                       $listNum = rand(0, count($temp) - 1);
-               }
-               $index = $this->calc(str_ireplace('last', $last, $listNum));
-               return $temp[$index];
-       }
-
-       /**
-        * Compares values together based on the settings in the input TypoScript array and returns TRUE or FALSE based on the comparison result.
-        * Implements the "if" function in TYPO3 TypoScript
-        *
-        * @param array $conf TypoScript properties defining what to compare
-        * @return bool
-        * @see stdWrap(), _parseFunc()
-        */
-       public function checkIf($conf) {
-               if (!is_array($conf)) {
-                       return TRUE;
-               }
-               if (isset($conf['directReturn'])) {
-                       return $conf['directReturn'] ? 1 : 0;
-               }
-               $flag = TRUE;
-               if (isset($conf['isNull.'])) {
-                       $isNull = $this->stdWrap('', $conf['isNull.']);
-                       if ($isNull !== NULL) {
-                               $flag = 0;
-                       }
-               }
-               if (isset($conf['isTrue']) || isset($conf['isTrue.'])) {
-                       $isTrue = isset($conf['isTrue.']) ? trim($this->stdWrap($conf['isTrue'], $conf['isTrue.'])) : trim($conf['isTrue']);
-                       if (!$isTrue) {
-                               $flag = 0;
-                       }
-               }
-               if (isset($conf['isFalse']) || isset($conf['isFalse.'])) {
-                       $isFalse = isset($conf['isFalse.']) ? trim($this->stdWrap($conf['isFalse'], $conf['isFalse.'])) : trim($conf['isFalse']);
-                       if ($isFalse) {
-                               $flag = 0;
-                       }
-               }
-               if (isset($conf['isPositive']) || isset($conf['isPositive.'])) {
-                       $number = isset($conf['isPositive.']) ? $this->calc($this->stdWrap($conf['isPositive'], $conf['isPositive.'])) : $this->calc($conf['isPositive']);
-                       if ($number < 1) {
-                               $flag = 0;
-                       }
-               }
-               if ($flag) {
-                       $value = isset($conf['value.']) ? trim($this->stdWrap($conf['value'], $conf['value.'])) : trim($conf['value']);
-                       if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) {
-                               $number = isset($conf['isGreaterThan.']) ? trim($this->stdWrap($conf['isGreaterThan'], $conf['isGreaterThan.'])) : trim($conf['isGreaterThan']);
-                               if ($number <= $value) {
-                                       $flag = 0;
-                               }
-                       }
-                       if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) {
-                               $number = isset($conf['isLessThan.']) ? trim($this->stdWrap($conf['isLessThan'], $conf['isLessThan.'])) : trim($conf['isLessThan']);
-                               if ($number >= $value) {
-                                       $flag = 0;
-                               }
-                       }
-                       if (isset($conf['equals']) || isset($conf['equals.'])) {
-                               $number = isset($conf['equals.']) ? trim($this->stdWrap($conf['equals'], $conf['equals.'])) : trim($conf['equals']);
-                               if ($number != $value) {
-                                       $flag = 0;
-                               }
-                       }
-                       if (isset($conf['isInList']) || isset($conf['isInList.'])) {
-                               $number = isset($conf['isInList.']) ? trim($this->stdWrap($conf['isInList'], $conf['isInList.'])) : trim($conf['isInList']);
-                               if (!GeneralUtility::inList($value, $number)) {
-                                       $flag = 0;
-                               }
-                       }
-               }
-               if ($conf['negate']) {
-                       $flag = $flag ? 0 : 1;
-               }
-               return $flag;
-       }
-
-       /**
-        * Reads a directory for files and returns the filepaths in a string list separated by comma.
-        * Implements the stdWrap property "filelist"
-        *
-        * @param string $data The command which contains information about what files/directory listing to return. See the "filelist" property of stdWrap for details.
-        * @return string Comma list of files.
-        * @access private
-        * @see stdWrap()
-        */
-       public function filelist($data) {
-               $data = trim($data);
-               if ($data) {
-                       $data_arr = explode('|', $data);
-                       // read directory:
-                       // MUST exist!
-                       if ($GLOBALS['TSFE']->lockFilePath) {
-                               // Cleaning name..., only relative paths accepted.
-                               $path = $this->clean_directory($data_arr[0]);
-                               // See if path starts with lockFilePath, the additional '/' is needed because clean_directory gets rid of it
-                               $path = GeneralUtility::isFirstPartOfStr($path . '/', $GLOBALS['TSFE']->lockFilePath) ? $path : '';
-                       }
-                       if ($path) {
-                               $items = array(
-                                       'files' => array(),
-                                       'sorting' => array()
-                               );
-                               $ext_list = strtolower(GeneralUtility::uniqueList($data_arr[1]));
-                               $sorting = trim($data_arr[2]);
-                               // Read dir:
-                               $d = @dir($path);
-                               $tempArray = array();
-                               if (is_object($d)) {
-                                       $count = 0;
-                                       while ($entry = $d->read()) {
-                                               if ($entry != '.' && $entry != '..') {
-                                                       // Because of odd PHP-error where <br />-tag is sometimes placed after a filename!!
-                                                       $wholePath = $path . '/' . $entry;
-                                                       if (file_exists($wholePath) && filetype($wholePath) == 'file') {
-                                                               $info = GeneralUtility::split_fileref($wholePath);
-                                                               if (!$ext_list || GeneralUtility::inList($ext_list, $info['fileext'])) {
-                                                                       $items['files'][] = $info['file'];
-                                                                       switch ($sorting) {
-                                                                               case 'name':
-                                                                                       $items['sorting'][] = strtolower($info['file']);
-                                                                                       break;
-                                                                               case 'size':
-                                                                                       $items['sorting'][] = filesize($wholePath);
-                                                                                       break;
-                                                                               case 'ext':
-                                                                                       $items['sorting'][] = $info['fileext'];
-                                                                                       break;
-                                                                               case 'date':
-                                                                                       $items['sorting'][] = filectime($wholePath);
-                                                                                       break;
-                                                                               case 'mdate':
-                                                                                       $items['sorting'][] = filemtime($wholePath);
-                                                                                       break;
-                                                                               default:
-                                                                                       $items['sorting'][] = $count;
-                                                                       }
-                                                                       $count++;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                                       $d->close();
-                               }
-                               // Sort if required
-                               if (count($items['sorting'])) {
-                                       if (strtolower(trim($data_arr[3])) != 'r') {
-                                               asort($items['sorting']);
-                                       } else {
-                                               arsort($items['sorting']);
-                                       }
-                               }
-                               if (count($items['files'])) {
-                                       // Make list
-                                       reset($items['sorting']);
-                                       $fullPath = trim($data_arr[4]);
-                                       $list_arr = array();
-                                       foreach ($items['sorting'] as $key => $v) {
-                                               $list_arr[] = $fullPath ? $path . '/' . $items['files'][$key] : $items['files'][$key];
-                                       }
-                                       return implode(',', $list_arr);
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Cleans $theDir for slashes in the end of the string and returns the new path, if it exists on the server.
-        *
-        * @param string $theDir Absolute path to directory
-        * @return string The directory path if it existed as was valid to access.
-        * @access private
-        * @see filelist()
-        */
-       public function clean_directory($theDir) {
-               // proceeds if no '//', '..' or '\' is in the $theFile
-               if (GeneralUtility::validPathStr($theDir)) {
-                       // Removes all dots, slashes and spaces after a path...
-                       $theDir = preg_replace('/[\\/\\. ]*$/', '', $theDir);
-                       if (!GeneralUtility::isAbsPath($theDir) && @is_dir($theDir)) {
-                               return $theDir;
-                       }
-               }
-       }
-
-       /**
-        * Passes the input value, $theValue, to an instance of "\TYPO3\CMS\Core\Html\HtmlParser"
-        * together with the TypoScript options which are first converted from a TS style array
-        * to a set of arrays with options for the \TYPO3\CMS\Core\Html\HtmlParser class.
-        *
-        * @param string $theValue The value to parse by the class \TYPO3\CMS\Core\Html\HtmlParser
-        * @param array $conf TypoScript properties for the parser. See link.
-        * @return string Return value.
-        * @see stdWrap(), \TYPO3\CMS\Core\Html\HtmlParser::HTMLparserConfig(), \TYPO3\CMS\Core\Html\HtmlParser::HTMLcleaner()
-        */
-       public function HTMLparser_TSbridge($theValue, $conf) {
-               $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
-               $htmlParserCfg = $htmlParser->HTMLparserConfig($conf);
-               return $htmlParser->HTMLcleaner($theValue, $htmlParserCfg[0], $htmlParserCfg[1], $htmlParserCfg[2], $htmlParserCfg[3]);
-       }
-
-       /**
-        * Wrapping input value in a regular "wrap" but parses the wrapping value first for "insertData" codes.
-        *
-        * @param string $content Input string being wrapped
-        * @param string $wrap The wrap string, eg. "<strong></strong>" or more likely here '<a href="index.php?id={TSFE:id}"> | </a>' which will wrap the input string in a <a> tag linking to the current page.
-        * @return string Output string wrapped in the wrapping value.
-        * @see insertData(), stdWrap()
-        */
-       public function dataWrap($content, $wrap) {
-               return $this->wrap($content, $this->insertData($wrap));
-       }
-
-       /**
-        * Implements the "insertData" property of stdWrap meaning that if strings matching {...} is found in the input string they will be substituted with the return value from getData (datatype) which is passed the content of the curly braces.
-        * Example: If input string is "This is the page title: {page:title}" then the part, '{page:title}', will be substituted with the current pages title field value.
-        *
-        * @param string $str Input value
-        * @return string Processed input value
-        * @see getData(), stdWrap(), dataWrap()
-        */
-       public function insertData($str) {
-               $inside = 0;
-               $newVal = '';
-               $pointer = 0;
-               $totalLen = strlen($str);
-               do {
-                       if (!$inside) {
-                               $len = strcspn(substr($str, $pointer), '{');
-                               $newVal .= substr($str, $pointer, $len);
-                               $inside = 1;
-                       } else {
-                               $len = strcspn(substr($str, $pointer), '}') + 1;
-                               $newVal .= $this->getData(substr($str, $pointer + 1, $len - 2), $this->data);
-                               $inside = 0;
-                       }
-                       $pointer += $len;
-               } while ($pointer < $totalLen);
-               return $newVal;
-       }
-
-       /**
-        * Returns a HTML comment with the second part of input string (divided by "|") where first part is an integer telling how many trailing tabs to put before the comment on a new line.
-        * Notice; this function (used by stdWrap) can be disabled by a "config.disablePrefixComment" setting in TypoScript.
-        *
-        * @param string $str Input value
-        * @param array $conf TypoScript Configuration (not used at this point.)
-        * @param string $content The content to wrap the comment around.
-        * @return string Processed input value
-        * @see stdWrap()
-        */
-       public function prefixComment($str, $conf, $content) {
-               if (empty($str)) {
-                       return $content;
-               }
-               $parts = explode('|', $str);
-               $indent = (int)$parts[0];
-               $comment = htmlspecialchars($this->insertData($parts[1]));
-               $output = LF
-                       . str_pad('', $indent, TAB) . '<!-- ' . $comment . ' [begin] -->' . LF
-                       . str_pad('', ($indent + 1), TAB) . $content . LF
-                       . str_pad('', $indent, TAB) . '<!-- ' . $comment . ' [end] -->' . LF
-                       . str_pad('', ($indent + 1), TAB);
-               return $output;
-       }
-
-       /**
-        * Implements the stdWrap property "substring" which is basically a TypoScript implementation of the PHP function, substr()
-        *
-        * @param string $content The string to perform the operation on
-        * @param string $options The parameters to substring, given as a comma list of integers where the first and second number is passed as arg 1 and 2 to substr().
-        * @return string The processed input value.
-        * @access private
-        * @see stdWrap()
-        */
-       public function substring($content, $options) {
-               $options = GeneralUtility::intExplode(',', $options . ',');
-               if ($options[1]) {
-                       return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0], $options[1]);
-               } else {
-                       return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0]);
-               }
-       }
-
-       /**
-        * Implements the stdWrap property "crop" which is a modified "substr" function allowing to limit a string length to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string really was cropped.
-        *
-        * @param string $content The string to perform the operation on
-        * @param string $options The parameters splitted by "|": First parameter is the max number of chars of the string. Negative value means cropping from end of string. Second parameter is the pre/postfix string to apply if cropping occurs. Third parameter is a boolean value. If set then crop will be applied at nearest space.
-        * @return string The processed input value.
-        * @access private
-        * @see stdWrap()
-        */
-       public function crop($content, $options) {
-               $options = explode('|', $options);
-               $chars = (int)$options[0];
-               $afterstring = trim($options[1]);
-               $crop2space = trim($options[2]);
-               if ($chars) {
-                       if ($GLOBALS['TSFE']->csConvObj->strlen($GLOBALS['TSFE']->renderCharset, $content) > abs($chars)) {
-                               $truncatePosition = FALSE;
-                               if ($chars < 0) {
-                                       $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $chars);
-                                       if ($crop2space) {
-                                               $truncatePosition = strpos($content, ' ');
-                                       }
-                                       $content = $truncatePosition ? $afterstring . substr($content, $truncatePosition) : $afterstring . $content;
-                               } else {
-                                       $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, 0, $chars);
-                                       if ($crop2space) {
-                                               $truncatePosition = strrpos($content, ' ');
-                                       }
-                                       $content = $truncatePosition ? substr($content, 0, $truncatePosition) . $afterstring : $content . $afterstring;
-                               }
-                       }
-               }
-               return $content;
-       }
-
-       /**
-        * Implements the stdWrap property "cropHTML" which is a modified "substr" function allowing to limit a string length
-        * to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string
-        * really was cropped.
-        *
-        * Compared to stdWrap.crop it respects HTML tags and entities.
-        *
-        * @param string $content The string to perform the operation on
-        * @param string $options The parameters splitted by "|": First parameter is the max number of chars of the string. Negative value means cropping from end of string. Second parameter is the pre/postfix string to apply if cropping occurs. Third parameter is a boolean value. If set then crop will be applied at nearest space.
-        * @return string The processed input value.
-        * @access private
-        * @see stdWrap()
-        */
-       public function cropHTML($content, $options) {
-               $options = explode('|', $options);
-               $chars = (int)$options[0];
-               $absChars = abs($chars);
-               $replacementForEllipsis = trim($options[1]);
-               $crop2space = trim($options[2]) === '1' ? TRUE : FALSE;
-               // Split $content into an array(even items in the array are outside the tags, odd numbers are tag-blocks).
-               $tags = 'a|b|blockquote|body|div|em|font|form|h1|h2|h3|h4|h5|h6|i|li|map|ol|option|p|pre|sub|sup|select|span|strong|table|thead|tbody|tfoot|td|textarea|tr|u|ul|br|hr|img|input|area|link';
-               // @todo We should not crop inside <script> tags.
-               $tagsRegEx = '
+    }
+
+    /**
+     * br
+     * Searches for single line breaks and replaces them with a <br />/<br> tag
+     * according to the doctype
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for br.
+     * @return string The processed input value
+     */
+    public function stdWrap_br($content = '')
+    {
+        return nl2br($content, !empty($this->getTypoScriptFrontendController()->xhtmlDoctype));
+    }
+
+    /**
+     * brTag
+     * Searches for single line feeds and replaces them with the given value
+     *
+     * @param string $content Input value undergoing processing in this function.
+     * @param array $conf stdWrap properties for brTag.
+     * @return string The processed input value
+     */
+    public function stdWrap_brTag($content = '', $conf = array())
+    {
+        return str_replace(LF, $conf['brTag'], $content);
+    }
+
+    /**
+     * encapsLines
+     * Modifies text blocks by searching for lines which are not surrounded by HTML tags yet
+     * and wrapping them with values given by stdWrap properties
+     *