‪TYPO3CMS  9.5
ContentObjectRenderer.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Doctrine\DBAL\DBALException;
18 use Doctrine\DBAL\Driver\Statement;
19 use Psr\Log\LoggerAwareInterface;
20 use Psr\Log\LoggerAwareTrait;
79 use TYPO3\HtmlSanitizer\Builder\BuilderInterface;
80 
90 class ‪ContentObjectRenderer implements LoggerAwareInterface
91 {
92  use LoggerAwareTrait;
93 
97  public ‪$align = [
98  'center',
99  'right',
100  'left'
101  ];
102 
108  public ‪$stdWrapOrder = [
109  'stdWrapPreProcess' => 'hook',
110  // this is a placeholder for the first Hook
111  'cacheRead' => 'hook',
112  // this is a placeholder for checking if the content is available in cache
113  'setContentToCurrent' => 'boolean',
114  'setContentToCurrent.' => 'array',
115  'addPageCacheTags' => 'string',
116  'addPageCacheTags.' => 'array',
117  'setCurrent' => 'string',
118  'setCurrent.' => 'array',
119  'lang.' => 'array',
120  'data' => 'getText',
121  'data.' => 'array',
122  'field' => 'fieldName',
123  'field.' => 'array',
124  'current' => 'boolean',
125  'current.' => 'array',
126  'cObject' => 'cObject',
127  'cObject.' => 'array',
128  'numRows.' => 'array',
129  // @deprecated - will be removed in TYPO3 v10.0.
130  'filelist' => 'dir',
131  // @deprecated - will be removed in TYPO3 v10.0.
132  'filelist.' => 'array',
133  'preUserFunc' => 'functionName',
134  'stdWrapOverride' => 'hook',
135  // this is a placeholder for the second Hook
136  'override' => 'string',
137  'override.' => 'array',
138  'preIfEmptyListNum' => 'listNum',
139  'preIfEmptyListNum.' => 'array',
140  'ifNull' => 'string',
141  'ifNull.' => 'array',
142  'ifEmpty' => 'string',
143  'ifEmpty.' => 'array',
144  'ifBlank' => 'string',
145  'ifBlank.' => 'array',
146  'listNum' => 'listNum',
147  'listNum.' => 'array',
148  'trim' => 'boolean',
149  'trim.' => 'array',
150  'strPad.' => 'array',
151  'stdWrap' => 'stdWrap',
152  'stdWrap.' => 'array',
153  'stdWrapProcess' => 'hook',
154  // this is a placeholder for the third Hook
155  'required' => 'boolean',
156  'required.' => 'array',
157  'if.' => 'array',
158  'fieldRequired' => 'fieldName',
159  'fieldRequired.' => 'array',
160  'csConv' => 'string',
161  'csConv.' => 'array',
162  'parseFunc' => 'objectpath',
163  'parseFunc.' => 'array',
164  'HTMLparser' => 'boolean',
165  'HTMLparser.' => 'array',
166  'split.' => 'array',
167  'replacement.' => 'array',
168  'prioriCalc' => 'boolean',
169  'prioriCalc.' => 'array',
170  'char' => 'integer',
171  'char.' => 'array',
172  'intval' => 'boolean',
173  'intval.' => 'array',
174  'hash' => 'string',
175  'hash.' => 'array',
176  'round' => 'boolean',
177  'round.' => 'array',
178  'numberFormat.' => 'array',
179  'expandList' => 'boolean',
180  'expandList.' => 'array',
181  'date' => 'dateconf',
182  'date.' => 'array',
183  'strtotime' => 'strtotimeconf',
184  'strtotime.' => 'array',
185  'strftime' => 'strftimeconf',
186  'strftime.' => 'array',
187  'age' => 'boolean',
188  'age.' => 'array',
189  'case' => 'case',
190  'case.' => 'array',
191  'bytes' => 'boolean',
192  'bytes.' => 'array',
193  'substring' => 'parameters',
194  'substring.' => 'array',
195  'cropHTML' => 'crop',
196  'cropHTML.' => 'array',
197  'stripHtml' => 'boolean',
198  'stripHtml.' => 'array',
199  'crop' => 'crop',
200  'crop.' => 'array',
201  'rawUrlEncode' => 'boolean',
202  'rawUrlEncode.' => 'array',
203  'htmlSpecialChars' => 'boolean',
204  'htmlSpecialChars.' => 'array',
205  'encodeForJavaScriptValue' => 'boolean',
206  'encodeForJavaScriptValue.' => 'array',
207  'doubleBrTag' => 'string',
208  'doubleBrTag.' => 'array',
209  'br' => 'boolean',
210  'br.' => 'array',
211  'brTag' => 'string',
212  'brTag.' => 'array',
213  'encapsLines.' => 'array',
214  'keywords' => 'boolean',
215  'keywords.' => 'array',
216  'innerWrap' => 'wrap',
217  'innerWrap.' => 'array',
218  'innerWrap2' => 'wrap',
219  'innerWrap2.' => 'array',
220  // @deprecated - will be removed in TYPO3 v10.0.
221  'addParams.' => 'array',
222  // @deprecated - will be removed in TYPO3 v10.0.
223  'filelink.' => 'array',
224  'preCObject' => 'cObject',
225  'preCObject.' => 'array',
226  'postCObject' => 'cObject',
227  'postCObject.' => 'array',
228  'wrapAlign' => 'align',
229  'wrapAlign.' => 'array',
230  'typolink.' => 'array',
231  'wrap' => 'wrap',
232  'wrap.' => 'array',
233  'noTrimWrap' => 'wrap',
234  'noTrimWrap.' => 'array',
235  'wrap2' => 'wrap',
236  'wrap2.' => 'array',
237  'dataWrap' => 'dataWrap',
238  'dataWrap.' => 'array',
239  'prepend' => 'cObject',
240  'prepend.' => 'array',
241  'append' => 'cObject',
242  'append.' => 'array',
243  'wrap3' => 'wrap',
244  'wrap3.' => 'array',
245  'orderedStdWrap' => 'stdWrap',
246  'orderedStdWrap.' => 'array',
247  'outerWrap' => 'wrap',
248  'outerWrap.' => 'array',
249  'insertData' => 'boolean',
250  'insertData.' => 'array',
251  'postUserFunc' => 'functionName',
252  'postUserFuncInt' => 'functionName',
253  'prefixComment' => 'string',
254  'prefixComment.' => 'array',
255  'editIcons' => 'string',
256  'editIcons.' => 'array',
257  'editPanel' => 'boolean',
258  'editPanel.' => 'array',
259  'htmlSanitize' => 'boolean',
260  'htmlSanitize.' => 'array',
261  'cacheStore' => 'hook',
262  // this is a placeholder for storing the content in cache
263  'stdWrapPostProcess' => 'hook',
264  // this is a placeholder for the last Hook
265  'debug' => 'boolean',
266  'debug.' => 'array',
267  'debugFunc' => 'boolean',
268  'debugFunc.' => 'array',
269  'debugData' => 'boolean',
270  'debugData.' => 'array'
271  ];
272 
278  protected ‪$contentObjectClassMap = [];
279 
289  public ‪$data = [];
290 
294  protected ‪$table = '';
295 
301  public ‪$oldData = [];
302 
308  public ‪$alternativeData = '';
309 
315  public ‪$parameters = [];
316 
320  public ‪$currentValKey = 'currentValue_kidjls9dksoje';
321 
328  public ‪$currentRecord = '';
329 
335  public ‪$currentRecordTotal = 0;
336 
342  public ‪$currentRecordNumber = 0;
343 
350 
356  public ‪$parentRecord = [];
357 
363  public ‪$checkPid_cache = [];
364 
368  public ‪$checkPid_badDoktypeList = '255';
369 
375  public ‪$lastTypoLinkUrl = '';
376 
382  public ‪$lastTypoLinkTarget = '';
383 
387  public ‪$lastTypoLinkLD = [];
388 
394  public ‪$recordRegister = [];
395 
402 
407 
413  protected ‪$stdWrapHookObjects = [];
414 
421 
425  protected ‪$currentFile;
426 
430  public ‪$doConvertToUserIntObject = false;
431 
437  protected ‪$userObjectType = false;
438 
442  protected ‪$stopRendering = [];
443 
447  protected ‪$stdWrapRecursionLevel = 0;
448 
453 
459  const ‪OBJECTTYPE_USER_INT = 1;
465  const ‪OBJECTTYPE_USER = 2;
466 
471  {
472  $this->typoScriptFrontendController = ‪$typoScriptFrontendController;
473  $this->contentObjectClassMap = ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'];
474  }
475 
483  public function ‪__sleep()
484  {
485  $vars = get_object_vars($this);
486  unset($vars['typoScriptFrontendController'], $vars['logger']);
487  if ($this->currentFile instanceof ‪FileReference) {
488  $this->currentFile = 'FileReference:' . $this->currentFile->getUid();
489  } elseif ($this->currentFile instanceof ‪File) {
490  $this->currentFile = 'File:' . $this->currentFile->getIdentifier();
491  } else {
492  unset($vars['currentFile']);
493  }
494  return array_keys($vars);
495  }
496 
502  public function ‪__wakeup()
503  {
504  if (isset(‪$GLOBALS['TSFE'])) {
505  $this->typoScriptFrontendController = ‪$GLOBALS['TSFE'];
506  }
507  if ($this->currentFile !== null && is_string($this->currentFile)) {
508  list($objectType, $identifier) = explode(':', $this->currentFile, 2);
509  try {
510  if ($objectType === 'File') {
511  $this->currentFile = ‪ResourceFactory::getInstance()->‪retrieveFileOrFolderObject($identifier);
512  } elseif ($objectType === 'FileReference') {
513  $this->currentFile = ‪ResourceFactory::getInstance()->‪getFileReferenceObject($identifier);
514  }
515  } catch (ResourceDoesNotExistException $e) {
516  $this->currentFile = null;
517  }
518  }
519  $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
520  }
521 
532  {
533  $this->contentObjectClassMap = ‪$contentObjectClassMap;
534  }
535 
546  public function ‪registerContentObjectClass($className, $contentObjectName)
547  {
548  $this->contentObjectClassMap[$contentObjectName] = $className;
549  }
550 
559  public function ‪start(‪$data, ‪$table = '')
560  {
561  $this->data = ‪$data;
562  $this->table = ‪$table;
563  $this->currentRecord = ‪$table !== ''
564  ? ‪$table . ':' . ($this->data['uid'] ?? '')
565  : '';
566  $this->parameters = [];
567  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] ?? [] as $classArr) {
568  $this->cObjHookObjectsRegistry[$classArr[0]] = $classArr[1];
569  }
570  $this->stdWrapHookObjects = [];
571  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] ?? [] as $className) {
572  $hookObject = GeneralUtility::makeInstance($className);
573  if (!$hookObject instanceof ‪ContentObjectStdWrapHookInterface) {
574  throw new \UnexpectedValueException($className . ' must implement interface ' . ContentObjectStdWrapHookInterface::class, 1195043965);
575  }
576  $this->stdWrapHookObjects[] = $hookObject;
577  }
578  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] ?? [] as $className) {
579  $postInitializationProcessor = GeneralUtility::makeInstance($className);
580  if (!$postInitializationProcessor instanceof ‪ContentObjectPostInitHookInterface) {
581  throw new \UnexpectedValueException($className . ' must implement interface ' . ContentObjectPostInitHookInterface::class, 1274563549);
582  }
583  $postInitializationProcessor->postProcessContentObjectInitialization($this);
584  }
585  }
586 
592  public function ‪getCurrentTable()
593  {
594  return ‪$this->table;
595  }
596 
603  protected function ‪getGetImgResourceHookObjects()
604  {
605  if (!isset($this->getImgResourceHookObjects)) {
606  $this->getImgResourceHookObjects = [];
607  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] ?? [] as $className) {
608  $hookObject = GeneralUtility::makeInstance($className);
609  if (!$hookObject instanceof ContentObjectGetImageResourceHookInterface) {
610  throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetImageResourceHookInterface::class, 1218636383);
611  }
612  $this->getImgResourceHookObjects[] = $hookObject;
613  }
614  }
616  }
617 
626  public function ‪setParent(‪$data, ‪$currentRecord)
627  {
628  $this->parentRecord = [
629  'data' => ‪$data,
630  'currentRecord' => ‪$currentRecord
631  ];
632  }
633 
634  /***********************************************
635  *
636  * CONTENT_OBJ:
637  *
638  ***********************************************/
647  public function ‪getCurrentVal()
648  {
649  return $this->data[‪$this->currentValKey];
650  }
651 
658  public function ‪setCurrentVal($value)
659  {
660  $this->data[‪$this->currentValKey] = $value;
661  }
662 
672  public function ‪cObjGet($setup, $addKey = '')
673  {
674  if (!is_array($setup)) {
675  return '';
676  }
677  $sKeyArray = ‪ArrayUtility::filterAndSortByNumericKeys($setup);
678  $content = '';
679  foreach ($sKeyArray as $theKey) {
680  $theValue = $setup[$theKey];
681  if ((int)$theKey && strpos($theKey, '.') === false) {
682  $conf = $setup[$theKey . '.'];
683  $content .= $this->‪cObjGetSingle($theValue, $conf, $addKey . $theKey);
684  }
685  }
686  return $content;
687  }
688 
698  public function ‪cObjGetSingle($name, $conf, $TSkey = '__')
699  {
700  $content = '';
701  // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
702  $this->‪getTypoScriptFrontendController()->cObjectDepthCounter--;
703  if ($this->‪getTypoScriptFrontendController()->cObjectDepthCounter > 0) {
704  $timeTracker = $this->‪getTimeTracker();
705  $name = trim($name);
706  if ($timeTracker->LR) {
707  $timeTracker->push($TSkey, $name);
708  }
709  // Checking if the COBJ is a reference to another object. (eg. name of 'some.object =< styles.something')
710  if (isset($name[0]) && $name[0] === '<') {
711  $key = trim(substr($name, 1));
712  $cF = GeneralUtility::makeInstance(TypoScriptParser::class);
713  // $name and $conf is loaded with the referenced values.
714  $confOverride = is_array($conf) ? $conf : [];
715  list($name, $conf) = $cF->getVal($key, $this->‪getTypoScriptFrontendController()->tmpl->setup);
716  $conf = array_replace_recursive(is_array($conf) ? $conf : [], $confOverride);
717  // Getting the cObject
718  $timeTracker->incStackPointer();
719  $content .= $this->‪cObjGetSingle($name, $conf, $key);
720  $timeTracker->decStackPointer();
721  } else {
722  $hooked = false;
723  // Application defined cObjects
724  if (!empty($this->cObjHookObjectsRegistry[$name])) {
725  if (empty($this->cObjHookObjectsArr[$name])) {
726  $this->cObjHookObjectsArr[$name] = GeneralUtility::makeInstance($this->cObjHookObjectsRegistry[$name]);
727  }
728  $hookObj = $this->cObjHookObjectsArr[$name];
729  if (method_exists($hookObj, 'cObjGetSingleExt')) {
730  $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
731  $hooked = true;
732  }
733  }
734  if (!$hooked) {
735  $contentObject = $this->‪getContentObject($name);
736  if ($contentObject) {
737  $content .= $this->‪render($contentObject, $conf);
738  } else {
739  // Call hook functions for extra processing
740  if ($name) {
741  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] ?? [] as $className) {
742  $hookObject = GeneralUtility::makeInstance($className);
743  if (!$hookObject instanceof ContentObjectGetSingleHookInterface) {
744  throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetSingleHookInterface::class, 1195043731);
745  }
747  $content .= $hookObject->getSingleContentObject($name, (array)$conf, $TSkey, $this);
748  }
749  } else {
750  // Log error in AdminPanel
751  $warning = sprintf('Content Object "%s" does not exist', $name);
752  $timeTracker->setTSlogMessage($warning, 2);
753  }
754  }
755  }
756  }
757  if ($timeTracker->LR) {
758  $timeTracker->pull($content);
759  }
760  }
761  // Increasing on exit...
762  $this->‪getTypoScriptFrontendController()->cObjectDepthCounter++;
763  return $content;
764  }
765 
775  public function ‪getContentObject($name)
776  {
777  if (!isset($this->contentObjectClassMap[$name])) {
778  return null;
779  }
780  $fullyQualifiedClassName = $this->contentObjectClassMap[$name];
781  $contentObject = GeneralUtility::makeInstance($fullyQualifiedClassName, $this);
782  if (!($contentObject instanceof ‪AbstractContentObject)) {
783  throw new ‪ContentRenderingException(sprintf('Registered content object class name "%s" must be an instance of AbstractContentObject, but is not!', $fullyQualifiedClassName), 1422564295);
784  }
785  return $contentObject;
786  }
787 
788  /********************************************
789  *
790  * Functions rendering content objects (cObjects)
791  *
792  ********************************************/
793 
805  public function ‪render(AbstractContentObject $contentObject, $configuration = [])
806  {
807  $content = '';
808 
809  // Evaluate possible cache and return
810  $cacheConfiguration = $configuration['cache.'] ?? null;
811  if ($cacheConfiguration !== null) {
812  unset($configuration['cache.']);
813  $cache = $this->‪getFromCache($cacheConfiguration);
814  if ($cache !== false) {
815  return $cache;
816  }
817  }
818 
819  // Render content
820  try {
821  $content .= $contentObject->render($configuration);
822  } catch (ContentRenderingException $exception) {
823  // Content rendering Exceptions indicate a critical problem which should not be
824  // caught e.g. when something went wrong with Exception handling itself
825  throw $exception;
826  } catch (\Exception $exception) {
827  $exceptionHandler = $this->‪createExceptionHandler($configuration);
828  if ($exceptionHandler === null) {
829  throw $exception;
830  }
831  $content = $exceptionHandler->handle($exception, $contentObject, $configuration);
832  }
833 
834  // Store cache
835  if ($cacheConfiguration !== null && !$this->‪getTypoScriptFrontendController()->no_cache) {
836  $key = $this->‪calculateCacheKey($cacheConfiguration);
837  if (!empty($key)) {
839  $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
840  $tags = $this->‪calculateCacheTags($cacheConfiguration);
841  $lifetime = $this->‪calculateCacheLifetime($cacheConfiguration);
842  $cacheFrontend->set($key, $content, $tags, $lifetime);
843  }
844  }
845 
846  return $content;
847  }
848 
857  protected function ‪createExceptionHandler($configuration = [])
858  {
859  $exceptionHandler = null;
860  $exceptionHandlerClassName = $this->‪determineExceptionHandlerClassName($configuration);
861  if (!empty($exceptionHandlerClassName)) {
862  $exceptionHandler = GeneralUtility::makeInstance($exceptionHandlerClassName, $this->‪mergeExceptionHandlerConfiguration($configuration));
863  if (!$exceptionHandler instanceof ExceptionHandlerInterface) {
864  throw new ContentRenderingException('An exception handler was configured but the class does not exist or does not implement the ExceptionHandlerInterface', 1403653369);
865  }
866  }
867 
868  return $exceptionHandler;
869  }
870 
877  protected function ‪determineExceptionHandlerClassName($configuration)
878  {
879  $exceptionHandlerClassName = null;
881  if (!isset($tsfe->config['config']['contentObjectExceptionHandler'])) {
882  if (GeneralUtility::getApplicationContext()->isProduction()) {
883  $exceptionHandlerClassName = '1';
884  }
885  } else {
886  $exceptionHandlerClassName = $tsfe->config['config']['contentObjectExceptionHandler'];
887  }
888 
889  if (isset($configuration['exceptionHandler'])) {
890  $exceptionHandlerClassName = $configuration['exceptionHandler'];
891  }
892 
893  if ($exceptionHandlerClassName === '1') {
894  $exceptionHandlerClassName = ProductionExceptionHandler::class;
895  }
896 
897  return $exceptionHandlerClassName;
898  }
899 
907  protected function ‪mergeExceptionHandlerConfiguration($configuration)
908  {
909  $exceptionHandlerConfiguration = [];
910  $tsfe = $this->‪getTypoScriptFrontendController();
911  if (!empty($tsfe->config['config']['contentObjectExceptionHandler.'])) {
912  $exceptionHandlerConfiguration = $tsfe->config['config']['contentObjectExceptionHandler.'];
913  }
914  if (!empty($configuration['exceptionHandler.'])) {
915  $exceptionHandlerConfiguration = array_replace_recursive($exceptionHandlerConfiguration, $configuration['exceptionHandler.']);
916  }
917 
918  return $exceptionHandlerConfiguration;
919  }
920 
929  public function ‪getUserObjectType()
930  {
932  }
933 
940  {
941  $this->userObjectType = ‪$userObjectType;
942  }
943 
947  public function ‪convertToUserIntObject()
948  {
949  if ($this->userObjectType !== self::OBJECTTYPE_USER) {
950  $this->‪getTimeTracker()->‪setTSlogMessage(self::class . '::convertToUserIntObject() is called in the wrong context or for the wrong object type', 2);
951  } else {
952  $this->doConvertToUserIntObject = true;
953  }
954  }
955 
956  /************************************
957  *
958  * Various helper functions for content objects:
959  *
960  ************************************/
968  public function ‪readFlexformIntoConf($flexData, &$conf, $recursive = false)
969  {
970  if ($recursive === false && is_string($flexData)) {
971  $flexData = GeneralUtility::xml2array($flexData, 'T3');
972  }
973  if (is_array($flexData) && isset($flexData['data']['sDEF']['lDEF'])) {
974  $flexData = $flexData['data']['sDEF']['lDEF'];
975  }
976  if (!is_array($flexData)) {
977  return;
978  }
979  foreach ($flexData as $key => $value) {
980  if (!is_array($value)) {
981  continue;
982  }
983  if (isset($value['el'])) {
984  if (is_array($value['el']) && !empty($value['el'])) {
985  foreach ($value['el'] as $ekey => $element) {
986  if (isset($element['vDEF'])) {
987  $conf[$ekey] = $element['vDEF'];
988  } else {
989  if (is_array($element)) {
990  $this->‪readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], true);
991  } else {
992  $this->‪readFlexformIntoConf($element, $conf[$key][$ekey], true);
993  }
994  }
995  }
996  } else {
997  $this->‪readFlexformIntoConf($value['el'], $conf[$key], true);
998  }
999  }
1000  if (isset($value['vDEF'])) {
1001  $conf[$key] = $value['vDEF'];
1002  }
1003  }
1004  }
1005 
1014  public function ‪getSlidePids($pidList, $pidConf)
1015  {
1016  $pidList = isset($pidConf) ? trim($this->‪stdWrap($pidList, $pidConf)) : trim($pidList);
1017  if ($pidList === '') {
1018  $pidList = 'this';
1019  }
1020  $tsfe = $this->‪getTypoScriptFrontendController();
1021  $listArr = null;
1022  if (trim($pidList)) {
1023  $listArr = GeneralUtility::intExplode(',', str_replace('this', $tsfe->contentPid, $pidList));
1024  $listArr = $this->‪checkPidArray($listArr);
1025  }
1026  $pidList = [];
1027  if (is_array($listArr) && !empty($listArr)) {
1028  foreach ($listArr as $uid) {
1029  $page = $tsfe->sys_page->getPage($uid);
1030  if (!$page['is_siteroot']) {
1031  $pidList[] = $page['pid'];
1032  }
1033  }
1034  }
1035  return implode(',', $pidList);
1036  }
1037 
1049  public function ‪cImage($file, $conf)
1050  {
1051  $tsfe = $this->‪getTypoScriptFrontendController();
1052  $info = $this->‪getImgResource($file, $conf['file.']);
1053  $tsfe->lastImageInfo = $info;
1054  if (!is_array($info)) {
1055  return '';
1056  }
1057  if (is_file(‪Environment::getPublicPath() . '/' . $info['3'])) {
1058  $source = $tsfe->absRefPrefix . str_replace('%2F', '/', rawurlencode($info['3']));
1059  } else {
1060  $source = $info[3];
1061  }
1062 
1063  $layoutKey = $this->‪stdWrap($conf['layoutKey'], $conf['layoutKey.']);
1064  $imageTagTemplate = $this->‪getImageTagTemplate($layoutKey, $conf);
1065  $sourceCollection = $this->‪getImageSourceCollection($layoutKey, $conf, $file);
1066 
1067  // This array is used to collect the image-refs on the page...
1068  $tsfe->imagesOnPage[] = $source;
1069  $altParam = $this->‪getAltParam($conf);
1070  $params = $this->‪stdWrapValue('params', $conf);
1071  if ($params !== '' && $params[0] !== ' ') {
1072  $params = ' ' . $params;
1073  }
1074 
1075  $imageTagValues = [
1076  'width' => (int)$info[0],
1077  'height' => (int)$info[1],
1078  'src' => htmlspecialchars($source),
1079  'params' => $params,
1080  'altParams' => $altParam,
1081  'border' => $this->‪getBorderAttr(' border="' . (int)$conf['border'] . '"'),
1082  'sourceCollection' => $sourceCollection,
1083  'selfClosingTagSlash' => !empty($tsfe->xhtmlDoctype) ? ' /' : '',
1084  ];
1085 
1086  $markerTemplateEngine = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
1087  $theValue = $markerTemplateEngine->substituteMarkerArray($imageTagTemplate, $imageTagValues, '###|###', true, true);
1088 
1089  $linkWrap = isset($conf['linkWrap.']) ? $this->‪stdWrap($conf['linkWrap'], $conf['linkWrap.']) : $conf['linkWrap'];
1090  if ($linkWrap) {
1091  $theValue = $this->‪linkWrap($theValue, $linkWrap);
1092  } elseif ($conf['imageLinkWrap']) {
1093  $originalFile = !empty($info['originalFile']) ? $info['originalFile'] : $info['origFile'];
1094  $theValue = $this->‪imageLinkWrap($theValue, $originalFile, $conf['imageLinkWrap.']);
1095  }
1096  $wrap = isset($conf['wrap.']) ? $this->‪stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
1097  if ((string)$wrap !== '') {
1098  $theValue = $this->‪wrap($theValue, $conf['wrap']);
1099  }
1100  return $theValue;
1101  }
1102 
1110  public function ‪getBorderAttr($borderAttr)
1111  {
1112  $tsfe = $this->‪getTypoScriptFrontendController();
1113  $docType = $tsfe->xhtmlDoctype;
1114  if (
1115  $docType !== 'xhtml_strict' && $docType !== 'xhtml_11'
1116  && $tsfe->config['config']['doctype'] !== 'html5'
1117  && !$tsfe->config['config']['disableImgBorderAttr']
1118  ) {
1119  return $borderAttr;
1120  }
1121  return '';
1122  }
1123 
1132  public function ‪getImageTagTemplate($layoutKey, $conf)
1133  {
1134  if ($layoutKey && isset($conf['layout.']) && isset($conf['layout.'][$layoutKey . '.'])) {
1135  $imageTagLayout = $this->‪stdWrap(
1136  $conf['layout.'][$layoutKey . '.']['element'] ?? '',
1137  $conf['layout.'][$layoutKey . '.']['element.'] ?? []
1138  );
1139  } else {
1140  $imageTagLayout = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
1141  }
1142  return $imageTagLayout;
1143  }
1144 
1154  public function ‪getImageSourceCollection($layoutKey, $conf, $file)
1155  {
1156  $sourceCollection = '';
1157  if ($layoutKey
1158  && isset($conf['sourceCollection.']) && $conf['sourceCollection.']
1159  && (
1160  isset($conf['layout.'][$layoutKey . '.']['source']) && $conf['layout.'][$layoutKey . '.']['source']
1161  || isset($conf['layout.'][$layoutKey . '.']['source.']) && $conf['layout.'][$layoutKey . '.']['source.']
1162  )
1163  ) {
1164 
1165  // find active sourceCollection
1166  $activeSourceCollections = [];
1167  foreach ($conf['sourceCollection.'] as $sourceCollectionKey => $sourceCollectionConfiguration) {
1168  if (substr($sourceCollectionKey, -1) === '.') {
1169  if (empty($sourceCollectionConfiguration['if.']) || $this->‪checkIf($sourceCollectionConfiguration['if.'])) {
1170  $activeSourceCollections[] = $sourceCollectionConfiguration;
1171  }
1172  }
1173  }
1174 
1175  // apply option split to configurations
1176  $tsfe = $this->‪getTypoScriptFrontendController();
1177  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
1178  $srcLayoutOptionSplitted = $typoScriptService->explodeConfigurationForOptionSplit((array)$conf['layout.'][$layoutKey . '.'], count($activeSourceCollections));
1179 
1180  // render sources
1181  foreach ($activeSourceCollections as $key => $sourceConfiguration) {
1182  $sourceLayout = $this->‪stdWrap(
1183  $srcLayoutOptionSplitted[$key]['source'] ?? '',
1184  $srcLayoutOptionSplitted[$key]['source.'] ?? []
1185  );
1186 
1187  $sourceRenderConfiguration = [
1188  'file' => $file,
1189  'file.' => $conf['file.'] ?? null
1190  ];
1191 
1192  if (isset($sourceConfiguration['quality']) || isset($sourceConfiguration['quality.'])) {
1193  $imageQuality = $sourceConfiguration['quality'] ?? '';
1194  if (isset($sourceConfiguration['quality.'])) {
1195  $imageQuality = $this->‪stdWrap($sourceConfiguration['quality'], $sourceConfiguration['quality.']);
1196  }
1197  if ($imageQuality) {
1198  $sourceRenderConfiguration['file.']['params'] = '-quality ' . (int)$imageQuality;
1199  }
1200  }
1201 
1202  if (isset($sourceConfiguration['pixelDensity'])) {
1203  $pixelDensity = (int)$this->‪stdWrap(
1204  $sourceConfiguration['pixelDensity'] ?? '',
1205  $sourceConfiguration['pixelDensity.'] ?? []
1206  );
1207  } else {
1208  $pixelDensity = 1;
1209  }
1210  $dimensionKeys = ['width', 'height', 'maxW', 'minW', 'maxH', 'minH', 'maxWidth', 'maxHeight', 'XY'];
1211  foreach ($dimensionKeys as $dimensionKey) {
1212  $dimension = $this->‪stdWrap(
1213  $sourceConfiguration[$dimensionKey] ?? '',
1214  $sourceConfiguration[$dimensionKey . '.'] ?? []
1215  );
1216  if (!$dimension) {
1217  $dimension = $this->‪stdWrap(
1218  $conf['file.'][$dimensionKey] ?? '',
1219  $conf['file.'][$dimensionKey . '.'] ?? []
1220  );
1221  }
1222  if ($dimension) {
1223  if (strstr($dimension, 'c') !== false && ($dimensionKey === 'width' || $dimensionKey === 'height')) {
1224  $dimensionParts = explode('c', $dimension, 2);
1225  $dimension = ((int)$dimensionParts[0] * $pixelDensity) . 'c';
1226  if ($dimensionParts[1]) {
1227  $dimension .= $dimensionParts[1];
1228  }
1229  } elseif ($dimensionKey === 'XY') {
1230  $dimensionParts = GeneralUtility::intExplode(',', $dimension, false, 2);
1231  $dimension = $dimensionParts[0] * $pixelDensity;
1232  if ($dimensionParts[1]) {
1233  $dimension .= ',' . $dimensionParts[1] * $pixelDensity;
1234  }
1235  } else {
1236  $dimension = (int)$dimension * $pixelDensity;
1237  }
1238  $sourceRenderConfiguration['file.'][$dimensionKey] = $dimension;
1239  // Remove the stdWrap properties for dimension as they have been processed already above.
1240  unset($sourceRenderConfiguration['file.'][$dimensionKey . '.']);
1241  }
1242  }
1243  $sourceInfo = $this->‪getImgResource($sourceRenderConfiguration['file'], $sourceRenderConfiguration['file.']);
1244  if ($sourceInfo) {
1245  $sourceConfiguration['width'] = $sourceInfo[0];
1246  $sourceConfiguration['height'] = $sourceInfo[1];
1247  $urlPrefix = '';
1248  if (parse_url($sourceInfo[3], PHP_URL_HOST) === null) {
1249  $urlPrefix = $tsfe->absRefPrefix;
1250  }
1251  $sourceConfiguration['src'] = htmlspecialchars($urlPrefix . $sourceInfo[3]);
1252  $sourceConfiguration['selfClosingTagSlash'] = !empty($tsfe->xhtmlDoctype) ? ' /' : '';
1253 
1254  $markerTemplateEngine = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
1255  $oneSourceCollection = $markerTemplateEngine->substituteMarkerArray($sourceLayout, $sourceConfiguration, '###|###', true, true);
1256 
1257  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'] ?? [] as $className) {
1258  $hookObject = GeneralUtility::makeInstance($className);
1259  if (!$hookObject instanceof ‪ContentObjectOneSourceCollectionHookInterface) {
1260  throw new \UnexpectedValueException(
1261  '$hookObject must implement interface ' . ContentObjectOneSourceCollectionHookInterface::class,
1262  1380007853
1263  );
1264  }
1265  $oneSourceCollection = $hookObject->getOneSourceCollection((array)$sourceRenderConfiguration, (array)$sourceConfiguration, $oneSourceCollection, $this);
1266  }
1267 
1268  $sourceCollection .= $oneSourceCollection;
1269  }
1270  }
1271  }
1272  return $sourceCollection;
1273  }
1274 
1284  public function ‪imageLinkWrap($string, $imageFile, $conf)
1285  {
1286  $string = (string)$string;
1287  $enable = isset($conf['enable.']) ? $this->‪stdWrap($conf['enable'], $conf['enable.']) : $conf['enable'];
1288  if (!$enable) {
1289  return $string;
1290  }
1291  $content = (string)$this->‪typoLink($string, $conf['typolink.']);
1292  if (isset($conf['file.'])) {
1293  $imageFile = $this->‪stdWrap($imageFile, $conf['file.']);
1294  }
1295 
1296  if ($imageFile instanceof File) {
1297  $file = $imageFile;
1298  } elseif ($imageFile instanceof FileReference) {
1299  $file = $imageFile->getOriginalFile();
1300  } else {
1302  $file = ‪ResourceFactory::getInstance()->‪getFileObject((int)$imageFile);
1303  } else {
1305  }
1306  }
1307 
1308  // Create imageFileLink if not created with typolink
1309  if ($content === $string && $file !== null) {
1310  $parameterNames = ['width', 'height', 'effects', 'bodyTag', 'title', 'wrap', 'crop'];
1311  ‪$parameters = [];
1312  $sample = isset($conf['sample.']) ? $this->‪stdWrap($conf['sample'], $conf['sample.']) : $conf['sample'];
1313  if ($sample) {
1314  ‪$parameters['sample'] = 1;
1315  }
1316  foreach ($parameterNames as $parameterName) {
1317  if (isset($conf[$parameterName . '.'])) {
1318  $conf[$parameterName] = $this->‪stdWrap($conf[$parameterName], $conf[$parameterName . '.']);
1319  }
1320  if (isset($conf[$parameterName]) && $conf[$parameterName]) {
1321  ‪$parameters[$parameterName] = $conf[$parameterName];
1322  }
1323  }
1324  $parametersEncoded = base64_encode(json_encode(‪$parameters));
1325  $hmac = GeneralUtility::hmac(implode('|', [$file->getUid(), $parametersEncoded]));
1326  $params = '&md5=' . $hmac;
1327  foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
1328  $params .= '&parameters' . rawurlencode('[') . $index . rawurlencode(']') . '=' . rawurlencode($chunk);
1329  }
1330  $url = $this->‪getTypoScriptFrontendController()->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . $file->getUid() . $params;
1331  $directImageLink = isset($conf['directImageLink.']) ? $this->‪stdWrap($conf['directImageLink'], $conf['directImageLink.']) : $conf['directImageLink'];
1332  if ($directImageLink) {
1333  $imgResourceConf = [
1334  'file' => $imageFile,
1335  'file.' => $conf
1336  ];
1337  $url = $this->‪cObjGetSingle('IMG_RESOURCE', $imgResourceConf);
1338  if (!$url) {
1339  // If no imagemagick / gm is available
1340  $url = $imageFile;
1341  }
1342  }
1343  // Create TARGET-attribute only if the right doctype is used
1344  $target = '';
1345  $xhtmlDocType = $this->‪getTypoScriptFrontendController()->xhtmlDoctype;
1346  if ($xhtmlDocType !== 'xhtml_strict' && $xhtmlDocType !== 'xhtml_11') {
1347  $target = isset($conf['target.'])
1348  ? (string)$this->‪stdWrap($conf['target'], $conf['target.'])
1349  : (string)$conf['target'];
1350  if ($target === '') {
1351  $target = 'thePicture';
1352  }
1353  }
1354  $a1 = '';
1355  $a2 = '';
1356  $conf['JSwindow'] = isset($conf['JSwindow.']) ? $this->‪stdWrap($conf['JSwindow'], $conf['JSwindow.']) : $conf['JSwindow'];
1357  if ($conf['JSwindow']) {
1358  if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
1359  $altUrl = isset($conf['JSwindow.']['altUrl.']) ? $this->‪stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.']) : $conf['JSwindow.']['altUrl'];
1360  if ($altUrl) {
1361  $url = $altUrl . ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' . rawurlencode($imageFile) . $params);
1362  }
1363  }
1364 
1365  $processedFile = $file->process(‪ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $conf);
1366  $JSwindowExpand = isset($conf['JSwindow.']['expand.']) ? $this->‪stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.']) : $conf['JSwindow.']['expand'];
1367  $offset = GeneralUtility::intExplode(',', $JSwindowExpand . ',');
1368  $newWindow = isset($conf['JSwindow.']['newWindow.']) ? $this->‪stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.']) : $conf['JSwindow.']['newWindow'];
1369  $onClick = 'openPic('
1370  . GeneralUtility::quoteJSvalue($this->‪getTypoScriptFrontendController()->baseUrlWrap($url)) . ','
1371  . '\'' . ($newWindow ? md5($url) : 'thePicture') . '\','
1372  . GeneralUtility::quoteJSvalue('width=' . ($processedFile->getProperty('width') + $offset[0])
1373  . ',height=' . ($processedFile->getProperty('height') + $offset[1]) . ',status=0,menubar=0')
1374  . '); return false;';
1375  $a1 = '<a href="' . htmlspecialchars($url) . '"'
1376  . ' onclick="' . htmlspecialchars($onClick) . '"'
1377  . ($target !== '' ? ' target="' . htmlspecialchars($target) . '"' : '')
1378  . $this->‪getTypoScriptFrontendController()->ATagParams . '>';
1379  $a2 = '</a>';
1380  $this->‪getTypoScriptFrontendController()->‪setJS('openPic');
1381  } else {
1382  $conf['linkParams.']['directImageLink'] = (bool)$conf['directImageLink'];
1383  $conf['linkParams.']['parameter'] = $url;
1384  $string = $this->‪typoLink($string, $conf['linkParams.']);
1385  }
1386  if (isset($conf['stdWrap.'])) {
1387  $string = $this->‪stdWrap($string, $conf['stdWrap.']);
1388  }
1389  $content = $a1 . $string . $a2;
1390  }
1391  return $content;
1392  }
1402  public function ‪lastChanged($tstamp)
1403  {
1404  $tstamp = (int)$tstamp;
1405  $tsfe = $this->‪getTypoScriptFrontendController();
1406  if ($tstamp > (int)$tsfe->register['SYS_LASTCHANGED']) {
1407  $tsfe->register['SYS_LASTCHANGED'] = $tstamp;
1408  }
1409  }
1410 
1420  public function ‪linkWrap($content, $wrap)
1421  {
1422  $wrapArr = explode('|', $wrap);
1423  if (preg_match('/\\{([0-9]*)\\}/', $wrapArr[0], $reg)) {
1424  $uid = $this->‪getTypoScriptFrontendController()->tmpl->rootLine[$reg[1]]['uid'] ?? null;
1425  if ($uid) {
1426  $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
1427  }
1428  }
1429  return trim($wrapArr[0] ?? '') . $content . trim($wrapArr[1] ?? '');
1430  }
1431 
1441  public function ‪getAltParam($conf, $longDesc = true)
1442  {
1443  $altText = isset($conf['altText.']) ? trim($this->‪stdWrap($conf['altText'], $conf['altText.'])) : trim($conf['altText']);
1444  $titleText = isset($conf['titleText.']) ? trim($this->‪stdWrap($conf['titleText'], $conf['titleText.'])) : trim($conf['titleText']);
1445  if (isset($conf['longdescURL.']) && $this->‪getTypoScriptFrontendController()->config['config']['doctype'] !== 'html5') {
1446  $longDescUrl = $this->‪typoLink_URL($conf['longdescURL.']);
1447  } else {
1448  $longDescUrl = trim($conf['longdescURL']);
1449  }
1450  $longDescUrl = strip_tags($longDescUrl);
1452  // "alt":
1453  $altParam = ' alt="' . htmlspecialchars($altText) . '"';
1454  // "title":
1455  $emptyTitleHandling = isset($conf['emptyTitleHandling.']) ? $this->‪stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.']) : $conf['emptyTitleHandling'];
1456  // Choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
1457  if ($titleText || $emptyTitleHandling === 'keepEmpty') {
1458  $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
1459  } elseif (!$titleText && $emptyTitleHandling === 'useAlt') {
1460  $altParam .= ' title="' . htmlspecialchars($altText) . '"';
1461  }
1462  // "longDesc" URL
1463  if ($longDesc && !empty($longDescUrl)) {
1464  $altParam .= ' longdesc="' . htmlspecialchars($longDescUrl) . '"';
1465  }
1466  return $altParam;
1467  }
1468 
1478  public function ‪getATagParams($conf, $addGlobal = 1)
1479  {
1480  $aTagParams = '';
1481  if ($conf['ATagParams.'] ?? false) {
1482  $aTagParams = ' ' . $this->‪stdWrap($conf['ATagParams'], $conf['ATagParams.']);
1483  } elseif ($conf['ATagParams'] ?? false) {
1484  $aTagParams = ' ' . $conf['ATagParams'];
1485  }
1486  if ($addGlobal) {
1487  $aTagParams = ' ' . trim($this->‪getTypoScriptFrontendController()->ATagParams . $aTagParams);
1488  }
1489  // Extend params
1490  $_params = [
1491  'conf' => &$conf,
1492  'aTagParams' => &$aTagParams
1493  ];
1494  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'] ?? [] as $className) {
1495  $processor = GeneralUtility::makeInstance($className);
1496  $aTagParams = $processor->process($_params, $this);
1497  }
1498 
1499  $aTagParams = trim($aTagParams);
1500  if (!empty($aTagParams)) {
1501  $aTagParams = ' ' . $aTagParams;
1502  }
1503 
1504  return $aTagParams;
1505  }
1506 
1515  public function ‪extLinkATagParams($URL, $TYPE)
1516  {
1517  $out = '';
1518  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler'])) {
1519  $extLinkATagParamsHandler = GeneralUtility::makeInstance(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']);
1520  if (method_exists($extLinkATagParamsHandler, 'main')) {
1521  $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
1522  }
1523  }
1524  return trim($out) ? ' ' . trim($out) : '';
1525  }
1526 
1527  /***********************************************
1528  *
1529  * HTML template processing functions
1530  *
1531  ***********************************************/
1532 
1538  public function ‪setCurrentFile($fileObject)
1539  {
1540  $this->currentFile = $fileObject;
1541  }
1548  public function ‪getCurrentFile()
1549  {
1550  return ‪$this->currentFile;
1551  }
1552 
1553  /***********************************************
1554  *
1555  * "stdWrap" + sub functions
1556  *
1557  ***********************************************/
1569  public function ‪stdWrap($content = '', $conf = [])
1570  {
1571  $content = (string)$content;
1572  // If there is any hook object, activate all of the process and override functions.
1573  // The hook interface ContentObjectStdWrapHookInterface takes care that all 4 methods exist.
1574  if ($this->stdWrapHookObjects) {
1575  $conf['stdWrapPreProcess'] = 1;
1576  $conf['stdWrapOverride'] = 1;
1577  $conf['stdWrapProcess'] = 1;
1578  $conf['stdWrapPostProcess'] = 1;
1579  }
1580 
1581  if (!is_array($conf) || !$conf) {
1582  return $content;
1583  }
1584 
1585  // Cache handling
1586  if (isset($conf['cache.']) && is_array($conf['cache.'])) {
1587  $conf['cache.']['key'] = $this->‪stdWrap($conf['cache.']['key'], $conf['cache.']['key.']);
1588  $conf['cache.']['tags'] = $this->‪stdWrap($conf['cache.']['tags'], $conf['cache.']['tags.']);
1589  $conf['cache.']['lifetime'] = $this->‪stdWrap($conf['cache.']['lifetime'], $conf['cache.']['lifetime.']);
1590  $conf['cacheRead'] = 1;
1591  $conf['cacheStore'] = 1;
1592  }
1593  // The configuration is sorted and filtered by intersection with the defined stdWrapOrder.
1594  $sortedConf = array_keys(array_intersect_key($this->stdWrapOrder, $conf));
1595  // Functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
1596  $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
1597  // Additional Array to check whether a function has already been executed
1598  $isExecuted = [];
1599  // Additional switch to make sure 'required', 'if' and 'fieldRequired'
1600  // will still stop rendering immediately in case they return FALSE
1601  $this->stdWrapRecursionLevel++;
1602  $this->stopRendering[‪$this->stdWrapRecursionLevel] = false;
1603  // execute each function in the predefined order
1604  foreach ($sortedConf as $stdWrapName) {
1605  // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
1606  if ((!isset($isExecuted[$stdWrapName]) || !$isExecuted[$stdWrapName]) && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
1607  $functionName = rtrim($stdWrapName, '.');
1608  $functionProperties = $functionName . '.';
1609  $functionType = $this->stdWrapOrder[$functionName] ?? null;
1610  // If there is any code on the next level, check if it contains "official" stdWrap functions
1611  // if yes, execute them first - will make each function stdWrap aware
1612  // so additional stdWrap calls within the functions can be removed, since the result will be the same
1613  if (!empty($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
1614  if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
1615  // Check if there's already content available before processing
1616  // any ifEmpty or ifBlank stdWrap properties
1617  if (($functionName === 'ifBlank' && $content !== '') ||
1618  ($functionName === 'ifEmpty' && trim($content) !== '')) {
1619  continue;
1620  }
1621 
1622  $conf[$functionName] = $this->‪stdWrap($conf[$functionName] ?? '', $conf[$functionProperties] ?? []);
1623  }
1624  }
1625  // Check if key is still containing something, since it might have been changed by next level stdWrap before
1626  if ((isset($conf[$functionName]) || $conf[$functionProperties])
1627  && ($functionType !== 'boolean' || $conf[$functionName])
1628  ) {
1629  // Get just that part of $conf that is needed for the particular function
1630  $singleConf = [
1631  $functionName => $conf[$functionName] ?? null,
1632  $functionProperties => $conf[$functionProperties] ?? null
1633  ];
1634  // Hand over the whole $conf array to the stdWrapHookObjects
1635  if ($functionType === 'hook') {
1636  $singleConf = $conf;
1637  }
1638  // Add both keys - with and without the dot - to the set of executed functions
1639  $isExecuted[$functionName] = true;
1640  $isExecuted[$functionProperties] = true;
1641  // Call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
1642  $functionName = 'stdWrap_' . $functionName;
1643  $content = $this->{$functionName}($content, $singleConf);
1644  } elseif ($functionType === 'boolean' && !$conf[$functionName]) {
1645  $isExecuted[$functionName] = true;
1646  $isExecuted[$functionProperties] = true;
1647  }
1648  }
1649  }
1650  unset($this->stopRendering[$this->stdWrapRecursionLevel]);
1651  $this->stdWrapRecursionLevel--;
1652 
1653  return $content;
1654  }
1655 
1664  public function ‪stdWrapValue($key, array $config, $defaultValue = '')
1665  {
1666  if (isset($config[$key])) {
1667  if (!isset($config[$key . '.'])) {
1668  return $config[$key];
1669  }
1670  } elseif (isset($config[$key . '.'])) {
1671  $config[$key] = '';
1672  } else {
1673  return $defaultValue;
1674  }
1675  $stdWrapped = $this->‪stdWrap($config[$key], $config[$key . '.']);
1676  return $stdWrapped ?: $defaultValue;
1677  }
1678 
1688  public function ‪stdWrap_stdWrapPreProcess($content = '', $conf = [])
1689  {
1690  foreach ($this->stdWrapHookObjects as $hookObject) {
1692  $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
1693  }
1694  return $content;
1695  }
1696 
1704  public function ‪stdWrap_cacheRead($content = '', $conf = [])
1705  {
1706  if (!isset($conf['cache.'])) {
1707  return $content;
1708  }
1709  $result = $this->‪getFromCache($conf['cache.']);
1710  return $result === false ? $content : $result;
1711  }
1720  public function ‪stdWrap_addPageCacheTags($content = '', $conf = [])
1721  {
1722  $tags = isset($conf['addPageCacheTags.'])
1723  ? $this->‪stdWrap($conf['addPageCacheTags'], $conf['addPageCacheTags.'])
1724  : $conf['addPageCacheTags'];
1725  if (!empty($tags)) {
1726  $cacheTags = GeneralUtility::trimExplode(',', $tags, true);
1728  }
1729  return $content;
1730  }
1731 
1739  public function ‪stdWrap_setContentToCurrent($content = '')
1740  {
1741  $this->data[‪$this->currentValKey] = $content;
1742  return $content;
1743  }
1744 
1753  public function ‪stdWrap_setCurrent($content = '', $conf = [])
1754  {
1755  $this->data[‪$this->currentValKey] = $conf['setCurrent'] ?? null;
1756  return $content;
1757  }
1758 
1767  public function ‪stdWrap_lang($content = '', $conf = [])
1768  {
1769  $request = ‪$GLOBALS['TYPO3_REQUEST'] ?? null;
1770  $siteLanguage = $request ? $request->getAttribute('language') : null;
1771  if ($siteLanguage instanceof SiteLanguage) {
1772  $currentLanguageCode = $siteLanguage->getTypo3Language();
1773  } else {
1774  $tsfe = $this->‪getTypoScriptFrontendController();
1775  $currentLanguageCode = $tsfe->config['config']['language'] ?? null;
1776  }
1777  if ($currentLanguageCode && isset($conf['lang.'][$currentLanguageCode])) {
1778  $content = $conf['lang.'][$currentLanguageCode];
1779  }
1780  return $content;
1781  }
1782 
1791  public function ‪stdWrap_data($content = '', $conf = [])
1792  {
1793  $content = $this->‪getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
1794  // This must be unset directly after
1795  $this->alternativeData = '';
1796  return $content;
1797  }
1798 
1807  public function ‪stdWrap_field($content = '', $conf = [])
1808  {
1809  return $this->‪getFieldVal($conf['field']);
1810  }
1811 
1821  public function ‪stdWrap_current($content = '', $conf = [])
1822  {
1823  return $this->data[‪$this->currentValKey];
1824  }
1825 
1835  public function ‪stdWrap_cObject($content = '', $conf = [])
1836  {
1837  return $this->‪cObjGetSingle($conf['cObject'] ?? '', $conf['cObject.'] ?? [], '/stdWrap/.cObject');
1838  }
1839 
1849  public function ‪stdWrap_numRows($content = '', $conf = [])
1850  {
1851  return $this->‪numRows($conf['numRows.']);
1852  }
1853 
1863  public function ‪stdWrap_filelist($content = '', $conf = [])
1864  {
1865  return $this->‪filelist($conf['filelist'], true);
1866  }
1867 
1876  public function ‪stdWrap_preUserFunc($content = '', $conf = [])
1877  {
1878  return $this->‪callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
1879  }
1890  public function ‪stdWrap_stdWrapOverride($content = '', $conf = [])
1891  {
1892  foreach ($this->stdWrapHookObjects as $hookObject) {
1894  $content = $hookObject->stdWrapOverride($content, $conf, $this);
1895  }
1896  return $content;
1897  }
1898 
1907  public function ‪stdWrap_override($content = '', $conf = [])
1908  {
1909  if (trim($conf['override'] ?? false)) {
1910  $content = $conf['override'];
1911  }
1912  return $content;
1913  }
1914 
1924  public function ‪stdWrap_preIfEmptyListNum($content = '', $conf = [])
1925  {
1926  return $this->‪listNum($content, $conf['preIfEmptyListNum'] ?? null, $conf['preIfEmptyListNum.']['splitChar'] ?? null);
1927  }
1928 
1937  public function ‪stdWrap_ifNull($content = '', $conf = [])
1938  {
1939  return $content ?? $conf['ifNull'];
1940  }
1951  public function ‪stdWrap_ifEmpty($content = '', $conf = [])
1952  {
1953  if (!trim($content)) {
1954  $content = $conf['ifEmpty'];
1955  }
1956  return $content;
1957  }
1958 
1968  public function ‪stdWrap_ifBlank($content = '', $conf = [])
1969  {
1970  if (trim($content) === '') {
1971  $content = $conf['ifBlank'];
1972  }
1973  return $content;
1974  }
1975 
1986  public function ‪stdWrap_listNum($content = '', $conf = [])
1987  {
1988  return $this->‪listNum($content, $conf['listNum'] ?? null, $conf['listNum.']['splitChar'] ?? null);
1989  }
1990 
1998  public function ‪stdWrap_trim($content = '')
1999  {
2000  return trim($content);
2001  }
2002 
2011  public function ‪stdWrap_strPad($content = '', $conf = [])
2012  {
2013  // Must specify a length in conf for this to make sense
2014  $length = 0;
2015  // Padding with space is PHP-default
2016  $padWith = ' ';
2017  // Padding on the right side is PHP-default
2018  $padType = STR_PAD_RIGHT;
2019  if (!empty($conf['strPad.']['length'])) {
2020  $length = isset($conf['strPad.']['length.']) ? $this->‪stdWrap($conf['strPad.']['length'], $conf['strPad.']['length.']) : $conf['strPad.']['length'];
2021  $length = (int)$length;
2022  }
2023  if (isset($conf['strPad.']['padWith']) && (string)$conf['strPad.']['padWith'] !== '') {
2024  $padWith = isset($conf['strPad.']['padWith.']) ? $this->‪stdWrap($conf['strPad.']['padWith'], $conf['strPad.']['padWith.']) : $conf['strPad.']['padWith'];
2025  }
2026  if (!empty($conf['strPad.']['type'])) {
2027  $type = isset($conf['strPad.']['type.']) ? $this->‪stdWrap($conf['strPad.']['type'], $conf['strPad.']['type.']) : $conf['strPad.']['type'];
2028  if (strtolower($type) === 'left') {
2029  $padType = STR_PAD_LEFT;
2030  } elseif (strtolower($type) === 'both') {
2031  $padType = STR_PAD_BOTH;
2032  }
2033  }
2034  return str_pad($content, $length, $padWith, $padType);
2035  }
2036 
2048  public function ‪stdWrap_stdWrap($content = '', $conf = [])
2049  {
2050  return $this->‪stdWrap($content, $conf['stdWrap.']);
2051  }
2062  public function ‪stdWrap_stdWrapProcess($content = '', $conf = [])
2063  {
2064  foreach ($this->stdWrapHookObjects as $hookObject) {
2066  $content = $hookObject->stdWrapProcess($content, $conf, $this);
2067  }
2068  return $content;
2069  }
2079  public function ‪stdWrap_required($content = '')
2080  {
2081  if ((string)$content === '') {
2082  $content = '';
2083  $this->stopRendering[‪$this->stdWrapRecursionLevel] = true;
2084  }
2085  return $content;
2086  }
2087 
2097  public function ‪stdWrap_if($content = '', $conf = [])
2098  {
2099  if (empty($conf['if.']) || $this->‪checkIf($conf['if.'])) {
2100  return $content;
2101  }
2102  $this->stopRendering[‪$this->stdWrapRecursionLevel] = true;
2103  return '';
2104  }
2105 
2115  public function ‪stdWrap_fieldRequired($content = '', $conf = [])
2116  {
2117  if (!trim($this->data[$conf['fieldRequired'] ?? null] ?? '')) {
2118  $content = '';
2119  $this->stopRendering[‪$this->stdWrapRecursionLevel] = true;
2120  }
2121  return $content;
2122  }
2123 
2134  public function ‪stdWrap_csConv($content = '', $conf = [])
2135  {
2136  if (!empty($conf['csConv'])) {
2137  ‪$output = mb_convert_encoding($content, 'utf-8', trim(strtolower($conf['csConv'])));
2138  return ‪$output !== false && ‪$output !== '' ? ‪$output : $content;
2139  }
2140  return $content;
2141  }
2142 
2152  public function ‪stdWrap_parseFunc($content = '', $conf = [])
2153  {
2154  return $this->‪parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
2155  }
2166  public function ‪stdWrap_HTMLparser($content = '', $conf = [])
2167  {
2168  if (isset($conf['HTMLparser.']) && is_array($conf['HTMLparser.'])) {
2169  $content = $this->‪HTMLparser_TSbridge($content, $conf['HTMLparser.']);
2170  }
2171  return $content;
2172  }
2173 
2183  public function ‪stdWrap_split($content = '', $conf = [])
2184  {
2185  return $this->‪splitObj($content, $conf['split.']);
2186  }
2187 
2196  public function ‪stdWrap_replacement($content = '', $conf = [])
2197  {
2198  return $this->‪replacement($content, $conf['replacement.']);
2199  }
2200 
2210  public function ‪stdWrap_prioriCalc($content = '', $conf = [])
2211  {
2212  $content = ‪MathUtility::calculateWithParentheses($content);
2213  if (!empty($conf['prioriCalc']) && $conf['prioriCalc'] === 'intval') {
2214  $content = (int)$content;
2215  }
2216  return $content;
2217  }
2218 
2230  public function ‪stdWrap_char($content = '', $conf = [])
2231  {
2232  return chr((int)$conf['char']);
2233  }
2234 
2242  public function ‪stdWrap_intval($content = '')
2243  {
2244  return (int)$content;
2245  }
2255  public function ‪stdWrap_hash($content = '', array $conf = [])
2256  {
2257  $algorithm = isset($conf['hash.']) ? $this->‪stdWrap($conf['hash'], $conf['hash.']) : $conf['hash'];
2258  if (function_exists('hash') && in_array($algorithm, hash_algos())) {
2259  return hash($algorithm, $content);
2260  }
2261  // Non-existing hashing algorithm
2262  return '';
2263  }
2264 
2273  public function ‪stdWrap_round($content = '', $conf = [])
2274  {
2275  return $this->‪round($content, $conf['round.']);
2276  }
2277 
2286  public function ‪stdWrap_numberFormat($content = '', $conf = [])
2287  {
2288  return $this->‪numberFormat($content, $conf['numberFormat.'] ?? []);
2289  }
2290 
2298  public function ‪stdWrap_expandList($content = '')
2299  {
2300  return GeneralUtility::expandList($content);
2301  }
2312  public function ‪stdWrap_date($content = '', $conf = [])
2313  {
2314  // Check for zero length string to mimic default case of date/gmdate.
2315  $content = (string)$content === '' ? ‪$GLOBALS['EXEC_TIME'] : (int)$content;
2316  $content = !empty($conf['date.']['GMT']) ? gmdate($conf['date'] ?? null, $content) : date($conf['date'] ?? null, $content);
2317  return $content;
2318  }
2319 
2329  public function ‪stdWrap_strftime($content = '', $conf = [])
2330  {
2331  // Check for zero length string to mimic default case of strtime/gmstrftime
2332  $content = (string)$content === '' ? ‪$GLOBALS['EXEC_TIME'] : (int)$content;
2333  $content = (isset($conf['strftime.']['GMT']) && $conf['strftime.']['GMT'])
2334  ? gmstrftime($conf['strftime'] ?? null, $content)
2335  : strftime($conf['strftime'] ?? null, $content);
2336  if (!empty($conf['strftime.']['charset'])) {
2337  ‪$output = mb_convert_encoding($content, 'utf-8', trim(strtolower($conf['strftime.']['charset'])));
2338  return ‪$output ?: $content;
2339  }
2340  return $content;
2341  }
2342 
2351  public function ‪stdWrap_strtotime($content = '', $conf = [])
2352  {
2353  if ($conf['strtotime'] !== '1') {
2354  $content .= ' ' . $conf['strtotime'];
2355  }
2356  return strtotime($content, ‪$GLOBALS['EXEC_TIME']);
2357  }
2358 
2367  public function ‪stdWrap_age($content = '', $conf = [])
2368  {
2369  return $this->‪calcAge((int)(‪$GLOBALS['EXEC_TIME'] ?? 0) - (int)$content, $conf['age'] ?? null);
2370  }
2371 
2381  public function ‪stdWrap_case($content = '', $conf = [])
2382  {
2383  return $this->‪HTMLcaseshift($content, $conf['case']);
2384  }
2385 
2394  public function ‪stdWrap_bytes($content = '', $conf = [])
2395  {
2396  return GeneralUtility::formatSize($content, $conf['bytes.']['labels'], $conf['bytes.']['base']);
2397  }
2398 
2407  public function ‪stdWrap_substring($content = '', $conf = [])
2408  {
2409  return $this->‪substring($content, $conf['substring']);
2410  }
2411 
2420  public function ‪stdWrap_cropHTML($content = '', $conf = [])
2421  {
2422  return $this->‪cropHTML($content, $conf['cropHTML'] ?? '');
2423  }
2424 
2432  public function ‪stdWrap_stripHtml($content = '')
2433  {
2434  return strip_tags($content);
2435  }
2436 
2445  public function ‪stdWrap_crop($content = '', $conf = [])
2446  {
2447  return $this->‪crop($content, $conf['crop']);
2448  }
2449 
2457  public function ‪stdWrap_rawUrlEncode($content = '')
2458  {
2459  return rawurlencode($content);
2460  }
2471  public function ‪stdWrap_htmlSpecialChars($content = '', $conf = [])
2472  {
2473  if (!empty($conf['htmlSpecialChars.']['preserveEntities'])) {
2474  $content = htmlspecialchars($content, ENT_COMPAT, 'UTF-8', false);
2475  } else {
2476  $content = htmlspecialchars($content);
2477  }
2478  return $content;
2479  }
2480 
2488  public function ‪stdWrap_encodeForJavaScriptValue($content = '')
2489  {
2490  return GeneralUtility::quoteJSvalue($content);
2491  }
2492 
2501  public function ‪stdWrap_doubleBrTag($content = '', $conf = [])
2502  {
2503  return preg_replace('/\R{1,2}[\t\x20]*\R{1,2}/', $conf['doubleBrTag'] ?? null, $content);
2504  }
2505 
2514  public function ‪stdWrap_br($content = '')
2515  {
2516  return nl2br($content, !empty($this->‪getTypoScriptFrontendController()->xhtmlDoctype));
2517  }
2518 
2527  public function ‪stdWrap_brTag($content = '', $conf = [])
2528  {
2529  return str_replace(LF, $conf['brTag'] ?? null, $content);
2530  }
2531 
2541  public function ‪stdWrap_encapsLines($content = '', $conf = [])
2542  {
2543  return $this->‪encaps_lineSplit($content, $conf['encapsLines.']);
2544  }
2545 
2553  public function ‪stdWrap_keywords($content = '')
2554  {
2555  return $this->‪keywords($content);
2556  }
2557 
2567  public function ‪stdWrap_innerWrap($content = '', $conf = [])
2568  {
2569  return $this->‪wrap($content, $conf['innerWrap'] ?? null);
2570  }
2571 
2581  public function ‪stdWrap_innerWrap2($content = '', $conf = [])
2582  {
2583  return $this->‪wrap($content, $conf['innerWrap2'] ?? null);
2584  }
2585 
2595  public function ‪stdWrap_addParams($content = '', $conf = [])
2596  {
2597  return $this->‪addParams($content, $conf['addParams.'] ?? [], true);
2598  }
2599 
2610  public function ‪stdWrap_filelink($content = '', $conf = [])
2611  {
2612  return $this->‪filelink($content, $conf['filelink.'] ?? [], true);
2613  }
2614 
2623  public function ‪stdWrap_preCObject($content = '', $conf = [])
2624  {
2625  return $this->‪cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content;
2626  }
2627 
2636  public function ‪stdWrap_postCObject($content = '', $conf = [])
2637  {
2638  return $content . $this->‪cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject');
2639  }
2640 
2650  public function ‪stdWrap_wrapAlign($content = '', $conf = [])
2651  {
2652  $wrapAlign = trim($conf['wrapAlign'] ?? '');
2653  if ($wrapAlign) {
2654  $content = $this->‪wrap($content, '<div style="text-align:' . htmlspecialchars($wrapAlign) . ';">|</div>');
2655  }
2656  return $content;
2657  }
2658 
2669  public function ‪stdWrap_typolink($content = '', $conf = [])
2670  {
2671  return $this->‪typoLink($content, $conf['typolink.']);
2672  }
2673 
2686  public function ‪stdWrap_wrap($content = '', $conf = [])
2687  {
2688  return $this->‪wrap(
2689  $content,
2690  $conf['wrap'] ?? null,
2691  $conf['wrap.']['splitChar'] ?? '|'
2692  );
2693  }
2694 
2704  public function ‪stdWrap_noTrimWrap($content = '', $conf = [])
2705  {
2706  $splitChar = isset($conf['noTrimWrap.']['splitChar.'])
2707  ? $this->‪stdWrap($conf['noTrimWrap.']['splitChar'] ?? '', $conf['noTrimWrap.']['splitChar.'])
2708  : $conf['noTrimWrap.']['splitChar'] ?? '';
2709  if ($splitChar === null || $splitChar === '') {
2710  $splitChar = '|';
2711  }
2712  $content = $this->‪noTrimWrap(
2713  $content,
2714  $conf['noTrimWrap'],
2715  $splitChar
2716  );
2717  return $content;
2718  }
2719 
2729  public function ‪stdWrap_wrap2($content = '', $conf = [])
2730  {
2731  return $this->‪wrap(
2732  $content,
2733  $conf['wrap2'] ?? null,
2734  $conf['wrap2.']['splitChar'] ?? '|'
2735  );
2736  }
2737 
2747  public function ‪stdWrap_dataWrap($content = '', $conf = [])
2748  {
2749  return $this->‪dataWrap($content, $conf['dataWrap']);
2750  }
2751 
2760  public function ‪stdWrap_prepend($content = '', $conf = [])
2761  {
2762  return $this->‪cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content;
2763  }
2764 
2773  public function ‪stdWrap_append($content = '', $conf = [])
2774  {
2775  return $content . $this->‪cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append');
2776  }
2787  public function ‪stdWrap_wrap3($content = '', $conf = [])
2788  {
2789  return $this->‪wrap(
2790  $content,
2791  $conf['wrap3'] ?? null,
2792  $conf['wrap3.']['splitChar'] ?? '|'
2793  );
2794  }
2795 
2804  public function ‪stdWrap_orderedStdWrap($content = '', $conf = [])
2805  {
2806  $sortedKeysArray = ‪ArrayUtility::filterAndSortByNumericKeys($conf['orderedStdWrap.'], true);
2807  foreach ($sortedKeysArray as $key) {
2808  $content = $this->‪stdWrap($content, $conf['orderedStdWrap.'][$key . '.'] ?? null);
2809  }
2810  return $content;
2811  }
2812 
2821  public function ‪stdWrap_outerWrap($content = '', $conf = [])
2822  {
2823  return $this->‪wrap($content, $conf['outerWrap'] ?? null);
2824  }
2825 
2833  public function ‪stdWrap_insertData($content = '')
2834  {
2835  return $this->‪insertData($content);
2836  }
2837 
2846  public function ‪stdWrap_postUserFunc($content = '', $conf = [])
2847  {
2848  return $this->‪callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content);
2849  }
2850 
2860  public function ‪stdWrap_postUserFuncInt($content = '', $conf = [])
2861  {
2862  $substKey = 'INT_SCRIPT.' . $this->‪getTypoScriptFrontendController()->‪uniqueHash();
2863  $this->‪getTypoScriptFrontendController()->config['INTincScript'][$substKey] = [
2864  'content' => $content,
2865  'postUserFunc' => $conf['postUserFuncInt'],
2866  'conf' => $conf['postUserFuncInt.'],
2867  'type' => 'POSTUSERFUNC',
2868  'cObj' => serialize($this)
2869  ];
2870  $content = '<!--' . $substKey . '-->';
2871  return $content;
2872  }
2873 
2882  public function ‪stdWrap_prefixComment($content = '', $conf = [])
2883  {
2884  if (
2885  (!isset($this->‪getTypoScriptFrontendController()->config['config']['disablePrefixComment']) || !$this->‪getTypoScriptFrontendController()->config['config']['disablePrefixComment'])
2886  && !empty($conf['prefixComment'])
2887  ) {
2888  $content = $this->‪prefixComment($conf['prefixComment'], [], $content);
2889  }
2890  return $content;
2891  }
2892 
2901  public function ‪stdWrap_editIcons($content = '', $conf = [])
2902  {
2903  if ($this->‪getTypoScriptFrontendController()->isBackendUserLoggedIn() && $conf['editIcons']) {
2904  if (!isset($conf['editIcons.']) || !is_array($conf['editIcons.'])) {
2905  $conf['editIcons.'] = [];
2906  }
2907  $content = $this->‪editIcons($content, $conf['editIcons'], $conf['editIcons.']);
2908  }
2909  return $content;
2910  }
2911 
2920  public function ‪stdWrap_editPanel($content = '', $conf = [])
2921  {
2922  if ($this->‪getTypoScriptFrontendController()->isBackendUserLoggedIn()) {
2923  $content = $this->‪editPanel($content, $conf['editPanel.']);
2924  }
2925  return $content;
2926  }
2927 
2928  public function ‪stdWrap_htmlSanitize(string $content = '', array $conf = []): string
2929  {
2930  $build = $conf['build'] ?? 'default';
2931  if (class_exists($build) && is_a($build, BuilderInterface::class, true)) {
2932  $builder = GeneralUtility::makeInstance($build);
2933  } else {
2934  $factory = GeneralUtility::makeInstance(SanitizerBuilderFactory::class);
2935  $builder = $factory->build($build);
2936  }
2937  $sanitizer = $builder->build();
2938  $initiator = $this->‪shallDebug()
2939  ? GeneralUtility::makeInstance(SanitizerInitiator::class, ‪DebugUtility::debugTrail())
2940  : null;
2941  return $sanitizer->sanitize($content, $initiator);
2942  }
2943 
2951  public function ‪stdWrap_cacheStore($content = '', $conf = [])
2952  {
2953  if (!isset($conf['cache.'])) {
2954  return $content;
2955  }
2956  $key = $this->‪calculateCacheKey($conf['cache.']);
2957  if (empty($key)) {
2958  return $content;
2959  }
2961  $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
2962  $tags = $this->‪calculateCacheTags($conf['cache.']);
2963  $lifetime = $this->‪calculateCacheLifetime($conf['cache.']);
2964  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'] ?? [] as $_funcRef) {
2965  $params = [
2966  'key' => $key,
2967  'content' => $content,
2968  'lifetime' => $lifetime,
2969  'tags' => $tags
2970  ];
2971  GeneralUtility::callUserFunction($_funcRef, $params, $this);
2972  }
2973  $cacheFrontend->set($key, $content, $tags, $lifetime);
2974  return $content;
2975  }
2976 
2986  public function ‪stdWrap_stdWrapPostProcess($content = '', $conf = [])
2987  {
2988  foreach ($this->stdWrapHookObjects as $hookObject) {
2990  $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
2991  }
2992  return $content;
2993  }
2994 
3002  public function ‪stdWrap_debug($content = '')
3003  {
3004  return '<pre>' . htmlspecialchars($content) . '</pre>';
3005  }
3006 
3015  public function ‪stdWrap_debugFunc($content = '', $conf = [])
3016  {
3017  ‪debug((int)$conf['debugFunc'] === 2 ? [$content] : $content);
3018  return $content;
3019  }
3020 
3028  public function ‪stdWrap_debugData($content = '')
3029  {
3030  ‪debug($this->data, '$cObj->data:');
3031  if (is_array($this->alternativeData)) {
3032  ‪debug($this->alternativeData, '$this->alternativeData');
3033  }
3034  return $content;
3035  }
3036 
3046  public function ‪numRows($conf)
3047  {
3048  $conf['select.']['selectFields'] = 'count(*)';
3049  $statement = $this->‪exec_getQuery($conf['table'], $conf['select.']);
3050 
3051  return (int)$statement->fetchColumn(0);
3052  }
3053 
3062  public function ‪listNum($content, $listNum, $char)
3063  {
3064  $char = $char ?: ',';
3066  $char = chr($char);
3067  }
3068  $temp = explode($char, $content);
3069  $last = '' . (count($temp) - 1);
3070  // Take a random item if requested
3071  if ($listNum === 'rand') {
3072  $listNum = rand(0, count($temp) - 1);
3073  }
3074  $index = $this->‪calc(str_ireplace('last', $last, $listNum));
3075  return $temp[$index];
3076  }
3077 
3086  public function ‪checkIf($conf)
3087  {
3088  if (!is_array($conf)) {
3089  return true;
3090  }
3091  if (isset($conf['directReturn'])) {
3092  return (bool)$conf['directReturn'];
3093  }
3094  $flag = true;
3095  if (isset($conf['isNull.'])) {
3096  $isNull = $this->‪stdWrap('', $conf['isNull.']);
3097  if ($isNull !== null) {
3098  $flag = false;
3099  }
3100  }
3101  if (isset($conf['isTrue']) || isset($conf['isTrue.'])) {
3102  $isTrue = isset($conf['isTrue.']) ? trim($this->‪stdWrap($conf['isTrue'], $conf['isTrue.'])) : trim($conf['isTrue']);
3103  if (!$isTrue) {
3104  $flag = false;
3105  }
3106  }
3107  if (isset($conf['isFalse']) || isset($conf['isFalse.'])) {
3108  $isFalse = isset($conf['isFalse.']) ? trim($this->‪stdWrap($conf['isFalse'], $conf['isFalse.'])) : trim($conf['isFalse']);
3109  if ($isFalse) {
3110  $flag = false;
3111  }
3112  }
3113  if (isset($conf['isPositive']) || isset($conf['isPositive.'])) {
3114  $number = isset($conf['isPositive.']) ? $this->‪calc($this->‪stdWrap($conf['isPositive'], $conf['isPositive.'])) : $this->‪calc($conf['isPositive']);
3115  if ($number < 1) {
3116  $flag = false;
3117  }
3118  }
3119  if ($flag) {
3120  $value = isset($conf['value.'])
3121  ? trim($this->‪stdWrap($conf['value'] ?? '', $conf['value.']))
3122  : trim($conf['value'] ?? '');
3123  if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) {
3124  $number = isset($conf['isGreaterThan.']) ? trim($this->‪stdWrap($conf['isGreaterThan'], $conf['isGreaterThan.'])) : trim($conf['isGreaterThan']);
3125  if ($number <= $value) {
3126  $flag = false;
3127  }
3128  }
3129  if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) {
3130  $number = isset($conf['isLessThan.']) ? trim($this->‪stdWrap($conf['isLessThan'], $conf['isLessThan.'])) : trim($conf['isLessThan']);
3131  if ($number >= $value) {
3132  $flag = false;
3133  }
3134  }
3135  if (isset($conf['equals']) || isset($conf['equals.'])) {
3136  $number = isset($conf['equals.']) ? trim($this->‪stdWrap($conf['equals'], $conf['equals.'])) : trim($conf['equals']);
3137  if ($number != $value) {
3138  $flag = false;
3139  }
3140  }
3141  if (isset($conf['isInList']) || isset($conf['isInList.'])) {
3142  $number = isset($conf['isInList.']) ? trim($this->‪stdWrap($conf['isInList'], $conf['isInList.'])) : trim($conf['isInList']);
3143  if (!GeneralUtility::inList($value, $number)) {
3144  $flag = false;
3145  }
3146  }
3147  }
3148  if ($conf['negate'] ?? false) {
3149  $flag = !$flag;
3150  }
3151  return $flag;
3152  }
3153 
3165  public function ‪filelist(‪$data, bool $isCoreCall = false)
3166  {
3167  if (!$isCoreCall) {
3168  trigger_error('ContentObjectRenderer->filelist() will be removed in TYPO3 v10.0. Use cObject FILES instead.', E_USER_DEPRECATED);
3169  }
3170  ‪$data = trim(‪$data);
3171  if (‪$data === '') {
3172  return '';
3173  }
3174  list($possiblePath, $ext_list, $sorting, $reverse, $useFullPath) = GeneralUtility::trimExplode('|', ‪$data);
3175  // read directory:
3176  // MUST exist!
3177  $path = '';
3178  // proceeds if no '//', '..' or '\' is in the $theFile
3179  if (GeneralUtility::validPathStr($possiblePath)) {
3180  // Removes all dots, slashes and spaces after a path.
3181  $possiblePath = preg_replace('/[\\/\\. ]*$/', '', $possiblePath);
3182  if (!GeneralUtility::isAbsPath($possiblePath) && @is_dir($possiblePath)) {
3183  // Now check if it matches one of the FAL storages
3184  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
3185  $storages = $storageRepository->findAll();
3186  foreach ($storages as $storage) {
3187  if ($storage->getDriverType() === 'Local' && $storage->isPublic() && $storage->isOnline()) {
3188  $folder = $storage->getPublicUrl($storage->getRootLevelFolder(), true);
3189  if (GeneralUtility::isFirstPartOfStr($possiblePath . '/', $folder)) {
3190  $path = $possiblePath;
3191  break;
3192  }
3193  }
3194  }
3195  }
3196  }
3197  if (!$path) {
3198  return '';
3199  }
3200  $items = [
3201  'files' => [],
3202  'sorting' => []
3203  ];
3204  $ext_list = strtolower(GeneralUtility::uniqueList($ext_list));
3205  // Read dir:
3206  $d = @dir($path);
3207  if (is_object($d)) {
3208  $count = 0;
3209  while ($entry = $d->read()) {
3210  if ($entry !== '.' && $entry !== '..') {
3211  // Because of odd PHP-error where <br />-tag is sometimes placed after a filename!!
3212  $wholePath = $path . '/' . $entry;
3213  if (file_exists($wholePath) && filetype($wholePath) === 'file') {
3214  $info = GeneralUtility::split_fileref($wholePath);
3215  if (!$ext_list || GeneralUtility::inList($ext_list, $info['fileext'])) {
3216  $items['files'][] = $info['file'];
3217  switch ($sorting) {
3218  case 'name':
3219  $items['sorting'][] = strtolower($info['file']);
3220  break;
3221  case 'size':
3222  $items['sorting'][] = filesize($wholePath);
3223  break;
3224  case 'ext':
3225  $items['sorting'][] = $info['fileext'];
3226  break;
3227  case 'date':
3228  $items['sorting'][] = filectime($wholePath);
3229  break;
3230  case 'mdate':
3231  $items['sorting'][] = filemtime($wholePath);
3232  break;
3233  default:
3234  $items['sorting'][] = $count;
3235  }
3236  $count++;
3237  }
3238  }
3239  }
3240  }
3241  $d->close();
3242  }
3243  // Sort if required
3244  if (!empty($items['sorting'])) {
3245  if (strtolower($reverse) !== 'r') {
3246  asort($items['sorting']);
3247  } else {
3248  arsort($items['sorting']);
3249  }
3250  }
3251  if (!empty($items['files'])) {
3252  // Make list
3253  reset($items['sorting']);
3254  $list_arr = [];
3255  foreach ($items['sorting'] as $key => $v) {
3256  $list_arr[] = $useFullPath ? $path . '/' . $items['files'][$key] : $items['files'][$key];
3257  }
3258  return implode(',', $list_arr);
3259  }
3260  return '';
3261  }
3262 
3273  public function ‪HTMLparser_TSbridge($theValue, $conf)
3274  {
3275  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
3276  $htmlParserCfg = $htmlParser->HTMLparserConfig($conf);
3277  return $htmlParser->HTMLcleaner($theValue, $htmlParserCfg[0], $htmlParserCfg[1], $htmlParserCfg[2], $htmlParserCfg[3]);
3278  }
3288  public function ‪dataWrap($content, $wrap)
3289  {
3290  return $this->‪wrap($content, $this->‪insertData($wrap));
3291  }
3292 
3306  public function ‪insertData($str)
3307  {
3308  $inside = 0;
3309  $newVal = '';
3310  $pointer = 0;
3311  $totalLen = strlen($str);
3312  do {
3313  if (!$inside) {
3314  $len = strcspn(substr($str, $pointer), '{');
3315  $newVal .= substr($str, $pointer, $len);
3316  $inside = true;
3317  if (substr($str, $pointer + $len + 1, 1) === '#') {
3318  $len2 = strcspn(substr($str, $pointer + $len), '}');
3319  $newVal .= substr($str, $pointer + $len, $len2);
3320  $len += $len2;
3321  $inside = false;
3322  }
3323  } else {
3324  $len = strcspn(substr($str, $pointer), '}') + 1;
3325  $newVal .= $this->‪getData(substr($str, $pointer + 1, $len - 2), $this->data);
3326  $inside = false;
3327  }
3328  $pointer += $len;
3329  } while ($pointer < $totalLen);
3330  return $newVal;
3331  }
3332 
3343  public function ‪prefixComment($str, $conf, $content)
3344  {
3345  if (empty($str)) {
3346  return $content;
3347  }
3348  $parts = explode('|', $str);
3349  $indent = (int)$parts[0];
3350  $comment = htmlspecialchars($this->‪insertData($parts[1]));
3351  ‪$output = LF
3352  . str_pad('', $indent, "\t") . '<!-- ' . $comment . ' [begin] -->' . LF
3353  . str_pad('', $indent + 1, "\t") . $content . LF
3354  . str_pad('', $indent, "\t") . '<!-- ' . $comment . ' [end] -->' . LF
3355  . str_pad('', $indent + 1, "\t");
3356  return ‪$output;
3357  }
3358 
3368  public function ‪substring($content, $options)
3369  {
3370  $options = GeneralUtility::intExplode(',', $options . ',');
3371  if ($options[1]) {
3372  return mb_substr($content, $options[0], $options[1], 'utf-8');
3373  }
3374  return mb_substr($content, $options[0], null, 'utf-8');
3375  }
3376 
3386  public function ‪crop($content, $options)
3387  {
3388  $options = explode('|', $options);
3389  $chars = (int)$options[0];
3390  $afterstring = trim($options[1] ?? '');
3391  $crop2space = trim($options[2] ?? '');
3392  if ($chars) {
3393  if (mb_strlen($content, 'utf-8') > abs($chars)) {
3394  $truncatePosition = false;
3395  if ($chars < 0) {
3396  $content = mb_substr($content, $chars, null, 'utf-8');
3397  if ($crop2space) {
3398  $truncatePosition = strpos($content, ' ');
3399  }
3400  $content = $truncatePosition ? $afterstring . substr($content, $truncatePosition) : $afterstring . $content;
3401  } else {
3402  $content = mb_substr($content, 0, $chars, 'utf-8');
3403  if ($crop2space) {
3404  $truncatePosition = strrpos($content, ' ');
3405  }
3406  $content = $truncatePosition ? substr($content, 0, $truncatePosition) . $afterstring : $content . $afterstring;
3407  }
3408  }
3409  }
3410  return $content;
3411  }
3412 
3426  public function ‪cropHTML($content, $options)
3427  {
3428  $options = explode('|', $options);
3429  $chars = (int)$options[0];
3430  $absChars = abs($chars);
3431  $replacementForEllipsis = trim($options[1] ?? '');
3432  $crop2space = trim($options[2] ?? '') === '1';
3433  // Split $content into an array(even items in the array are outside the tags, odd numbers are tag-blocks).
3434  $tags = 'a|abbr|address|area|article|aside|audio|b|bdi|bdo|blockquote|body|br|button|caption|cite|code|col|colgroup|data|datalist|dd|del|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|h1|h2|h3|h4|h5|h6|header|hr|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|main|map|mark|meter|nav|object|ol|optgroup|option|output|p|param|pre|progress|q|rb|rp|rt|rtc|ruby|s|samp|section|select|small|source|span|strong|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|tr|track|u|ul|ut|var|video|wbr';
3435  $tagsRegEx = '
3436  (
3437  (?:
3438  <!--.*?--> # a comment
3439  |
3440  <canvas[^>]*>.*?</canvas> # a canvas tag
3441  |
3442  <script[^>]*>.*?</script> # a script tag
3443  |
3444  <noscript[^>]*>.*?</noscript> # a noscript tag
3445  |
3446  <template[^>]*>.*?</template> # a template tag
3447  )
3448  |
3449  </?(?:' . $tags . ')+ # opening tag (\'<tag\') or closing tag (\'</tag\')
3450  (?:
3451  (?:
3452  (?:
3453  \\s+\\w[\\w-]* # EITHER spaces, followed by attribute names
3454  (?:
3455  \\s*=?\\s* # equals
3456  (?>
3457  ".*?" # attribute values in double-quotes
3458  |
3459  \'.*?\' # attribute values in single-quotes
3460  |
3461  [^\'">\\s]+ # plain attribute values
3462  )
3463  )?
3464  )
3465  | # OR a single dash (for TYPO3 link tag)
3466  (?:
3467  \\s+-
3468  )
3469  )+\\s*
3470  | # OR only spaces
3471  \\s*
3472  )
3473  /?> # closing the tag with \'>\' or \'/>\'
3474  )';
3475  $splittedContent = preg_split('%' . $tagsRegEx . '%xs', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
3476  // Reverse array if we are cropping from right.
3477  if ($chars < 0) {
3478  $splittedContent = array_reverse($splittedContent);
3479  }
3480  // Crop the text (chars of tag-blocks are not counted).
3481  $strLen = 0;
3482  // This is the offset of the content item which was cropped.
3483  $croppedOffset = null;
3484  $countSplittedContent = count($splittedContent);
3485  for ($offset = 0; $offset < $countSplittedContent; $offset++) {
3486  if ($offset % 2 === 0) {
3487  $tempContent = $splittedContent[$offset];
3488  $thisStrLen = mb_strlen(html_entity_decode($tempContent, ENT_COMPAT, 'UTF-8'), 'utf-8');
3489  if ($strLen + $thisStrLen > $absChars) {
3490  $croppedOffset = $offset;
3491  $cropPosition = $absChars - $strLen;
3492  // The snippet "&[^&\s;]{2,8};" in the RegEx below represents entities.
3493  $patternMatchEntityAsSingleChar = '(&[^&\\s;]{2,8};|.)';
3494  $cropRegEx = $chars < 0 ? '#' . $patternMatchEntityAsSingleChar . '{0,' . ($cropPosition + 1) . '}$#uis' : '#^' . $patternMatchEntityAsSingleChar . '{0,' . ($cropPosition + 1) . '}#uis';
3495  if (preg_match($cropRegEx, $tempContent, $croppedMatch)) {
3496  $tempContentPlusOneCharacter = $croppedMatch[0];
3497  } else {
3498  $tempContentPlusOneCharacter = false;
3499  }
3500  $cropRegEx = $chars < 0 ? '#' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#uis' : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}#uis';
3501  if (preg_match($cropRegEx, $tempContent, $croppedMatch)) {
3502  $tempContent = $croppedMatch[0];
3503  if ($crop2space && $tempContentPlusOneCharacter !== false) {
3504  $cropRegEx = $chars < 0 ? '#(?<=\\s)' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#uis' : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}(?=\\s)#uis';
3505  if (preg_match($cropRegEx, $tempContentPlusOneCharacter, $croppedMatch)) {
3506  $tempContent = $croppedMatch[0];
3507  }
3508  }
3509  }
3510  $splittedContent[$offset] = $tempContent;
3511  break;
3512  }
3513  $strLen += $thisStrLen;
3514  }
3515  }
3516  // Close cropped tags.
3517  $closingTags = [];
3518  if ($croppedOffset !== null) {
3519  $openingTagRegEx = '#^<(\\w+)(?:\\s|>)#';
3520  $closingTagRegEx = '#^</(\\w+)(?:\\s|>)#';
3521  for ($offset = $croppedOffset - 1; $offset >= 0; $offset = $offset - 2) {
3522  if (substr($splittedContent[$offset], -2) === '/>') {
3523  // Ignore empty element tags (e.g. <br />).
3524  continue;
3525  }
3526  preg_match($chars < 0 ? $closingTagRegEx : $openingTagRegEx, $splittedContent[$offset], $matches);
3527  $tagName = $matches[1] ?? null;
3528  if ($tagName !== null) {
3529  // Seek for the closing (or opening) tag.
3530  $countSplittedContent = count($splittedContent);
3531  for ($seekingOffset = $offset + 2; $seekingOffset < $countSplittedContent; $seekingOffset = $seekingOffset + 2) {
3532  preg_match($chars < 0 ? $openingTagRegEx : $closingTagRegEx, $splittedContent[$seekingOffset], $matches);
3533  $seekingTagName = $matches[1] ?? null;
3534  if ($tagName === $seekingTagName) {
3535  // We found a matching tag.
3536  // Add closing tag only if it occurs after the cropped content item.
3537  if ($seekingOffset > $croppedOffset) {
3538  $closingTags[] = $splittedContent[$seekingOffset];
3539  }
3540  break;
3541  }
3542  }
3543  }
3544  }
3545  // Drop the cropped items of the content array. The $closingTags will be added later on again.
3546  array_splice($splittedContent, $croppedOffset + 1);
3547  }
3548  $splittedContent = array_merge($splittedContent, [
3549  $croppedOffset !== null ? $replacementForEllipsis : ''
3550  ], $closingTags);
3551  // Reverse array once again if we are cropping from the end.
3552  if ($chars < 0) {
3553  $splittedContent = array_reverse($splittedContent);
3554  }
3555  return implode('', $splittedContent);
3556  }
3557 
3568  public function ‪addParams($content, $conf, $isCoreCall = false)
3569  {
3570  if (!$isCoreCall) {
3571  trigger_error('ContentObjectRenderer->addParams() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
3572  }
3573  // For XHTML compliance.
3574  $lowerCaseAttributes = true;
3575  if (!is_array($conf)) {
3576  return $content;
3577  }
3578  $key = 1;
3579  $parts = explode('<', $content);
3580  if (isset($conf['_offset']) && (int)$conf['_offset']) {
3581  $key = (int)$conf['_offset'] < 0 ? count($parts) + (int)$conf['_offset'] : (int)$conf['_offset'];
3582  }
3583  $subparts = explode('>', $parts[$key] ?? '');
3584  if (trim($subparts[0])) {
3585  // Get attributes and name
3586  $attribs = GeneralUtility::get_tag_attributes('<' . $subparts[0] . '>');
3587  list($tagName) = explode(' ', $subparts[0], 2);
3588  // adds/overrides attributes
3589  foreach ($conf as $pkey => $val) {
3590  if (substr($pkey, -1) !== '.' && $pkey[0] !== '_') {
3591  $tmpVal = isset($conf[$pkey . '.']) ? $this->‪stdWrap($conf[$pkey], $conf[$pkey . '.']) : (string)$val;
3592  if ($lowerCaseAttributes) {
3593  $pkey = strtolower($pkey);
3594  }
3595  if ($tmpVal !== '') {
3596  $attribs[$pkey] = $tmpVal;
3597  }
3598  }
3599  }
3600  // Re-assembles the tag and content
3601  $subparts[0] = trim($tagName . ' ' . GeneralUtility::implodeAttributes($attribs));
3602  $parts[$key] = implode('>', $subparts);
3603  $content = implode('<', $parts);
3604  }
3605  return $content;
3606  }
3607 
3620  public function ‪filelink($theValue, $conf, $isCoreCall = false)
3621  {
3622  if (!$isCoreCall) {
3623  trigger_error('ContentObjectRenderer->filelink() will be removed in TYPO3 v10.0. Use cObject FILES instead.', E_USER_DEPRECATED);
3624  }
3625  $conf['path'] = isset($conf['path.'])
3626  ? $this->‪stdWrap($conf['path'] ?? '', $conf['path.'])
3627  : ($conf['path'] ?? '');
3628  $theFile = trim($conf['path']) . $theValue;
3629  if (!@is_file($theFile)) {
3630  return '';
3631  }
3632  $theFileEnc = str_replace('%2F', '/', rawurlencode($theFile));
3633  $title = $conf['title'] ?? '';
3634  if (isset($conf['title.'])) {
3635  $title = $this->‪stdWrap($title, $conf['title.']);
3636  }
3637  $target = $conf['target'] ?? '';
3638  if (isset($conf['target.'])) {
3639  $target = $this->‪stdWrap($target, $conf['target.']);
3640  }
3641  $tsfe = $this->‪getTypoScriptFrontendController();
3642 
3643  $typoLinkConf = [
3644  'parameter' => $theFileEnc,
3645  'fileTarget' => $target,
3646  'title' => $title,
3647  'ATagParams' => $this->‪getATagParams($conf)
3648  ];
3649 
3650  if (isset($conf['typolinkConfiguration.'])) {
3651  $additionalTypoLinkConfiguration = $conf['typolinkConfiguration.'];
3652  // We only allow additional configuration. This is why the generated conf overwrites the additional conf.
3653  ‪ArrayUtility::mergeRecursiveWithOverrule($additionalTypoLinkConfiguration, $typoLinkConf);
3654  $typoLinkConf = $additionalTypoLinkConfiguration;
3655  }
3656 
3657  $theLinkWrap = $this->‪typoLink('|', $typoLinkConf);
3658  $theSize = filesize($theFile);
3659  $fI = GeneralUtility::split_fileref($theFile);
3660  $icon = '';
3661  if ($conf['icon'] ?? false) {
3662  $conf['icon.']['path'] = isset($conf['icon.']['path.'])
3663  ? $this->‪stdWrap($conf['icon.']['path'], $conf['icon.']['path.'])
3664  : $conf['icon.']['path'];
3665  $iconPath = !empty($conf['icon.']['path'])
3666  ? $conf['icon.']['path']
3667  : GeneralUtility::getFileAbsFileName('EXT:frontend/Resources/Public/Icons/FileIcons/');
3668  $conf['icon.']['ext'] = isset($conf['icon.']['ext.'])
3669  ? $this->‪stdWrap($conf['icon.']['ext'], $conf['icon.']['ext.'])
3670  : $conf['icon.']['ext'];
3671  $iconExt = !empty($conf['icon.']['ext']) ? '.' . $conf['icon.']['ext'] : '.gif';
3672  $icon = @is_file($iconPath . $fI['fileext'] . $iconExt)
3673  ? $iconPath . $fI['fileext'] . $iconExt
3674  : $iconPath . 'default' . $iconExt;
3675  $icon = ‪PathUtility::stripPathSitePrefix($icon);
3676  // Checking for images: If image, then return link to thumbnail.
3677  $IEList = isset($conf['icon_image_ext_list.']) ? $this->‪stdWrap($conf['icon_image_ext_list'], $conf['icon_image_ext_list.']) : $conf['icon_image_ext_list'];
3678  $image_ext_list = str_replace(' ', '', strtolower($IEList));
3679  if ($fI['fileext'] && GeneralUtility::inList($image_ext_list, $fI['fileext'])) {
3680  if ($conf['iconCObject']) {
3681  $icon = $this->‪cObjGetSingle($conf['iconCObject'], $conf['iconCObject.'], 'iconCObject');
3682  } else {
3683  $notFoundThumb = GeneralUtility::getFileAbsFileName('EXT:core/Resources/Public/Images/NotFound.gif');
3684  $notFoundThumb = ‪PathUtility::stripPathSitePrefix($notFoundThumb);
3685  $sizeParts = [64, 64];
3686  if (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) {
3687  // using the File Abstraction Layer to generate a preview image
3688  try {
3691  if ($fileObject->isMissing()) {
3692  $icon = $notFoundThumb;
3693  } else {
3694  $fileExtension = $fileObject->‪getExtension();
3695  if ($fileExtension === 'ttf' || GeneralUtility::inList(‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) {
3696  if ($conf['icon_thumbSize'] || $conf['icon_thumbSize.']) {
3697  $thumbSize = isset($conf['icon_thumbSize.']) ? $this->‪stdWrap($conf['icon_thumbSize'], $conf['icon_thumbSize.']) : $conf['icon_thumbSize'];
3698  $sizeParts = explode('x', $thumbSize);
3699  }
3700  $icon = $fileObject->process(‪ProcessedFile::CONTEXT_IMAGEPREVIEW, [
3701  'width' => $sizeParts[0],
3702  'height' => $sizeParts[1]
3703  ])->getPublicUrl(true);
3704  }
3705  }
3706  } catch (ResourceDoesNotExistException $exception) {
3707  $icon = $notFoundThumb;
3708  }
3709  } else {
3710  $icon = $notFoundThumb;
3711  }
3712  $urlPrefix = '';
3713  if (parse_url($icon, PHP_URL_HOST) === null) {
3714  $urlPrefix = $tsfe->absRefPrefix;
3715  }
3716  $icon = '<img src="' . htmlspecialchars($urlPrefix . $icon) . '"' .
3717  ' width="' . (int)$sizeParts[0] . '" height="' . (int)$sizeParts[1] . '" ' .
3718  $this->‪getBorderAttr(' border="0"') . '' . $this->‪getAltParam($conf) . ' />';
3719  }
3720  } else {
3721  $conf['icon.']['widthAttribute'] = isset($conf['icon.']['widthAttribute.'])
3722  ? $this->‪stdWrap($conf['icon.']['widthAttribute'], $conf['icon.']['widthAttribute.'])
3723  : $conf['icon.']['widthAttribute'];
3724  $iconWidth = !empty($conf['icon.']['widthAttribute']) ? $conf['icon.']['widthAttribute'] : 18;
3725  $conf['icon.']['heightAttribute'] = isset($conf['icon.']['heightAttribute.'])
3726  ? $this->‪stdWrap($conf['icon.']['heightAttribute'], $conf['icon.']['heightAttribute.'])
3727  : $conf['icon.']['heightAttribute'];
3728  $iconHeight = !empty($conf['icon.']['heightAttribute']) ? (int)$conf['icon.']['heightAttribute'] : 16;
3729  $icon = '<img src="' . htmlspecialchars($tsfe->absRefPrefix . $icon) . '" width="' . (int)$iconWidth . '" height="' . (int)$iconHeight . '"'
3730  . $this->‪getBorderAttr(' border="0"') . $this->‪getAltParam($conf) . ' />';
3731  }
3732  if ($conf['icon_link'] && !$conf['combinedLink']) {
3733  $icon = $this->‪wrap($icon, $theLinkWrap);
3734  }
3735  $icon = isset($conf['icon.']) ? $this->‪stdWrap($icon, $conf['icon.']) : $icon;
3736  }
3737  $size = '';
3738  if ($conf['size'] ?? false) {
3739  $size = isset($conf['size.']) ? $this->‪stdWrap($theSize, $conf['size.']) : $theSize;
3740  }
3741  // Wrapping file label
3742  if ($conf['removePrependedNumbers'] ?? false) {
3743  $theValue = preg_replace('/_[0-9][0-9](\\.[[:alnum:]]*)$/', '\\1', $theValue);
3744  }
3745  if (isset($conf['labelStdWrap.'])) {
3746  $theValue = $this->‪stdWrap($theValue, $conf['labelStdWrap.']);
3747  }
3748  // Wrapping file
3749  $wrap = isset($conf['wrap.'])
3750  ? $this->‪stdWrap($conf['wrap'] ?? '', $conf['wrap.'])
3751  : ($conf['wrap'] ?? '');
3752  if ($conf['combinedLink'] ?? false) {
3753  $theValue = $icon . $theValue;
3754  if ($conf['ATagBeforeWrap']) {
3755  $theValue = $this->‪wrap($this->‪wrap($theValue, $wrap), $theLinkWrap);
3756  } else {
3757  $theValue = $this->‪wrap($this->‪wrap($theValue, $theLinkWrap), $wrap);
3758  }
3759  $file = isset($conf['file.']) ? $this->‪stdWrap($theValue, $conf['file.']) : $theValue;
3760  // output
3761  ‪$output = $file . $size;
3762  } else {
3763  if ($conf['ATagBeforeWrap'] ?? false) {
3764  $theValue = $this->‪wrap($this->‪wrap($theValue, $wrap), $theLinkWrap);
3765  } else {
3766  $theValue = $this->‪wrap($this->‪wrap($theValue, $theLinkWrap), $wrap);
3767  }
3768  $file = isset($conf['file.']) ? $this->‪stdWrap($theValue, $conf['file.']) : $theValue;
3769  // output
3770  ‪$output = $icon . $file . $size;
3771  }
3772  if (isset($conf['stdWrap.'])) {
3773  ‪$output = $this->‪stdWrap(‪$output, $conf['stdWrap.']);
3774  }
3775  return ‪$output;
3776  }
3777 
3785  public function ‪calc($val)
3786  {
3787  $parts = GeneralUtility::splitCalc($val, '+-*/');
3788  $value = 0;
3789  foreach ($parts as $part) {
3790  $theVal = $part[1];
3791  $sign = $part[0];
3792  if ((string)(int)$theVal === (string)$theVal) {
3793  $theVal = (int)$theVal;
3794  } else {
3795  $theVal = 0;
3796  }
3797  if ($sign === '-') {
3798  $value -= $theVal;
3799  }
3800  if ($sign === '+') {
3801  $value += $theVal;
3802  }
3803  if ($sign === '/') {
3804  if ((int)$theVal) {
3805  $value /= (int)$theVal;
3806  }
3807  }
3808  if ($sign === '*') {
3809  $value *= $theVal;
3810  }
3811  }
3812  return $value;
3813  }
3814 
3825  public function ‪calcIntExplode($delim, $string)
3826  {
3827  trigger_error('calcIntExplode will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
3828  $temp = explode($delim, $string);
3829  foreach ($temp as $key => $val) {
3830  $temp[$key] = (int)$this->‪calc($val);
3831  }
3832  return $temp;
3833  }
3834 
3846  public function ‪splitObj($value, $conf)
3847  {
3848  $conf['token'] = isset($conf['token.']) ? $this->‪stdWrap($conf['token'], $conf['token.']) : $conf['token'];
3849  if ($conf['token'] === '') {
3850  return $value;
3851  }
3852  $valArr = explode($conf['token'], $value);
3853 
3854  // return value directly by returnKey. No further processing
3855  if (!empty($valArr) && (‪MathUtility::canBeInterpretedAsInteger($conf['returnKey'] ?? null) || ($conf['returnKey.'] ?? false))
3856  ) {
3857  $key = isset($conf['returnKey.']) ? (int)$this->‪stdWrap($conf['returnKey'], $conf['returnKey.']) : (int)$conf['returnKey'];
3858  return $valArr[$key] ?? '';
3859  }
3860 
3861  // return the amount of elements. No further processing
3862  if (!empty($valArr) && ($conf['returnCount'] || $conf['returnCount.'])) {
3863  $returnCount = isset($conf['returnCount.']) ? (bool)$this->‪stdWrap($conf['returnCount'], $conf['returnCount.']) : (bool)$conf['returnCount'];
3864  return $returnCount ? count($valArr) : 0;
3865  }
3866 
3867  // calculate splitCount
3868  $splitCount = count($valArr);
3869  $max = isset($conf['max.']) ? (int)$this->‪stdWrap($conf['max'], $conf['max.']) : (int)$conf['max'];
3870  if ($max && $splitCount > $max) {
3871  $splitCount = $max;
3872  }
3873  $min = isset($conf['min.']) ? (int)$this->‪stdWrap($conf['min'], $conf['min.']) : (int)$conf['min'];
3874  if ($min && $splitCount < $min) {
3875  $splitCount = $min;
3876  }
3877  $wrap = isset($conf['wrap.']) ? (string)$this->‪stdWrap($conf['wrap'], $conf['wrap.']) : (string)$conf['wrap'];
3878  $cObjNumSplitConf = isset($conf['cObjNum.']) ? (string)$this->‪stdWrap($conf['cObjNum'], $conf['cObjNum.']) : (string)$conf['cObjNum'];
3879  $splitArr = [];
3880  if ($wrap !== '' || $cObjNumSplitConf !== '') {
3881  $splitArr['wrap'] = $wrap;
3882  $splitArr['cObjNum'] = $cObjNumSplitConf;
3883  $splitArr = GeneralUtility::makeInstance(TypoScriptService::class)
3884  ->explodeConfigurationForOptionSplit($splitArr, $splitCount);
3885  }
3886  $content = '';
3887  for ($a = 0; $a < $splitCount; $a++) {
3888  $this->‪getTypoScriptFrontendController()->register['SPLIT_COUNT'] = $a;
3889  $value = '' . $valArr[$a];
3890  $this->data[‪$this->currentValKey] = $value;
3891  if ($splitArr[$a]['cObjNum']) {
3892  $objName = (int)$splitArr[$a]['cObjNum'];
3893  $value = isset($conf[$objName . '.'])
3894  ? $this->‪stdWrap($this->‪cObjGet($conf[$objName . '.'], $objName . '.'), $conf[$objName . '.'])
3895  : $this->‪cObjGet($conf[$objName . '.'], $objName . '.');
3896  }
3897  $wrap = isset($splitArr[$a]['wrap.']) ? $this->‪stdWrap($splitArr[$a]['wrap'], $splitArr[$a]['wrap.']) : $splitArr[$a]['wrap'];
3898  if ($wrap) {
3899  $value = $this->‪wrap($value, $wrap);
3900  }
3901  $content .= $value;
3902  }
3903  return $content;
3904  }
3905 
3913  protected function ‪replacement($content, array $configuration)
3914  {
3915  // Sorts actions in configuration by numeric index
3916  ksort($configuration, SORT_NUMERIC);
3917  foreach ($configuration as $index => $action) {
3918  // Checks whether we have an valid action and a numeric key ending with a dot ("10.")
3919  if (is_array($action) && substr($index, -1) === '.' && ‪MathUtility::canBeInterpretedAsInteger(substr($index, 0, -1))) {
3920  $content = $this->‪replacementSingle($content, $action);
3921  }
3922  }
3923  return $content;
3924  }
3925 
3933  protected function ‪replacementSingle($content, array $configuration)
3934  {
3935  if ((isset($configuration['search']) || isset($configuration['search.'])) && (isset($configuration['replace']) || isset($configuration['replace.']))) {
3936  // Gets the strings
3937  $search = isset($configuration['search.']) ? $this->‪stdWrap($configuration['search'], $configuration['search.']) : $configuration['search'];
3938  $replace = isset($configuration['replace.'])
3939  ? $this->‪stdWrap($configuration['replace'] ?? null, $configuration['replace.'])
3940  : $configuration['replace'] ?? null;
3941  $useRegularExpression = false;
3942  // Determines whether regular expression shall be used
3943  if (isset($configuration['useRegExp'])
3944  || (isset($configuration['useRegExp.']) && $configuration['useRegExp.'])
3945  ) {
3946  $useRegularExpression = isset($configuration['useRegExp.']) ? (bool)$this->‪stdWrap($configuration['useRegExp'], $configuration['useRegExp.']) : (bool)$configuration['useRegExp'];
3947  }
3948  $useOptionSplitReplace = false;
3949  // Determines whether replace-pattern uses option-split
3950  if (isset($configuration['useOptionSplitReplace']) || isset($configuration['useOptionSplitReplace.'])) {
3951  $useOptionSplitReplace = isset($configuration['useOptionSplitReplace.']) ? (bool)$this->‪stdWrap($configuration['useOptionSplitReplace'], $configuration['useOptionSplitReplace.']) : (bool)$configuration['useOptionSplitReplace'];
3952  }
3953 
3954  // Performs a replacement by preg_replace()
3955  if ($useRegularExpression) {
3956  // Get separator-character which precedes the string and separates search-string from the modifiers
3957  $separator = $search[0];
3958  $startModifiers = strrpos($search, $separator);
3959  if ($separator !== false && $startModifiers > 0) {
3960  $modifiers = substr($search, $startModifiers + 1);
3961  // remove "e" (eval-modifier), which would otherwise allow to run arbitrary PHP-code
3962  $modifiers = str_replace('e', '', $modifiers);
3963  $search = substr($search, 0, $startModifiers + 1) . $modifiers;
3964  }
3965  if ($useOptionSplitReplace) {
3966  // init for replacement
3967  $splitCount = preg_match_all($search, $content, $matches);
3968  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
3969  $replaceArray = $typoScriptService->explodeConfigurationForOptionSplit([$replace], $splitCount);
3970  $replaceCount = 0;
3971 
3972  $replaceCallback = function ($match) use ($replaceArray, $search, &$replaceCount) {
3973  $replaceCount++;
3974  return preg_replace($search, $replaceArray[$replaceCount - 1][0], $match[0]);
3975  };
3976  $content = preg_replace_callback($search, $replaceCallback, $content);
3977  } else {
3978  $content = preg_replace($search, $replace, $content);
3979  }
3980  } elseif ($useOptionSplitReplace) {
3981  // turn search-string into a preg-pattern
3982  $searchPreg = '#' . preg_quote($search, '#') . '#';
3984  // init for replacement
3985  $splitCount = preg_match_all($searchPreg, $content, $matches);
3986  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
3987  $replaceArray = $typoScriptService->explodeConfigurationForOptionSplit([$replace], $splitCount);
3988  $replaceCount = 0;
3989 
3990  $replaceCallback = function () use ($replaceArray, $search, &$replaceCount) {
3991  $replaceCount++;
3992  return $replaceArray[$replaceCount - 1][0];
3993  };
3994  $content = preg_replace_callback($searchPreg, $replaceCallback, $content);
3995  } else {
3996  $content = str_replace($search, $replace, $content);
3997  }
3998  }
3999  return $content;
4000  }
4001 
4010  protected function ‪round($content, array $conf = [])
4011  {
4012  $decimals = isset($conf['decimals.'])
4013  ? $this->‪stdWrap($conf['decimals'] ?? '', $conf['decimals.'])
4014  : ($conf['decimals'] ?? null);
4015  $type = isset($conf['roundType.'])
4016  ? $this->‪stdWrap($conf['roundType'] ?? '', $conf['roundType.'])
4017  : ($conf['roundType'] ?? null);
4018  $floatVal = (float)$content;
4019  switch ($type) {
4020  case 'ceil':
4021  $content = ceil($floatVal);
4022  break;
4023  case 'floor':
4024  $content = floor($floatVal);
4025  break;
4026  case 'round':
4027 
4028  default:
4029  $content = ‪round($floatVal, (int)$decimals);
4030  }
4031  return $content;
4032  }
4033 
4042  public function ‪numberFormat($content, $conf)
4043  {
4044  $decimals = isset($conf['decimals.'])
4045  ? (int)$this->‪stdWrap($conf['decimals'] ?? '', $conf['decimals.'])
4046  : (int)($conf['decimals'] ?? 0);
4047  $dec_point = isset($conf['dec_point.'])
4048  ? $this->‪stdWrap($conf['dec_point'] ?? '', $conf['dec_point.'])
4049  : ($conf['dec_point'] ?? null);
4050  $thousands_sep = isset($conf['thousands_sep.'])
4051  ? $this->‪stdWrap($conf['thousands_sep'] ?? '', $conf['thousands_sep.'])
4052  : ($conf['thousands_sep'] ?? null);
4053  return number_format((float)$content, $decimals, $dec_point, $thousands_sep);
4054  }
4055 
4075  public function ‪parseFunc($theValue, $conf, $ref = '')
4076  {
4077  // Fetch / merge reference, if any
4078  if ($ref) {
4079  $temp_conf = [
4080  'parseFunc' => $ref,
4081  'parseFunc.' => $conf
4082  ];
4083  $temp_conf = $this->‪mergeTSRef($temp_conf, 'parseFunc');
4084  $conf = $temp_conf['parseFunc.'];
4085  }
4086  // early return, no processing in case no configuration is given
4087  if (empty($conf)) {
4088  // @deprecated Invoking ContentObjectRenderer::parseFunc without any configuration will trigger an exception in TYPO3 v12.0
4089  trigger_error('Invoking ContentObjectRenderer::parseFunc without any configuration will trigger an exception in TYPO3 v12.0', E_USER_DEPRECATED);
4090  return $theValue;
4091  }
4092  // Handle HTML sanitizer invocation
4093  if (!isset($conf['htmlSanitize'])) {
4094  // @deprecated Property htmlSanitize was not defined, but will be mandatory in TYPO3 v12.0
4095  trigger_error('Property htmlSanitize was not defined, but will be mandatory in TYPO3 v12.0', E_USER_DEPRECATED);
4096  $features = GeneralUtility::makeInstance(Features::class);
4097  $conf['htmlSanitize'] = $features->isFeatureEnabled('security.frontend.htmlSanitizeParseFuncDefault');
4098  }
4099  $conf['htmlSanitize'] = (bool)$conf['htmlSanitize'];
4100 
4101  // Process:
4102  if ((string)($conf['externalBlocks'] ?? '') === '') {
4103  $result = $this->‪_parseFunc($theValue, $conf);
4104  if ($conf['htmlSanitize']) {
4105  $result = $this->‪stdWrap_htmlSanitize($result, $conf['htmlSanitize.'] ?? []);
4106  }
4107  return $result;
4108  }
4109  $tags = strtolower(implode(',', GeneralUtility::trimExplode(',', $conf['externalBlocks'])));
4110  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
4111  $parts = $htmlParser->splitIntoBlock($tags, $theValue);
4112  foreach ($parts as $k => $v) {
4113  if ($k % 2) {
4114  // font:
4115  $tagName = strtolower($htmlParser->getFirstTagName($v));
4116  $cfg = $conf['externalBlocks.'][$tagName . '.'];
4117  if ($cfg['stripNLprev'] || $cfg['stripNL']) {
4118  $parts[$k - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $parts[$k - 1]);
4119  }
4120  if ($cfg['stripNLnext'] || $cfg['stripNL']) {
4121  $parts[$k + 1] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $parts[$k + 1]);
4122  }
4123  }
4124  }
4125  foreach ($parts as $k => $v) {
4126  if ($k % 2) {
4127  $tag = $htmlParser->getFirstTag($v);
4128  $tagName = strtolower($htmlParser->getFirstTagName($v));
4129  $cfg = $conf['externalBlocks.'][$tagName . '.'];
4130  if ($cfg['callRecursive']) {
4131  $parts[$k] = $this->‪parseFunc($htmlParser->removeFirstAndLastTag($v), $conf);
4132  if (!$cfg['callRecursive.']['dontWrapSelf']) {
4133  if ($cfg['callRecursive.']['alternativeWrap']) {
4134  $parts[$k] = $this->‪wrap($parts[$k], $cfg['callRecursive.']['alternativeWrap']);
4135  } else {
4136  if (is_array($cfg['callRecursive.']['tagStdWrap.'])) {
4137  $tag = $this->‪stdWrap($tag, $cfg['callRecursive.']['tagStdWrap.']);
4138  }
4139  $parts[$k] = $tag . $parts[$k] . '</' . $tagName . '>';
4140  }
4141  }
4142  } elseif ($cfg['HTMLtableCells']) {
4143  $rowParts = $htmlParser->splitIntoBlock('tr', $parts[$k]);
4144  foreach ($rowParts as $kk => $vv) {
4145  if ($kk % 2) {
4146  $colParts = $htmlParser->splitIntoBlock('td,th', $vv);
4147  $cc = 0;
4148  foreach ($colParts as $kkk => $vvv) {
4149  if ($kkk % 2) {
4150  $cc++;
4151  $tag = $htmlParser->getFirstTag($vvv);
4152  $tagName = strtolower($htmlParser->getFirstTagName($vvv));
4153  $colParts[$kkk] = $htmlParser->removeFirstAndLastTag($vvv);
4154  if ($cfg['HTMLtableCells.'][$cc . '.']['callRecursive'] || !isset($cfg['HTMLtableCells.'][$cc . '.']['callRecursive']) && $cfg['HTMLtableCells.']['default.']['callRecursive']) {
4155  if ($cfg['HTMLtableCells.']['addChr10BetweenParagraphs']) {
4156  $colParts[$kkk] = str_replace('</p><p>', '</p>' . LF . '<p>', $colParts[$kkk]);
4157  }
4158  $colParts[$kkk] = $this->‪parseFunc($colParts[$kkk], $conf);
4159  }
4160  $tagStdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.'])
4161  ? $cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.']
4162  : $cfg['HTMLtableCells.']['default.']['tagStdWrap.'];
4163  if (is_array($tagStdWrap)) {
4164  $tag = $this->‪stdWrap($tag, $tagStdWrap);
4165  }
4166  $stdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['stdWrap.'])
4167  ? $cfg['HTMLtableCells.'][$cc . '.']['stdWrap.']
4168  : $cfg['HTMLtableCells.']['default.']['stdWrap.'];
4169  if (is_array($stdWrap)) {
4170  $colParts[$kkk] = $this->‪stdWrap($colParts[$kkk], $stdWrap);
4171  }
4172  $colParts[$kkk] = $tag . $colParts[$kkk] . '</' . $tagName . '>';
4173  }
4174  }
4175  $rowParts[$kk] = implode('', $colParts);
4176  }
4177  }
4178  $parts[$k] = implode('', $rowParts);
4179  }
4180  if (is_array($cfg['stdWrap.'])) {
4181  $parts[$k] = $this->‪stdWrap($parts[$k], $cfg['stdWrap.']);
4182  }
4183  } else {
4184  $parts[$k] = $this->‪_parseFunc($parts[$k], $conf);
4185  }
4186  }
4187  $result = implode('', $parts);
4188  if ($conf['htmlSanitize']) {
4189  $result = $this->‪stdWrap_htmlSanitize($result, $conf['htmlSanitize.'] ?? []);
4190  }
4191  return $result;
4192  }
4193 
4203  public function ‪_parseFunc($theValue, $conf)
4204  {
4205  if (!empty($conf['if.']) && !$this->‪checkIf($conf['if.'])) {
4206  return $theValue;
4207  }
4208  // Indicates that the data is from within a tag.
4209  $inside = false;
4210  // Pointer to the total string position
4211  $pointer = 0;
4212  // Loaded with the current typo-tag if any.
4213  $currentTag = '';
4214  $stripNL = 0;
4215  $contentAccum = [];
4216  $contentAccumP = 0;
4217  $allowTags = strtolower(str_replace(' ', '', $conf['allowTags'] ?? ''));
4218  $denyTags = strtolower(str_replace(' ', '', $conf['denyTags'] ?? ''));
4219  $totalLen = strlen($theValue);
4220  do {
4221  if (!$inside) {
4222  if (!is_array($currentTag)) {
4223  // These operations should only be performed on code outside the typotags...
4224  // data: this checks that we enter tags ONLY if the first char in the tag is alphanumeric OR '/'
4225  $len_p = 0;
4226  $c = 100;
4227  do {
4228  $len = strcspn(substr($theValue, $pointer + $len_p), '<');
4229  $len_p += $len + 1;
4230  $endChar = ord(strtolower(substr($theValue, $pointer + $len_p, 1)));
4231  $c--;
4232  } while ($c > 0 && $endChar && ($endChar < 97 || $endChar > 122) && $endChar != 47);
4233  $len = $len_p - 1;
4234  } else {
4235  // If we're inside a currentTag, just take it to the end of that tag!
4236  $tempContent = strtolower(substr($theValue, $pointer));
4237  $len = strpos($tempContent, '</' . $currentTag[0]);
4238  if (is_string($len) && !$len) {
4239  $len = strlen($tempContent);
4240  }
4241  }
4242  // $data is the content until the next <tag-start or end is detected.
4243  // In case of a currentTag set, this would mean all data between the start- and end-tags
4244  ‪$data = substr($theValue, $pointer, $len);
4245  if (‪$data != '') {
4246  if ($stripNL) {
4247  // If the previous tag was set to strip NewLines in the beginning of the next data-chunk.
4248  ‪$data = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', ‪$data);
4249  }
4250  // These operations should only be performed on code outside the tags...
4251  if (!is_array($currentTag)) {
4252  // Constants
4253  $tsfe = $this->‪getTypoScriptFrontendController();
4254  $tmpConstants = $tsfe->tmpl->setup['constants.'] ?? null;
4255  if ($conf['constants'] && is_array($tmpConstants)) {
4256  foreach ($tmpConstants as $key => $val) {
4257  if (is_string($val)) {
4258  ‪$data = str_replace('###' . $key . '###', $val, ‪$data);
4259  }
4260  }
4261  }
4262  // Short
4263  if (isset($conf['short.']) && is_array($conf['short.'])) {
4264  $shortWords = $conf['short.'];
4265  krsort($shortWords);
4266  foreach ($shortWords as $key => $val) {
4267  if (is_string($val)) {
4268  ‪$data = str_replace($key, $val, ‪$data);
4269  }
4270  }
4271  }
4272  // stdWrap
4273  if (isset($conf['plainTextStdWrap.']) && is_array($conf['plainTextStdWrap.'])) {
4274  ‪$data = $this->‪stdWrap($data, $conf['plainTextStdWrap.']);
4275  }
4276  // userFunc
4277  if ($conf['userFunc'] ?? false) {
4278  ‪$data = $this->‪callUserFunction($conf['userFunc'], $conf['userFunc.'], ‪$data);
4279  }
4280  // Makelinks: (Before search-words as we need the links to be generated when searchwords go on...!)
4281  if ($conf['makelinks'] ?? false) {
4282  ‪$data = $this->‪http_makelinks($data, $conf['makelinks.']['http.']);
4283  ‪$data = $this->‪mailto_makelinks($data, $conf['makelinks.']['mailto.'] ?? []);
4284  }
4285  // Search Words:
4286  if ($tsfe->no_cache && $conf['sword'] && is_array($tsfe->sWordList) && $tsfe->sWordRegEx) {
4287  $newstring = '';
4288  do {
4289  $pregSplitMode = 'i';
4290  if (isset($tsfe->config['config']['sword_noMixedCase']) && !empty($tsfe->config['config']['sword_noMixedCase'])) {
4291  $pregSplitMode = '';
4292  }
4293  $pieces = preg_split('/' . $tsfe->sWordRegEx . '/' . $pregSplitMode, ‪$data, 2);
4294  $newstring .= $pieces[0];
4295  $match_len = strlen(‪$data) - (strlen($pieces[0]) + strlen($pieces[1]));
4296  $inTag = false;
4297  if (strstr($pieces[0], '<') || strstr($pieces[0], '>')) {
4298  // Returns TRUE, if a '<' is closer to the string-end than '>'.
4299  // This is the case if we're INSIDE a tag (that could have been
4300  // made by makelinks...) and we must secure, that the inside of a tag is
4301  // not marked up.
4302  $inTag = strrpos($pieces[0], '<') > strrpos($pieces[0], '>');
4303  }
4304  // The searchword:
4305  $match = substr(‪$data, strlen($pieces[0]), $match_len);
4306  if (trim($match) && strlen($match) > 1 && !$inTag) {
4307  $match = $this->‪wrap($match, $conf['sword']);
4308  }
4309  // Concatenate the Search Word again.
4310  $newstring .= $match;
4311  ‪$data = $pieces[1];
4312  } while ($pieces[1]);
4313  ‪$data = $newstring;
4314  }
4315  }
4316  $contentAccum[$contentAccumP] = isset($contentAccum[$contentAccumP])
4317  ? $contentAccum[$contentAccumP] . ‪$data
4318  : ‪$data;
4319  }
4320  $inside = true;
4321  } else {
4322  // tags
4323  $len = strcspn(substr($theValue, $pointer), '>') + 1;
4324  ‪$data = substr($theValue, $pointer, $len);
4325  if (‪StringUtility::endsWith(‪$data, '/>') && strpos(‪$data, '<link ') !== 0) {
4326  $tagContent = substr(‪$data, 1, -2);
4327  } else {
4328  $tagContent = substr(‪$data, 1, -1);
4329  }
4330  $tag = explode(' ', trim($tagContent), 2);
4331  $tag[0] = strtolower($tag[0]);
4332  if ($tag[0][0] === '/') {
4333  $tag[0] = substr($tag[0], 1);
4334  $tag['out'] = 1;
4335  }
4336  if ($conf['tags.'][$tag[0]] ?? false) {
4337  $treated = false;
4338  $stripNL = false;
4339  // in-tag
4340  if (!$currentTag && (!isset($tag['out']) || !$tag['out'])) {
4341  // $currentTag (array!) is the tag we are currently processing
4342  $currentTag = $tag;
4343  $contentAccumP++;
4344  $treated = true;
4345  // in-out-tag: img and other empty tags
4346  if (preg_match('/^(area|base|br|col|hr|img|input|meta|param)$/i', $tag[0])) {
4347  $tag['out'] = 1;
4348  }
4349  }
4350  // out-tag
4351  if ($currentTag[0] === $tag[0] && isset($tag['out']) && $tag['out']) {
4352  $theName = $conf['tags.'][$tag[0]];
4353  $theConf = $conf['tags.'][$tag[0] . '.'];
4354  // This flag indicates, that NL- (13-10-chars) should be stripped first and last.
4355  $stripNL = (bool)($theConf['stripNL'] ?? false);
4356  // This flag indicates, that this TypoTag section should NOT be included in the nonTypoTag content.
4357  $breakOut = (bool)($theConf['breakoutTypoTagContent'] ?? false);
4358  $this->parameters = [];
4359  if ($currentTag[1]) {
4360  // decode HTML entities in attributes, since they're processed
4361  $params = GeneralUtility::get_tag_attributes($currentTag[1], true);
4362  if (is_array($params)) {
4363  foreach ($params as $option => $val) {
4364  // contains non-encoded values
4365  $this->parameters[strtolower($option)] = $val;
4366  }
4367  }
4368  }
4369  $this->parameters['allParams'] = trim($currentTag[1]);
4370  // Removes NL in the beginning and end of the tag-content AND at the end of the currentTagBuffer.
4371  // $stripNL depends on the configuration of the current tag
4372  if ($stripNL) {
4373  $contentAccum[$contentAccumP - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP - 1]);
4374  $contentAccum[$contentAccumP] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $contentAccum[$contentAccumP]);
4375  $contentAccum[$contentAccumP] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP]);
4376  }
4377  $this->data[‪$this->currentValKey] = $contentAccum[$contentAccumP];
4378  $newInput = $this->‪cObjGetSingle($theName, $theConf, '/parseFunc/.tags.' . $tag[0]);
4379  // fetch the content object
4380  $contentAccum[$contentAccumP] = $newInput;
4381  $contentAccumP++;
4382  // If the TypoTag section
4383  if (!$breakOut) {
4384  if (!isset($contentAccum[$contentAccumP - 2])) {
4385  $contentAccum[$contentAccumP - 2] = '';
4386  }
4387  $contentAccum[$contentAccumP - 2] .= ($contentAccum[$contentAccumP - 1] ?? '') . ($contentAccum[$contentAccumP] ?? '');
4388  unset($contentAccum[$contentAccumP]);
4389  unset($contentAccum[$contentAccumP - 1]);
4390  $contentAccumP -= 2;
4391  }
4392  unset($currentTag);
4393  $treated = true;
4394  }
4395  // other tags
4396  if (!$treated) {
4397  $contentAccum[$contentAccumP] .= ‪$data;
4398  }
4399  } else {
4400  // If a tag was not a typo tag, then it is just added to the content
4401  $stripNL = false;
4402  if (GeneralUtility::inList($allowTags, $tag[0]) || $denyTags !== '*' && !GeneralUtility::inList($denyTags, $tag[0])) {
4403  $contentAccum[$contentAccumP] = isset($contentAccum[$contentAccumP])
4404  ? $contentAccum[$contentAccumP] . ‪$data
4405  : ‪$data;
4406  } else {
4407  $contentAccum[$contentAccumP] = isset($contentAccum[$contentAccumP])
4408  ? $contentAccum[$contentAccumP] . htmlspecialchars(‪$data)
4409  : htmlspecialchars(‪$data);
4410  }
4411  }
4412  $inside = false;
4413  }
4414  $pointer += $len;
4415  } while ($pointer < $totalLen);
4416  // Parsing nonTypoTag content (all even keys):
4417  reset($contentAccum);
4418  $contentAccumCount = count($contentAccum);
4419  for ($a = 0; $a < $contentAccumCount; $a++) {
4420  if ($a % 2 != 1) {
4421  // stdWrap
4422  if (isset($conf['nonTypoTagStdWrap.']) && is_array($conf['nonTypoTagStdWrap.'])) {
4423  $contentAccum[$a] = $this->‪stdWrap($contentAccum[$a], $conf['nonTypoTagStdWrap.']);
4424  }
4425  // userFunc
4426  if (!empty($conf['nonTypoTagUserFunc'])) {
4427  $contentAccum[$a] = $this->‪callUserFunction($conf['nonTypoTagUserFunc'], $conf['nonTypoTagUserFunc.'], $contentAccum[$a]);
4428  }
4429  }
4430  }
4431  return implode('', $contentAccum);
4432  }
4433 
4442  public function ‪encaps_lineSplit($theValue, $conf)
4443  {
4444  if ((string)$theValue === '') {
4445  return '';
4446  }
4447  $lParts = explode(LF, $theValue);
4448 
4449  // When the last element is an empty linebreak we need to remove it, otherwise we will have a duplicate empty line.
4450  $lastPartIndex = count($lParts) - 1;
4451  if ($lParts[$lastPartIndex] === '' && trim($lParts[$lastPartIndex - 1], CR) === '') {
4452  array_pop($lParts);
4453  }
4454 
4455  $encapTags = GeneralUtility::trimExplode(',', strtolower($conf['encapsTagList']), true);
4456  $nonWrappedTag = $conf['nonWrappedTag'];
4457  $defaultAlign = isset($conf['defaultAlign.'])
4458  ? trim($this->‪stdWrap($conf['defaultAlign'] ?? '', $conf['defaultAlign.']))
4459  : trim($conf['defaultAlign'] ?? '');
4460 
4461  $str_content = '';
4462  foreach ($lParts as $k => $l) {
4463  $sameBeginEnd = 0;
4464  $emptyTag = false;
4465  $l = trim($l);
4466  $attrib = [];
4467  $nonWrapped = false;
4468  $tagName = '';
4469  if (isset($l[0]) && $l[0] === '<' && substr($l, -1) === '>') {
4470  $fwParts = explode('>', substr($l, 1), 2);
4471  list($tagName) = explode(' ', $fwParts[0], 2);
4472  if (!$fwParts[1]) {
4473  if (substr($tagName, -1) === '/') {
4474  $tagName = substr($tagName, 0, -1);
4475  }
4476  if (substr($fwParts[0], -1) === '/') {
4477  $sameBeginEnd = 1;
4478  $emptyTag = true;
4479  // decode HTML entities, they're encoded later again
4480  $attrib = GeneralUtility::get_tag_attributes('<' . substr($fwParts[0], 0, -1) . '>', true);
4481  }
4482  } else {
4483  $backParts = GeneralUtility::revExplode('<', substr($fwParts[1], 0, -1), 2);
4484  // decode HTML entities, they're encoded later again
4485  $attrib = GeneralUtility::get_tag_attributes('<' . $fwParts[0] . '>', true);
4486  $str_content = $backParts[0];
4487  $sameBeginEnd = substr(strtolower($backParts[1]), 1, strlen($tagName)) === strtolower($tagName);
4488  }
4489  }
4490  if ($sameBeginEnd && in_array(strtolower($tagName), $encapTags)) {
4491  $uTagName = strtoupper($tagName);
4492  $uTagName = strtoupper($conf['remapTag.'][$uTagName] ?? $uTagName);
4493  } else {
4494  $uTagName = strtoupper($nonWrappedTag);
4495  // The line will be wrapped: $uTagName should not be an empty tag
4496  $emptyTag = false;
4497  $str_content = $lParts[$k];
4498  $nonWrapped = true;
4499  $attrib = [];
4500  }
4501  // Wrapping all inner-content:
4502  if (is_array($conf['innerStdWrap_all.'])) {
4503  $str_content = $this->‪stdWrap($str_content, $conf['innerStdWrap_all.']);
4504  }
4505  if ($uTagName) {
4506  // Setting common attributes
4507  if (isset($conf['addAttributes.'][$uTagName . '.']) && is_array($conf['addAttributes.'][$uTagName . '.'])) {
4508  foreach ($conf['addAttributes.'][$uTagName . '.'] as $kk => $vv) {
4509  if (!is_array($vv)) {
4510  if ((string)$conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] === 'blank') {
4511  if ((string)($attrib[$kk] ?? '') === '') {
4512  $attrib[$kk] = $vv;
4513  }
4514  } elseif ((string)$conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] === 'exists') {
4515  if (!isset($attrib[$kk])) {
4516  $attrib[$kk] = $vv;
4517  }
4518  } else {
4519  $attrib[$kk] = $vv;
4520  }
4521  }
4522  }
4523  }
4524  // Wrapping all inner-content:
4525  if (isset($conf['encapsLinesStdWrap.'][$uTagName . '.']) && is_array($conf['encapsLinesStdWrap.'][$uTagName . '.'])) {
4526  $str_content = $this->‪stdWrap($str_content, $conf['encapsLinesStdWrap.'][$uTagName . '.']);
4527  }
4528  // Default align
4529  if ((!isset($attrib['align']) || !$attrib['align']) && $defaultAlign) {
4530  $attrib['align'] = $defaultAlign;
4531  }
4532  // implode (insecure) attributes, that's why `htmlspecialchars` is used here
4533  $params = GeneralUtility::implodeAttributes($attrib, true);
4534  if (!isset($conf['removeWrapping']) || !$conf['removeWrapping'] || ($emptyTag && $conf['removeWrapping.']['keepSingleTag'])) {
4535  $selfClosingTagList = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
4536  if ($emptyTag && in_array(strtolower($uTagName), $selfClosingTagList, true)) {
4537  $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . ' />';
4538  } else {
4539  $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . '>' . $str_content . '</' . strtolower($uTagName) . '>';
4540  }
4541  }
4542  }
4543  if ($nonWrapped && isset($conf['wrapNonWrappedLines']) && $conf['wrapNonWrappedLines']) {
4544  $str_content = $this->‪wrap($str_content, $conf['wrapNonWrappedLines']);
4545  }
4546  $lParts[$k] = $str_content;
4547  }
4548  return implode(LF, $lParts);
4549  }
4550 
4561  public function ‪http_makelinks(‪$data, $conf)
4562  {
4563  $aTagParams = $this->‪getATagParams($conf);
4564  $textstr = '';
4565  foreach (['http://', 'https://'] as $scheme) {
4566  $textpieces = explode($scheme, ‪$data);
4567  $pieces = count($textpieces);
4568  $textstr = $textpieces[0];
4569  for ($i = 1; $i < $pieces; $i++) {
4570  $len = strcspn($textpieces[$i], chr(32) . "\t" . CRLF);
4571  if (trim(substr($textstr, -1)) === '' && $len) {
4572  $lastChar = substr($textpieces[$i], $len - 1, 1);
4573  if (!preg_match('/[A-Za-z0-9\\/#_-]/', $lastChar)) {
4574  $len--;
4575  }
4576  // Included '\/' 3/12
4577  $parts[0] = substr($textpieces[$i], 0, $len);
4578  $parts[1] = substr($textpieces[$i], $len);
4579  $keep = $conf['keep'];
4580  $linkParts = parse_url($scheme . $parts[0]);
4581  $linktxt = '';
4582  if (strstr($keep, 'scheme')) {
4583  $linktxt = $scheme;
4584  }
4585  $linktxt .= $linkParts['host'];
4586  if (strstr($keep, 'path')) {
4587  $linktxt .= $linkParts['path'];
4588  // Added $linkParts['query'] 3/12
4589  if (strstr($keep, 'query') && $linkParts['query']) {
4590  $linktxt .= '?' . $linkParts['query'];
4591  } elseif ($linkParts['path'] === '/') {
4592  $linktxt = substr($linktxt, 0, -1);
4593  }
4594  }
4595  if (isset($conf['extTarget'])) {
4596  if (isset($conf['extTarget.'])) {
4597  $target = $this->‪stdWrap($conf['extTarget'], $conf['extTarget.']);
4598  } else {
4599  $target = $conf['extTarget'];
4600  }
4601  } else {
4602  $target = $this->‪getTypoScriptFrontendController()->extTarget;
4603  }
4604 
4605  // check for jump URLs or similar
4606  $linkUrl = $this->‪processUrl(‪UrlProcessorInterface::CONTEXT_COMMON, $scheme . $parts[0], $conf);
4607 
4608  $res = '<a href="' . htmlspecialchars($linkUrl) . '"'
4609  . ($target !== '' ? ' target="' . htmlspecialchars($target) . '"' : '')
4610  . $aTagParams . $this->‪extLinkATagParams('http://' . $parts[0], 'url') . '>';
4611 
4612  $wrap = isset($conf['wrap.']) ? $this->‪stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
4613  if ((string)$conf['ATagBeforeWrap'] !== '') {
4614  $res = $res . $this->‪wrap($linktxt, $wrap) . '</a>';
4615  } else {
4616  $res = $this->‪wrap($res . $linktxt . '</a>', $wrap);
4617  }
4618  $textstr .= $res . $parts[1];
4619  } else {
4620  $textstr .= $scheme . $textpieces[$i];
4621  }
4622  }
4623  ‪$data = $textstr;
4624  }
4625  return $textstr;
4626  }
4627 
4637  public function ‪mailto_makelinks(‪$data, $conf)
4638  {
4639  // http-split
4640  $aTagParams = $this->‪getATagParams($conf);
4641  $textpieces = explode('mailto:', ‪$data);
4642  $pieces = count($textpieces);
4643  $textstr = $textpieces[0];
4644  $tsfe = $this->‪getTypoScriptFrontendController();
4645  for ($i = 1; $i < $pieces; $i++) {
4646  $len = strcspn($textpieces[$i], chr(32) . "\t" . CRLF);
4647  if (trim(substr($textstr, -1)) === '' && $len) {
4648  $lastChar = substr($textpieces[$i], $len - 1, 1);
4649  if (!preg_match('/[A-Za-z0-9]/', $lastChar)) {
4650  $len--;
4651  }
4652  $parts[0] = substr($textpieces[$i], 0, $len);
4653  $parts[1] = substr($textpieces[$i], $len);
4654  $linktxt = preg_replace('/\\?.*/', '', $parts[0]);
4655  list($mailToUrl, $linktxt) = $this->‪getMailTo($parts[0], $linktxt);
4656  $mailToUrl = $tsfe->spamProtectEmailAddresses === 'ascii' ? $mailToUrl : htmlspecialchars($mailToUrl);
4657  $res = '<a href="' . $mailToUrl . '"' . $aTagParams . '>';
4658  $wrap = isset($conf['wrap.']) ? $this->‪stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
4659  if ((string)$conf['ATagBeforeWrap'] !== '') {
4660  $res = $res . $this->‪wrap($linktxt, $wrap) . '</a>';
4661  } else {
4662  $res = $this->‪wrap($res . $linktxt . '</a>', $wrap);
4663  }
4664  $textstr .= $res . $parts[1];
4665  } else {
4666  $textstr .= 'mailto:' . $textpieces[$i];
4667  }
4668  }
4669  return $textstr;
4670  }
4671 
4696  public function ‪getImgResource($file, $fileArray)
4697  {
4698  if (empty($file) && empty($fileArray)) {
4699  return null;
4700  }
4701  if (!is_array($fileArray)) {
4702  $fileArray = (array)$fileArray;
4703  }
4704  $imageResource = null;
4705  if ($file === 'GIFBUILDER') {
4706  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
4707  $theImage = '';
4708  if (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
4709  $gifCreator->start($fileArray, $this->data);
4710  $theImage = $gifCreator->gifBuild();
4711  }
4712  $imageResource = $gifCreator->getImageDimensions($theImage);
4713  $imageResource['origFile'] = $theImage;
4714  } else {
4715  if ($file instanceof File) {
4716  $fileObject = $file;
4717  } elseif ($file instanceof FileReference) {
4718  $fileObject = $file->getOriginalFile();
4719  } else {
4720  try {
4721  if (isset($fileArray['import.']) && $fileArray['import.']) {
4722  $importedFile = trim($this->‪stdWrap('', $fileArray['import.']));
4723  if (!empty($importedFile)) {
4724  $file = $importedFile;
4725  }
4726  }
4727 
4729  $treatIdAsReference = isset($fileArray['treatIdAsReference.']) ? $this->‪stdWrap($fileArray['treatIdAsReference'], $fileArray['treatIdAsReference.']) : $fileArray['treatIdAsReference'];
4730  if (!empty($treatIdAsReference)) {
4731  $file = $this->‪getResourceFactory()->‪getFileReferenceObject($file);
4732  $fileObject = $file->‪getOriginalFile();
4733  } else {
4734  $fileObject = $this->‪getResourceFactory()->‪getFileObject($file);
4735  }
4736  } elseif (preg_match('/^(0|[1-9][0-9]*):/', $file)) { // combined identifier
4737  $fileObject = $this->‪getResourceFactory()->‪retrieveFileOrFolderObject($file);
4738  } else {
4739  if (isset($importedFile) && !empty($importedFile) && !empty($fileArray['import'])) {
4740  $file = $fileArray['import'] . $file;
4741  }
4742  $fileObject = $this->‪getResourceFactory()->‪retrieveFileOrFolderObject($file);
4743  }
4744  } catch (Exception $exception) {
4745  $this->logger->warning('The image "' . $file . '" could not be found and won\'t be included in frontend output', ['exception' => $exception]);
4746  return null;
4747  }
4748  }
4749  if ($fileObject instanceof File) {
4750  $processingConfiguration = [];
4751  $processingConfiguration['width'] = isset($fileArray['width.']) ? $this->‪stdWrap($fileArray['width'], $fileArray['width.']) : $fileArray['width'];
4752  $processingConfiguration['height'] = isset($fileArray['height.']) ? $this->‪stdWrap($fileArray['height'], $fileArray['height.']) : $fileArray['height'];
4753  $processingConfiguration['fileExtension'] = isset($fileArray['ext.']) ? $this->‪stdWrap($fileArray['ext'], $fileArray['ext.']) : $fileArray['ext'];
4754  $processingConfiguration['maxWidth'] = isset($fileArray['maxW.']) ? (int)$this->‪stdWrap($fileArray['maxW'], $fileArray['maxW.']) : (int)$fileArray['maxW'];
4755  $processingConfiguration['maxHeight'] = isset($fileArray['maxH.']) ? (int)$this->‪stdWrap($fileArray['maxH'], $fileArray['maxH.']) : (int)$fileArray['maxH'];
4756  $processingConfiguration['minWidth'] = isset($fileArray['minW.']) ? (int)$this->‪stdWrap($fileArray['minW'], $fileArray['minW.']) : (int)$fileArray['minW'];
4757  $processingConfiguration['minHeight'] = isset($fileArray['minH.']) ? (int)$this->‪stdWrap($fileArray['minH'], $fileArray['minH.']) : (int)$fileArray['minH'];
4758  $processingConfiguration['noScale'] = isset($fileArray['noScale.']) ? $this->‪stdWrap($fileArray['noScale'], $fileArray['noScale.']) : $fileArray['noScale'];
4759  $processingConfiguration['additionalParameters'] = isset($fileArray['params.']) ? $this->‪stdWrap($fileArray['params'], $fileArray['params.']) : $fileArray['params'];
4760  $processingConfiguration['frame'] = isset($fileArray['frame.']) ? (int)$this->‪stdWrap($fileArray['frame'], $fileArray['frame.']) : (int)$fileArray['frame'];
4761  if ($file instanceof FileReference) {
4762  $processingConfiguration['crop'] = $this->‪getCropAreaFromFileReference($file, $fileArray);
4763  } else {
4764  $processingConfiguration['crop'] = $this->‪getCropAreaFromFromTypoScriptSettings($fileObject, $fileArray);
4765  }
4766 
4767  // Possibility to cancel/force profile extraction
4768  // see $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_stripColorProfileCommand']
4769  if (isset($fileArray['stripProfile'])) {
4770  $processingConfiguration['stripProfile'] = $fileArray['stripProfile'];
4771  }
4772  // Check if we can handle this type of file for editing
4773  if (GeneralUtility::inList(‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) {
4774  $maskArray = $fileArray['m.'];
4775  // Must render mask images and include in hash-calculating
4776  // - otherwise we cannot be sure the filename is unique for the setup!
4777  if (is_array($maskArray)) {
4778  $mask = $this->‪getImgResource($maskArray['mask'], $maskArray['mask.']);
4779  $bgImg = $this->‪getImgResource($maskArray['bgImg'], $maskArray['bgImg.']);
4780  $bottomImg = $this->‪getImgResource($maskArray['bottomImg'], $maskArray['bottomImg.']);
4781  $bottomImg_mask = $this->‪getImgResource($maskArray['bottomImg_mask'], $maskArray['bottomImg_mask.']);
4782 
4783  $processingConfiguration['maskImages']['maskImage'] = $mask['processedFile'];
4784  $processingConfiguration['maskImages']['backgroundImage'] = $bgImg['processedFile'];
4785  $processingConfiguration['maskImages']['maskBottomImage'] = $bottomImg['processedFile'];
4786  $processingConfiguration['maskImages']['maskBottomImageMask'] = $bottomImg_mask['processedFile'];
4787  }
4788  $processedFileObject = $fileObject->process(‪ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration);
4789  if ($processedFileObject->isProcessed()) {
4790  $imageResource = [
4791  0 => (int)$processedFileObject->getProperty('width'),
4792  1 => (int)$processedFileObject->getProperty('height'),
4793  2 => $processedFileObject->getExtension(),
4794  3 => $processedFileObject->getPublicUrl(),
4795  'origFile' => $fileObject->getPublicUrl(),
4796  'origFile_mtime' => $fileObject->getModificationTime(),
4797  // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder,
4798  // in order for the setup-array to create a unique filename hash.
4799  'originalFile' => $fileObject,
4800  'processedFile' => $processedFileObject
4801  ];
4802  }
4803  }
4804  }
4805  }
4806  // If image was processed by GIFBUILDER:
4807  // ($imageResource indicates that it was processed the regular way)
4808  if (!isset($imageResource)) {
4809  try {
4810  $theImage = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize((string)$file);
4811  $info = GeneralUtility::makeInstance(GifBuilder::class)->imageMagickConvert($theImage, 'WEB');
4812  $info['origFile'] = $theImage;
4813  // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder, ln 100ff in order for the setup-array to create a unique filename hash.
4814  $info['origFile_mtime'] = @filemtime($theImage);
4815  $imageResource = $info;
4816  } catch (\‪TYPO3\CMS\Core\Resource\Exception $e) {
4817  // do nothing in case the file path is invalid
4818  }
4819  }
4820  // Hook 'getImgResource': Post-processing of image resources
4821  if (isset($imageResource)) {
4823  foreach ($this->‪getGetImgResourceHookObjects() as $hookObject) {
4824  $imageResource = $hookObject->getImgResourcePostProcess($file, (array)$fileArray, $imageResource, $this);
4825  }
4826  }
4827  return $imageResource;
4828  }
4829 
4847  protected function ‪getCropAreaFromFileReference(FileReference $fileReference, array $fileArray)
4848  {
4849  // Use cropping area from file reference if nothing is configured in TypoScript.
4850  if (!isset($fileArray['crop']) && !isset($fileArray['crop.'])) {
4851  // Set crop variant from TypoScript settings. If not set, use default.
4852  $cropVariant = $fileArray['cropVariant'] ?? 'default';
4853  $fileCropArea = $this->‪createCropAreaFromJsonString((string)$fileReference->getProperty('crop'), $cropVariant);
4854  return $fileCropArea->isEmpty() ? null : $fileCropArea->makeAbsoluteBasedOnFile($fileReference);
4855  }
4856 
4857  return $this->‪getCropAreaFromFromTypoScriptSettings($fileReference, $fileArray);
4858  }
4859 
4868  protected function ‪getCropAreaFromFromTypoScriptSettings(FileInterface $file, array $fileArray)
4869  {
4871  $cropArea = null;
4872  // Resolve TypoScript configured cropping.
4873  $cropSettings = isset($fileArray['crop.'])
4874  ? $this->‪stdWrap($fileArray['crop'], $fileArray['crop.'])
4875  : ($fileArray['crop'] ?? null);
4876 
4877  if (is_string($cropSettings)) {
4878  // Set crop variant from TypoScript settings. If not set, use default.
4879  $cropVariant = $fileArray['cropVariant'] ?? 'default';
4880  // Get cropArea from CropVariantCollection, if cropSettings is a valid json.
4881  // CropVariantCollection::create does json_decode.
4882  $jsonCropArea = $this->‪createCropAreaFromJsonString($cropSettings, $cropVariant);
4883  $cropArea = $jsonCropArea->isEmpty() ? null : $jsonCropArea->makeAbsoluteBasedOnFile($file);
4884 
4885  // Cropping is configured in TypoScript in the following way: file.crop = 50,50,100,100
4886  if ($jsonCropArea->isEmpty() && preg_match('/^[0-9]+,[0-9]+,[0-9]+,[0-9]+$/', $cropSettings)) {
4887  $cropSettings = explode(',', $cropSettings);
4888  if (count($cropSettings) === 4) {
4889  $stringCropArea = GeneralUtility::makeInstance(
4890  Area::class,
4891  ...$cropSettings
4892  );
4893  $cropArea = $stringCropArea->isEmpty() ? null : $stringCropArea;
4894  }
4895  }
4896  }
4897 
4898  return $cropArea;
4899  }
4900 
4909  protected function ‪createCropAreaFromJsonString(string $cropSettings, string $cropVariant): ‪Area
4910  {
4911  return ‪CropVariantCollection::create($cropSettings)->‪getCropArea($cropVariant);
4912  }
4913 
4914  /***********************************************
4915  *
4916  * Data retrieval etc.
4917  *
4918  ***********************************************/
4925  public function ‪getFieldVal($field)
4926  {
4927  if (!strstr($field, '//')) {
4928  return $this->data[trim($field)] ?? null;
4929  }
4930  $sections = GeneralUtility::trimExplode('//', $field, true);
4931  foreach ($sections as $k) {
4932  if ((string)$this->data[$k] !== '') {
4933  return $this->data[$k];
4934  }
4935  }
4936 
4937  return '';
4938  }
4939 
4948  public function ‪getData($string, $fieldArray = null)
4949  {
4950  $tsfe = $this->‪getTypoScriptFrontendController();
4951  if (!is_array($fieldArray)) {
4952  $fieldArray = $tsfe->page;
4953  }
4954  $retVal = '';
4955  $sections = explode('//', $string);
4956  foreach ($sections as $secKey => $secVal) {
4957  if ($retVal) {
4958  break;
4959  }
4960  $parts = explode(':', $secVal, 2);
4961  $type = strtolower(trim($parts[0]));
4962  $typesWithOutParameters = ['level', 'date', 'current', 'pagelayout'];
4963  $key = trim($parts[1] ?? '');
4964  if (($key != '') || in_array($type, $typesWithOutParameters)) {
4965  switch ($type) {
4966  case 'gp':
4967  // Merge GET and POST and get $key out of the merged array
4968  $getPostArray = GeneralUtility::_GET();
4969  ‪ArrayUtility::mergeRecursiveWithOverrule($getPostArray, GeneralUtility::_POST());
4970  $retVal = $this->‪getGlobal($key, $getPostArray);
4971  break;
4972  case 'tsfe':
4973  $retVal = $this->‪getGlobal('TSFE|' . $key);
4974  break;
4975  case 'getenv':
4976  $retVal = getenv($key);
4977  break;
4978  case 'getindpenv':
4979  $retVal = $this->‪getEnvironmentVariable($key);
4980  break;
4981  case 'field':
4982  $retVal = $this->‪getGlobal($key, $fieldArray);
4983  break;
4984  case 'file':
4985  $retVal = $this->‪getFileDataKey($key);
4986  break;
4987  case 'parameters':
4988  $retVal = $this->parameters[$key];
4989  break;
4990  case 'register':
4991  $retVal = $tsfe->register[$key] ?? null;
4992  break;
4993  case 'global':
4994  $retVal = $this->‪getGlobal($key);
4995  break;
4996  case 'level':
4997  $retVal = count($tsfe->tmpl->rootLine) - 1;
4998  break;
4999  case 'leveltitle':
5000  $keyParts = GeneralUtility::trimExplode(',', $key);
5001  $numericKey = $this->‪getKey($keyParts[0], $tsfe->tmpl->rootLine);
5002  $retVal = $this->‪rootLineValue($numericKey, 'title', strtolower($keyParts[1] ?? '') === 'slide');
5003  break;
5004  case 'levelmedia':
5005  $keyParts = GeneralUtility::trimExplode(',', $key);
5006  $numericKey = $this->‪getKey($keyParts[0], $tsfe->tmpl->rootLine);
5007  $retVal = $this->‪rootLineValue($numericKey, 'media', strtolower($keyParts[1] ?? '') === 'slide');
5008  break;
5009  case 'leveluid':
5010  $numericKey = $this->‪getKey($key, $tsfe->tmpl->rootLine);
5011  $retVal = $this->‪rootLineValue($numericKey, 'uid');
5012  break;
5013  case 'levelfield':
5014  $keyParts = GeneralUtility::trimExplode(',', $key);
5015  $numericKey = $this->‪getKey($keyParts[0], $tsfe->tmpl->rootLine);
5016  $retVal = $this->‪rootLineValue($numericKey, $keyParts[1], strtolower($keyParts[2] ?? '') === 'slide');
5017  break;
5018  case 'fullrootline':
5019  $keyParts = GeneralUtility::trimExplode(',', $key);
5020  $fullKey = (int)$keyParts[0] - count($tsfe->tmpl->rootLine) + count($tsfe->rootLine);
5021  if ($fullKey >= 0) {
5022  $retVal = $this->‪rootLineValue($fullKey, $keyParts[1], stristr($keyParts[2] ?? '', 'slide'), $tsfe->rootLine);
5023  }
5024  break;
5025  case 'date':
5026  if (!$key) {
5027  $key = 'd/m Y';
5028  }
5029  $retVal = date($key, ‪$GLOBALS['EXEC_TIME']);
5030  break;
5031  case 'page':
5032  $retVal = $tsfe->page[$key];
5033  break;
5034  case 'pagelayout':
5035  // Check if the current page has a value in the DB field "backend_layout"
5036  // if empty, check the root line for "backend_layout_next_level"
5037  // same as
5038  // field = backend_layout
5039  // ifEmpty.data = levelfield:-2, backend_layout_next_level, slide
5040  // ifEmpty.ifEmpty = default
5041  $retVal = $tsfe->page['backend_layout'];
5042 
5043  // If it is set to "none" - don't use any
5044  if ($retVal === '-1') {
5045  $retVal = 'none';
5046  } elseif ($retVal === '' || $retVal === '0') {
5047  // If it not set check the root-line for a layout on next level and use this
5048  // Remove first element, which is the current page
5049  // See also \TYPO3\CMS\Backend\View\BackendLayoutView::getSelectedCombinedIdentifier()
5050  $rootLine = $tsfe->rootLine;
5051  array_shift($rootLine);
5052  foreach ($rootLine as $rootLinePage) {
5053  $retVal = (string)$rootLinePage['backend_layout_next_level'];
5054  // If layout for "next level" is set to "none" - don't use any and stop searching
5055  if ($retVal === '-1') {
5056  $retVal = 'none';
5057  break;
5058  }
5059  if ($retVal !== '' && $retVal !== '0') {
5060  // Stop searching if a layout for "next level" is set
5061  break;
5062  }
5063  }
5064  }
5065  if ($retVal === '0' || $retVal === '') {
5066  $retVal = 'default';
5067  }
5068  break;
5069  case 'current':
5070  $retVal = $this->data[‪$this->currentValKey] ?? null;
5071  break;
5072  case 'db':
5073  $selectParts = GeneralUtility::trimExplode(':', $key);
5074  $db_rec = $tsfe->sys_page->getRawRecord($selectParts[0], $selectParts[1]);
5075  if (is_array($db_rec) && $selectParts[2]) {
5076  $retVal = $db_rec[$selectParts[2]];
5077  }
5078  break;
5079  case 'lll':
5080  $retVal = $tsfe->sL('LLL:' . $key);
5081  break;
5082  case 'path':
5083  try {
5084  $retVal = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($key);
5085  } catch (\‪TYPO3\CMS\Core\Resource\Exception $e) {
5086  // do nothing in case the file path is invalid
5087  $retVal = null;
5088  }
5089  break;
5090  case 'cobj':
5091  switch ($key) {
5092  case 'parentRecordNumber':
5093  $retVal = ‪$this->parentRecordNumber;
5094  break;
5095  }
5096  break;
5097  case 'debug':
5098  switch ($key) {
5099  case 'rootLine':
5100  $retVal = ‪DebugUtility::viewArray($tsfe->tmpl->rootLine);
5101  break;
5102  case 'fullRootLine':
5103  $retVal = ‪DebugUtility::viewArray($tsfe->rootLine);
5104  break;
5105  case 'data':
5106  $retVal = ‪DebugUtility::viewArray($this->data);
5107  break;
5108  case 'register':
5109  $retVal = ‪DebugUtility::viewArray($tsfe->register);
5110  break;
5111  case 'page':
5112  $retVal = ‪DebugUtility::viewArray($tsfe->page);
5113  break;
5114  }
5115  break;
5116  case 'flexform':
5117  $keyParts = GeneralUtility::trimExplode(':', $key, true);
5118  if (count($keyParts) === 2 && isset($this->data[$keyParts[0]])) {
5119  $flexFormContent = $this->data[$keyParts[0]];
5120  if (!empty($flexFormContent)) {
5121  $flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
5122  $flexFormKey = str_replace('.', '|', $keyParts[1]);
5123  $settings = $flexFormService->convertFlexFormContentToArray($flexFormContent);
5124  $retVal = $this->‪getGlobal($flexFormKey, $settings);
5125  }
5126  }
5127  break;
5128  case 'session':
5129  $keyParts = GeneralUtility::trimExplode('|', $key, true);
5130  $sessionKey = array_shift($keyParts);
5131  $retVal = $this->‪getTypoScriptFrontendController()->fe_user->getSessionData($sessionKey);
5132  foreach ($keyParts as $keyPart) {
5133  if (is_object($retVal)) {
5134  $retVal = $retVal->{$keyPart};
5135  } elseif (is_array($retVal)) {
5136  $retVal = $retVal[$keyPart];
5137  } else {
5138  $retVal = '';
5139  break;
5140  }
5141  }
5142  if (!is_scalar($retVal)) {
5143  $retVal = '';
5144  }
5145  break;
5146  case 'context':
5147  $context = GeneralUtility::makeInstance(Context::class);
5148  list($aspectName, $propertyName) = GeneralUtility::trimExplode(':', $key, true, 2);
5149  $retVal = $context->getPropertyFromAspect($aspectName, $propertyName, '');
5150  if (is_array($retVal)) {
5151  $retVal = implode(',', $retVal);
5152  }
5153  if (!is_scalar($retVal)) {
5154  $retVal = '';
5155  }
5156  break;
5157  case 'site':
5158  $request = ‪$GLOBALS['TYPO3_REQUEST'] ?? null;
5159  $site = $request ? $request->getAttribute('site') : null;
5160  if ($site instanceof Site) {
5161  if ($key === 'identifier') {
5162  $retVal = $site->getIdentifier();
5163  } elseif ($key === 'base') {
5164  $retVal = $site->getBase();
5165  } else {
5166  try {
5167  $retVal = ‪ArrayUtility::getValueByPath($site->getConfiguration(), $key, '.');
5168  } catch (MissingArrayPathException $exception) {
5169  $this->logger->warning(sprintf('getData() with "%s" failed', $key), ['exception' => $exception]);
5170  }
5171  }
5172  }
5173  break;
5174  case 'sitelanguage':
5175  $request = ‪$GLOBALS['TYPO3_REQUEST'] ?? null;
5176  $siteLanguage = $request ? $request->getAttribute('language') : null;
5177  if ($siteLanguage instanceof SiteLanguage) {
5178  $config = $siteLanguage->toArray();
5179  if (isset($config[$key])) {
5180  $retVal = $config[$key];
5181  }
5182  }
5183  break;
5184  }
5185  }
5186 
5187  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'] ?? [] as $className) {
5188  $hookObject = GeneralUtility::makeInstance($className);
5189  if (!$hookObject instanceof ContentObjectGetDataHookInterface) {
5190  throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetDataHookInterface::class, 1195044480);
5191  }
5192  $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $this);
5193  }
5194  }
5195  return $retVal;
5196  }
5197 
5207  protected function getFileDataKey($key)
5208  {
5209  list($fileUidOrCurrentKeyword, $requestedFileInformationKey) = explode(':', $key, 3);
5210  try {
5211  if ($fileUidOrCurrentKeyword === 'current') {
5212  $fileObject = $this->getCurrentFile();
5213  } elseif (‪MathUtility::canBeInterpretedAsInteger($fileUidOrCurrentKeyword)) {
5215  $fileFactory = GeneralUtility::makeInstance(ResourceFactory::class);
5216  $fileObject = $fileFactory->getFileObject($fileUidOrCurrentKeyword);
5217  } else {
5218  $fileObject = null;
5219  }
5220  } catch (Exception $exception) {
5221  $this->logger->warning('The file "' . $fileUidOrCurrentKeyword . '" could not be found and won\'t be included in frontend output', ['exception' => $exception]);
5222  $fileObject = null;
5223  }
5224 
5225  if ($fileObject instanceof FileInterface) {
5226  // All properties of the \TYPO3\CMS\Core\Resource\FileInterface are available here:
5227  switch ($requestedFileInformationKey) {
5228  case 'name':
5229  return $fileObject->getName();
5230  case 'uid':
5231  if (method_exists($fileObject, 'getUid')) {
5232  return $fileObject->getUid();
5233  }
5234  return 0;
5235  case 'originalUid':
5236  if ($fileObject instanceof FileReference) {
5237  return $fileObject->getOriginalFile()->getUid();
5238  }
5239  return null;
5240  case 'size':
5241  return $fileObject->getSize();
5242  case 'sha1':
5243  return $fileObject->getSha1();
5244  case 'extension':
5245  return $fileObject->getExtension();
5246  case 'mimetype':
5247  return $fileObject->getMimeType();
5248  case 'contents':
5249  return $fileObject->getContents();
5250  case 'publicUrl':
5251  return $fileObject->getPublicUrl();
5252  default:
5253  // Generic alternative here
5254  return $fileObject->getProperty($requestedFileInformationKey);
5255  }
5256  } else {
5257  // @todo fail silently as is common in tslib_content
5258  return 'Error: no file object';
5259  }
5260  }
5261 
5273  public function rootLineValue($key, $field, $slideBack = false, $altRootLine = '')
5274  {
5275  $rootLine = is_array($altRootLine) ? $altRootLine : $this->getTypoScriptFrontendController()->tmpl->rootLine;
5276  if (!$slideBack) {
5277  return $rootLine[$key][$field];
5278  }
5279  for ($a = $key; $a >= 0; $a--) {
5280  $val = $rootLine[$a][$field];
5281  if ($val) {
5282  return $val;
5283  }
5284  }
5285 
5286  return '';
5287  }
5288 
5298  public function getGlobal($keyString, $source = null)
5299  {
5300  $keys = explode('|', $keyString);
5301  $numberOfLevels = count($keys);
5302  $rootKey = trim($keys[0]);
5303  $value = isset($source) ? $source[$rootKey] : ‪$GLOBALS[$rootKey];
5304  for ($i = 1; $i < $numberOfLevels && isset($value); $i++) {
5305  $currentKey = trim($keys[$i]);
5306  if (is_object($value)) {
5307  $value = $value->{$currentKey};
5308  } elseif (is_array($value)) {
5309  $value = $value[$currentKey];
5310  } else {
5311  $value = '';
5312  break;
5313  }
5314  }
5315  if (!is_scalar($value)) {
5316  $value = '';
5317  }
5318  return $value;
5319  }
5320 
5331  public function getKey($key, $arr)
5332  {
5333  $key = (int)$key;
5334  if (is_array($arr)) {
5335  if ($key < 0) {
5336  $key = count($arr) + $key;
5337  }
5338  if ($key < 0) {
5339  $key = 0;
5340  }
5341  }
5342  return $key;
5343  }
5344 
5345  /***********************************************
5346  *
5347  * Link functions (typolink)
5348  *
5349  ***********************************************/
5350 
5365  protected function resolveMixedLinkParameter($linkText, $mixedLinkParameter, &$configuration = [])
5366  {
5367  $linkParameter = null;
5368 
5369  // Link parameter value = first part
5370  $linkParameterParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($mixedLinkParameter);
5371 
5372  // Check for link-handler keyword
5373  $linkHandlerExploded = explode(':', $linkParameterParts['url'], 2);
5374  $linkHandlerKeyword = $linkHandlerExploded[0] ?? null;
5375  $linkHandlerValue = $linkHandlerExploded[1] ?? null;
5376  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword])
5377  && (string)$linkHandlerValue !== ''
5378  ) {
5379  $linkHandlerObj = GeneralUtility::makeInstance(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]);
5380  if (method_exists($linkHandlerObj, 'main')) {
5381  return $linkHandlerObj->main($linkText, $configuration, $linkHandlerKeyword, $linkHandlerValue, $mixedLinkParameter, $this);
5382  }
5383  }
5384 
5385  if (in_array(strtolower(preg_replace('#\s|[[:cntrl:]]#', '', $linkHandlerKeyword)), ['javascript', 'data'], true)) {
5386  // Disallow insecure scheme's like javascript: or data:
5387  return $linkText;
5388  }
5389  $linkParameter = $linkParameterParts['url'];
5390 
5391  // additional parameters that need to be set
5392  if ($linkParameterParts['additionalParams'] !== '') {
5393  $forceParams = $linkParameterParts['additionalParams'];
5394  // params value
5395  $configuration['additionalParams'] .= $forceParams[0] === '&' ? $forceParams : '&' . $forceParams;
5396  }
5397 
5398  return [
5399  'href' => $linkParameter,
5400  'target' => $linkParameterParts['target'],
5401  'class' => $linkParameterParts['class'],
5402  'title' => $linkParameterParts['title']
5403  ];
5404  }
5405 
5420  public function typoLink($linkText, $conf)
5421  {
5422  $linkText = (string)$linkText;
5423  $tsfe = $this->getTypoScriptFrontendController();
5424 
5425  $linkParameter = trim(
5426  (isset($conf['parameter.']) ?? '')
5427  ? $this->stdWrap($conf['parameter'] ?? '', $conf['parameter.'])
5428  : ($conf['parameter'] ?? '')
5429  );
5430  $this->lastTypoLinkUrl = '';
5431  $this->lastTypoLinkTarget = '';
5432 
5433  $resolvedLinkParameters = $this->resolveMixedLinkParameter($linkText, $linkParameter, $conf);
5434  // check if the link handler hook has resolved the link completely already
5435  if (!is_array($resolvedLinkParameters)) {
5436  return $resolvedLinkParameters;
5437  }
5438  $linkParameter = $resolvedLinkParameters['href'];
5439  $target = $resolvedLinkParameters['target'];
5440  $title = $resolvedLinkParameters['title'];
5441 
5442  if (!$linkParameter) {
5443  return $this->resolveAnchorLink($linkText, $conf ?? []);
5444  }
5445 
5446  // Detecting kind of link and resolve all necessary parameters
5447  $linkService = GeneralUtility::makeInstance(LinkService::class);
5448  try {
5449  $linkDetails = $linkService->resolve($linkParameter);
5450  } catch (Exception\InvalidPathException $exception) {
5451  $this->logger->warning('The link could not be generated', ['exception' => $exception]);
5452  return $linkText;
5453  }
5454 
5455  $linkDetails['typoLinkParameter'] = $linkParameter;
5456  if (isset($linkDetails['type']) && isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['typolinkBuilder'][$linkDetails['type']])) {
5458  $linkBuilder = GeneralUtility::makeInstance(
5459  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['typolinkBuilder'][$linkDetails['type']],
5460  $this,
5461  $tsfe
5462  );
5463  try {
5464  list($this->lastTypoLinkUrl, $linkText, $target) = $linkBuilder->build($linkDetails, $linkText, $target, $conf);
5465  $this->lastTypoLinkTarget = htmlspecialchars($target);
5466  $this->lastTypoLinkLD['target'] = htmlspecialchars($target);
5467  $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
5468  } catch (UnableToLinkException $e) {
5469  $this->logger->debug(sprintf('Unable to link "%s": %s', $e->getLinkText(), $e->getMessage()), ['exception' => $e]);
5470 
5471  // Only return the link text directly
5472  return $e->getLinkText();
5473  }
5474  } elseif (isset($linkDetails['url'])) {
5475  $this->lastTypoLinkUrl = $linkDetails['url'];
5476  $this->lastTypoLinkTarget = htmlspecialchars($target);
5477  $this->lastTypoLinkLD['target'] = htmlspecialchars($target);
5478  $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
5479  } else {
5480  return $linkText;
5481  }
5482 
5483  // We need to backup the URL because ATagParams might call typolink again and change the last URL.
5484  $url = $this->lastTypoLinkUrl;
5485  $finalTagParts = [
5486  'aTagParams' => $this->getATagParams($conf) . $this->extLinkATagParams($this->lastTypoLinkUrl, $linkDetails['type']),
5487  'url' => $url,
5488  'TYPE' => $linkDetails['type']
5489  ];
5490 
5491  // Ensure "href" is not in the list of aTagParams to avoid double tags, usually happens within buggy parseFunc settings
5492  if (!empty($finalTagParts['aTagParams'])) {
5493  $aTagParams = GeneralUtility::get_tag_attributes($finalTagParts['aTagParams'], true);
5494  if (isset($aTagParams['href'])) {
5495  unset($aTagParams['href']);
5496  $finalTagParts['aTagParams'] = GeneralUtility::implodeAttributes($aTagParams, true);
5497  }
5498  }
5499 
5500  // Building the final <a href=".."> tag
5501  $tagAttributes = [];
5502 
5503  // Title attribute
5504  if (empty($title)) {
5505  $title = $conf['title'] ?? '';
5506  if (isset($conf['title.']) && is_array($conf['title.'])) {
5507  $title = $this->stdWrap($title, $conf['title.']);
5508  }
5509  }
5510 
5511  // Check, if the target is coded as a JS open window link:
5512  $JSwindowParts = [];
5513  $JSwindowParams = '';
5514  if ($target && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $target, $JSwindowParts)) {
5515  // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
5516  $JSwindow_tempParamsArr = GeneralUtility::trimExplode(',', strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]), true);
5517  $JSwindow_paramsArr = [];
5518  foreach ($JSwindow_tempParamsArr as $JSv) {
5519  list($JSp, $JSv) = explode('=', $JSv, 2);
5520  $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv;
5521  }
5522  // Add width/height:
5523  $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1];
5524  $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2];
5525  // Imploding into string:
5526  $JSwindowParams = implode(',', $JSwindow_paramsArr);
5527  }
5528 
5529  if (!$JSwindowParams && $linkDetails['type'] === LinkService::TYPE_EMAIL && $tsfe->spamProtectEmailAddresses === 'ascii') {
5530  $tagAttributes['href'] = $finalTagParts['url'];
5531  } else {
5532  $tagAttributes['href'] = htmlspecialchars($finalTagParts['url']);
5533  }
5534  if (!empty($title)) {
5535  $tagAttributes['title'] = htmlspecialchars($title);
5536  }
5537 
5538  // Target attribute
5539  if (!empty($target)) {
5540  $tagAttributes['target'] = htmlspecialchars($target);
5541  } elseif ($JSwindowParams && !in_array($tsfe->xhtmlDoctype, ['xhtml_strict', 'xhtml_11'], true)) {
5542  // Create TARGET-attribute only if the right doctype is used
5543  $tagAttributes['target'] = 'FEopenLink';
5544  }
5545 
5546  if ($JSwindowParams) {
5547  $onClick = 'openPic(' . GeneralUtility::quoteJSvalue($tsfe->baseUrlWrap($finalTagParts['url'])) . ',\'FEopenLink\',' . GeneralUtility::quoteJSvalue($JSwindowParams) . ');return false;';
5548  $tagAttributes['onclick'] = htmlspecialchars($onClick);
5549  $this->getTypoScriptFrontendController()->setJS('openPic');
5550  }
5551 
5552  if (!empty($resolvedLinkParameters['class'])) {
5553  $tagAttributes['class'] = htmlspecialchars($resolvedLinkParameters['class']);
5554  }
5555 
5556  // Prevent trouble with double and missing spaces between attributes and merge params before implode
5557  // (skip decoding HTML entities, since `$tagAttributes` are expected to be encoded already)
5558  $finalTagAttributes = array_merge($tagAttributes, GeneralUtility::get_tag_attributes($finalTagParts['aTagParams']));
5559  $finalAnchorTag = '<a ' . GeneralUtility::implodeAttributes($finalTagAttributes) . '>';
5560 
5561  // kept for backwards-compatibility in hooks
5562  $finalTagParts['targetParams'] = !empty($tagAttributes['target']) ? ' target="' . $tagAttributes['target'] . '"' : '';
5563  $this->lastTypoLinkTarget = $target;
5564 
5565  // Call user function:
5566  if ($conf['userFunc'] ?? false) {
5567  $finalTagParts['TAG'] = $finalAnchorTag;
5568  $finalAnchorTag = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts);
5569  }
5570 
5571  // Hook: Call post processing function for link rendering:
5572  $_params = [
5573  'conf' => &$conf,
5574  'linktxt' => &$linkText,
5575  'finalTag' => &$finalAnchorTag,
5576  'finalTagParts' => &$finalTagParts,
5577  'linkDetails' => &$linkDetails,
5578  'tagAttributes' => &$finalTagAttributes
5579  ];
5580  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] ?? [] as $_funcRef) {
5581  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
5582  }
5583 
5584  // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
5585  if ($conf['returnLast'] ?? false) {
5586  switch ($conf['returnLast']) {
5587  case 'url':
5588  return $this->lastTypoLinkUrl;
5589  case 'target':
5590  return $this->lastTypoLinkTarget;
5591  }
5592  }
5593 
5594  $wrap = isset($conf['wrap.'])
5595  ? $this->stdWrap($conf['wrap'] ?? '', $conf['wrap.'])
5596  : $conf['wrap'] ?? '';
5597 
5598  if ($conf['ATagBeforeWrap'] ?? false) {
5599  return $finalAnchorTag . $this->wrap($linkText, $wrap) . '</a>';
5600  }
5601  return $this->wrap($finalAnchorTag . $linkText . '</a>', $wrap);
5602  }
5611  public function typoLink_URL($conf)
5612  {
5613  $this->typoLink('|', $conf);
5614  return $this->lastTypoLinkUrl;
5615  }
5616 
5630  public function getTypoLink($label, $params, $urlParameters = [], $target = '')
5631  {
5632  $conf = [];
5633  $conf['parameter'] = $params;
5634  if ($target) {
5635  $conf['target'] = $target;
5636  $conf['extTarget'] = $target;
5637  $conf['fileTarget'] = $target;
5638  }
5639  if (is_array($urlParameters)) {
5640  if (!empty($urlParameters)) {
5641  $conf['additionalParams'] .= HttpUtility::buildQueryString($urlParameters, '&');
5642  }
5643  } else {
5644  $conf['additionalParams'] .= $urlParameters;
5645  }
5646  $out = $this->typoLink($label, $conf);
5647  return $out;
5648  }
5649 
5657  public function getUrlToCurrentLocation($addQueryString = true)
5658  {
5659  $conf = [];
5660  $conf['parameter'] = $this->getTypoScriptFrontendController()->id . ',' . $this->getTypoScriptFrontendController()->type;
5661  if ($addQueryString) {
5662  $conf['addQueryString'] = '1';
5663  $linkVars = implode(',', array_keys(GeneralUtility::explodeUrl2Array($this->getTypoScriptFrontendController()->linkVars)));
5664  $conf['addQueryString.'] = [
5665  'method' => 'GET',
5666  'exclude' => 'id,type,cHash' . ($linkVars ? ',' . $linkVars : '')
5667  ];
5668  $conf['useCacheHash'] = GeneralUtility::_GET('cHash') ? '1' : '0';
5669  }
5671  return $this->typoLink_URL($conf);
5672  }
5673 
5683  public function getTypoLink_URL($params, $urlParameters = [], $target = '')
5684  {
5685  $this->getTypoLink('', $params, $urlParameters, $target);
5686  return $this->lastTypoLinkUrl;
5687  }
5688 
5697  public function typolinkWrap($conf)
5698  {
5699  trigger_error('ContentObjectRenderer->typolinkWrap() will be removed in TYPO3 v10.0. Use $cObj->typoLink() instead.', E_USER_DEPRECATED);
5700  $k = md5(microtime());
5701  return explode($k, $this->typoLink($k, $conf));
5702  }
5703 
5713  public function currentPageUrl($urlParameters = [], $id = 0)
5714  {
5715  trigger_error('ContentObjectRenderer->currentPageUrl() will be removed in TYPO3 v10.0. Use $cObj->getTypoLink_URL() instead.', E_USER_DEPRECATED);
5716  $tsfe = $this->getTypoScriptFrontendController();
5717  return $this->getTypoLink_URL($id ?: $tsfe->id, $urlParameters, $tsfe->sPre);
5718  }
5719 
5729  protected function processUrl($context, $url, $typolinkConfiguration = [])
5730  {
5731  $urlProcessors = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['urlProcessing']['urlProcessors'] ?? [];
5732  if (empty($urlProcessors)) {
5733  return $url;
5734  }
5735 
5736  foreach ($urlProcessors as $identifier => $configuration) {
5737  if (empty($configuration) || !is_array($configuration)) {
5738  throw new \RuntimeException('Missing configuration for URI processor "' . $identifier . '".', 1442050529);
5739  }
5740  if (!is_string($configuration['processor']) || empty($configuration['processor']) || !class_exists($configuration['processor']) || !is_subclass_of($configuration['processor'], UrlProcessorInterface::class)) {
5741  throw new \RuntimeException('The URI processor "' . $identifier . '" defines an invalid provider. Ensure the class exists and implements the "' . UrlProcessorInterface::class . '".', 1442050579);
5742  }
5743  }
5744 
5745  $orderedProcessors = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($urlProcessors);
5746  $keepProcessing = true;
5747 
5748  foreach ($orderedProcessors as $configuration) {
5750  $urlProcessor = GeneralUtility::makeInstance($configuration['processor']);
5751  $url = $urlProcessor->process($context, $url, $typolinkConfiguration, $this, $keepProcessing);
5752  if (!$keepProcessing) {
5753  break;
5754  }
5755  }
5756 
5757  return $url;
5758  }
5759 
5769  public function getMailTo($mailAddress, $linktxt)
5770  {
5771  $mailAddress = (string)$mailAddress;
5772  if ((string)$linktxt === '') {
5773  $linktxt = htmlspecialchars($mailAddress);
5774  }
5775 
5776  $originalMailToUrl = 'mailto:' . $mailAddress;
5777  $mailToUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_MAIL, $originalMailToUrl);
5778 
5779  // no processing happened, therefore, the default processing kicks in
5780  if ($mailToUrl === $originalMailToUrl) {
5781  $tsfe = $this->getTypoScriptFrontendController();
5782  if ($tsfe->spamProtectEmailAddresses) {
5783  $mailToUrl = $this->encryptEmail($mailToUrl, $tsfe->spamProtectEmailAddresses);
5784  if ($tsfe->spamProtectEmailAddresses !== 'ascii') {
5785  $encodedForJsAndHref = rawurlencode(GeneralUtility::quoteJSvalue($mailToUrl));
5786  $mailToUrl = 'javascript:linkTo_UnCryptMailto(' . $encodedForJsAndHref . ');';
5787  }
5788  $atLabel = trim($tsfe->config['config']['spamProtectEmailAddresses_atSubst']) ?: '(at)';
5789  $spamProtectedMailAddress = str_replace('@', $atLabel, htmlspecialchars($mailAddress));
5790  if ($tsfe->config['config']['spamProtectEmailAddresses_lastDotSubst']) {
5791  $lastDotLabel = trim($tsfe->config['config']['spamProtectEmailAddresses_lastDotSubst']);
5792  $lastDotLabel = $lastDotLabel ? $lastDotLabel : '(dot)';
5793  $spamProtectedMailAddress = preg_replace('/\\.([^\\.]+)$/', $lastDotLabel . '$1', $spamProtectedMailAddress);
5794  }
5795  $linktxt = str_ireplace($mailAddress, $spamProtectedMailAddress, $linktxt);
5796  }
5797  }
5798 
5799  return [$mailToUrl, $linktxt];
5800  }
5801 
5809  protected function encryptEmail(string $string, $type): string
5810  {
5811  $out = '';
5812  // obfuscates using the decimal HTML entity references for each character
5813  if ($type === 'ascii') {
5814  foreach (preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY) as $char) {
5815  $out .= '&#' . mb_ord($char) . ';';
5816  }
5817  } else {
5818  // like str_rot13() but with a variable offset and a wider character range
5819  $len = strlen($string);
5820  $offset = (int)$type;
5821  for ($i = 0; $i < $len; $i++) {
5822  $charValue = ord($string[$i]);
5823  // 0-9 . , - + / :
5824  if ($charValue >= 43 && $charValue <= 58) {
5825  $out .= $this->encryptCharcode($charValue, 43, 58, $offset);
5826  } elseif ($charValue >= 64 && $charValue <= 90) {
5827  // A-Z @
5828  $out .= $this->encryptCharcode($charValue, 64, 90, $offset);
5829  } elseif ($charValue >= 97 && $charValue <= 122) {
5830  // a-z
5831  $out .= $this->encryptCharcode($charValue, 97, 122, $offset);
5832  } else {
5833  $out .= $string[$i];
5834  }
5835  }
5836  }
5837  return $out;
5838  }
5839 
5847  protected function decryptEmail(string $string, $type): string
5848  {
5849  $out = '';
5850  // obfuscates using the decimal HTML entity references for each character
5851  if ($type === 'ascii') {
5852  foreach (preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY) as $char) {
5853  $out .= '&#' . mb_ord($char) . ';';
5854  }
5855  } else {
5856  // like str_rot13() but with a variable offset and a wider character range
5857  $len = strlen($string);
5858  $offset = (int)$type * -1;
5859  for ($i = 0; $i < $len; $i++) {
5860  $charValue = ord($string[$i]);
5861  // 0-9 . , - + / :
5862  if ($charValue >= 43 && $charValue <= 58) {
5863  $out .= $this->encryptCharcode($charValue, 43, 58, $offset);
5864  } elseif ($charValue >= 64 && $charValue <= 90) {
5865  // A-Z @
5866  $out .= $this->encryptCharcode($charValue, 64, 90, $offset);
5867  } elseif ($charValue >= 97 && $charValue <= 122) {
5868  // a-z
5869  $out .= $this->encryptCharcode($charValue, 97, 122, $offset);
5870  } else {
5871  $out .= $string[$i];
5872  }
5873  }
5874  }
5875  return $out;
5876  }
5877 
5888  protected function encryptCharcode($n, $start, $end, $offset)
5889  {
5890  $n = $n + $offset;
5891  if ($offset > 0 && $n > $end) {
5892  $n = $start + ($n - $end - 1);
5893  } elseif ($offset < 0 && $n < $start) {
5894  $n = $end - ($start - $n - 1);
5895  }
5896  return chr($n);
5897  }
5898 
5908  public function getQueryArguments($conf, $overruleQueryArguments = [], $forceOverruleArguments = false)
5909  {
5910  $method = (string)($conf['method'] ?? '');
5911  switch ($method) {
5912  case 'GET':
5913  $currentQueryArray = GeneralUtility::_GET();
5914  break;
5915  case 'POST':
5916  $currentQueryArray = GeneralUtility::_POST();
5917  break;
5918  case 'GET,POST':
5919  $currentQueryArray = GeneralUtility::_GET();
5920  ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_POST());
5921  break;
5922  case 'POST,GET':
5923  $currentQueryArray = GeneralUtility::_POST();
5924  ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_GET());
5925  break;
5926  default:
5927  $currentQueryArray = [];
5928  parse_str($this->getEnvironmentVariable('QUERY_STRING'), $currentQueryArray);
5929  }
5930  if ($conf['exclude'] ?? false) {
5931  $excludeString = str_replace(',', '&', $conf['exclude']);
5932  $excludedQueryParts = [];
5933  parse_str($excludeString, $excludedQueryParts);
5934  // never repeat id
5935  $exclude['id'] = 0;
5936  $newQueryArray = ArrayUtility::arrayDiffAssocRecursive($currentQueryArray, $excludedQueryParts);
5937  } else {
5938  $newQueryArray = $currentQueryArray;
5939  }
5940  ArrayUtility::mergeRecursiveWithOverrule($newQueryArray, $overruleQueryArguments, $forceOverruleArguments);
5941  return HttpUtility::buildQueryString($newQueryArray, '&');
5942  }
5943 
5944  /***********************************************
5945  *
5946  * Miscellaneous functions, stand alone
5947  *
5948  ***********************************************/
5960  public function wrap($content, $wrap, $char = '|')
5961  {
5962  if ($wrap) {
5963  $wrapArr = explode($char, $wrap);
5964  $content = trim($wrapArr[0] ?? '') . $content . trim($wrapArr[1] ?? '');
5965  }
5966  return $content;
5967  }
5968 
5979  public function noTrimWrap($content, $wrap, $char = '|')
5980  {
5981  if ($wrap) {
5982  // expects to be wrapped with (at least) 3 characters (before, middle, after)
5983  // anything else is not taken into account
5984  $wrapArr = explode($char, $wrap, 4);
5985  $content = $wrapArr[1] . $content . $wrapArr[2];
5986  }
5987  return $content;
5988  }
5989 
6000  public function callUserFunction($funcName, $conf, $content)
6001  {
6002  // Split parts
6003  $parts = explode('->', $funcName);
6004  if (count($parts) === 2) {
6005  // Check whether PHP class is available
6006  if (class_exists($parts[0])) {
6007  $classObj = GeneralUtility::makeInstance($parts[0]);
6008  if (is_object($classObj) && method_exists($classObj, $parts[1])) {
6009  $classObj->cObj = $this;
6010  $content = call_user_func_array([
6011  $classObj,
6012  $parts[1]
6013  ], [
6014  $content,
6015  $conf
6016  ]);
6017  } else {
6018  $this->getTimeTracker()->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', 3);
6019  }
6020  } else {
6021  $this->getTimeTracker()->setTSlogMessage('Class "' . $parts[0] . '" did not exist', 3);
6022  }
6023  } elseif (function_exists($funcName)) {
6024  $content = call_user_func($funcName, $content, $conf);
6025  } else {
6026  $this->getTimeTracker()->setTSlogMessage('Function "' . $funcName . '" did not exist', 3);
6027  }
6028  return $content;
6029  }
6030 
6037  public function keywords($content)
6038  {
6039  $listArr = preg_split('/[,;' . LF . ']/', $content);
6040  foreach ($listArr as $k => $v) {
6041  $listArr[$k] = trim($v);
6042  }
6043  return implode(',', $listArr);
6044  }
6045 
6054  public function caseshift($theValue, $case)
6055  {
6056  switch (strtolower($case)) {
6057  case 'upper':
6058  $theValue = mb_strtoupper($theValue, 'utf-8');
6059  break;
6060  case 'lower':
6061  $theValue = mb_strtolower($theValue, 'utf-8');
6062  break;
6063  case 'capitalize':
6064  $theValue = mb_convert_case($theValue, MB_CASE_TITLE, 'utf-8');
6065  break;
6066  case 'ucfirst':
6067  $firstChar = mb_substr($theValue, 0, 1, 'utf-8');
6068  $firstChar = mb_strtoupper($firstChar, 'utf-8');
6069  $remainder = mb_substr($theValue, 1, null, 'utf-8');
6070  $theValue = $firstChar . $remainder;
6071  break;
6072  case 'lcfirst':
6073  $firstChar = mb_substr($theValue, 0, 1, 'utf-8');
6074  $firstChar = mb_strtolower($firstChar, 'utf-8');
6075  $remainder = mb_substr($theValue, 1, null, 'utf-8');
6076  $theValue = $firstChar . $remainder;
6077  break;
6078  case 'uppercamelcase':
6079  $theValue = GeneralUtility::underscoredToUpperCamelCase($theValue);
6080  break;
6081  case 'lowercamelcase':
6082  $theValue = GeneralUtility::underscoredToLowerCamelCase($theValue);
6083  break;
6084  }
6085  return $theValue;
6086  }
6087 
6096  public function HTMLcaseshift($theValue, $case)
6097  {
6098  $inside = 0;
6099  $newVal = '';
6100  $pointer = 0;
6101  $totalLen = strlen($theValue);
6102  do {
6103  if (!$inside) {
6104  $len = strcspn(substr($theValue, $pointer), '<');
6105  $newVal .= $this->caseshift(substr($theValue, $pointer, $len), $case);
6106  $inside = 1;
6107  } else {
6108  $len = strcspn(substr($theValue, $pointer), '>') + 1;
6109  $newVal .= substr($theValue, $pointer, $len);
6110  $inside = 0;
6111  }
6112  $pointer += $len;
6113  } while ($pointer < $totalLen);
6114  return $newVal;
6115  }
6116 
6124  public function calcAge($seconds, $labels)
6125  {
6126  if (MathUtility::canBeInterpretedAsInteger($labels)) {
6127  $labels = ' min| hrs| days| yrs| min| hour| day| year';
6128  } else {
6129  $labels = str_replace('"', '', $labels);
6130  }
6131  $labelArr = explode('|', $labels);
6132  if (count($labelArr) === 4) {
6133  $labelArr = array_merge($labelArr, $labelArr);
6134  }
6135  $absSeconds = abs($seconds);
6136  $sign = $seconds > 0 ? 1 : -1;
6137  if ($absSeconds < 3600) {
6138  $val = round($absSeconds / 60);
6139  $seconds = $sign * $val . ($val == 1 ? $labelArr[4] : $labelArr[0]);
6140  } elseif ($absSeconds < 24 * 3600) {
6141  $val = round($absSeconds / 3600);
6142  $seconds = $sign * $val . ($val == 1 ? $labelArr[5] : $labelArr[1]);
6143  } elseif ($absSeconds < 365 * 24 * 3600) {
6144  $val = round($absSeconds / (24 * 3600));
6145  $seconds = $sign * $val . ($val == 1 ? $labelArr[6] : $labelArr[2]);
6146  } else {
6147  $val = round($absSeconds / (365 * 24 * 3600));
6148  $seconds = $sign * $val . ($val == 1 ? ($labelArr[7] ?? null) : ($labelArr[3] ?? null));
6149  }
6150  return $seconds;
6151  }
6152 
6164  public function sendNotifyEmail($message, $recipients, $cc, $senderAddress, $senderName = '', $replyTo = '')
6165  {
6167  $mail = GeneralUtility::makeInstance(MailMessage::class);
6168  $senderName = trim($senderName);
6169  $senderAddress = trim($senderAddress);
6170  if ($senderName !== '' && $senderAddress !== '') {
6171  $mail->setFrom([$senderAddress => $senderName]);
6172  } elseif ($senderAddress !== '') {
6173  $mail->setFrom([$senderAddress]);
6174  }
6175  $parsedReplyTo = MailUtility::parseAddresses($replyTo);
6176  if (!empty($parsedReplyTo)) {
6177  $mail->setReplyTo($parsedReplyTo);
6178  }
6179  $message = trim($message);
6180  if ($message !== '') {
6181  // First line is subject
6182  $messageParts = explode(LF, $message, 2);
6183  $subject = trim($messageParts[0]);
6184  $plainMessage = trim($messageParts[1]);
6185  $parsedRecipients = MailUtility::parseAddresses($recipients);
6186  if (!empty($parsedRecipients)) {
6187  $mail->setTo($parsedRecipients)
6188  ->setSubject($subject)
6189  ->setBody($plainMessage);
6190  $mail->send();
6191  }
6192  $parsedCc = MailUtility::parseAddresses($cc);
6193  if (!empty($parsedCc)) {
6194  $from = $mail->getFrom();
6196  $mail = GeneralUtility::makeInstance(MailMessage::class);
6197  if (!empty($parsedReplyTo)) {
6198  $mail->setReplyTo($parsedReplyTo);
6199  }
6200  $mail->setFrom($from)
6201  ->setTo($parsedCc)
6202  ->setSubject($subject)
6203  ->setBody($plainMessage);
6204  $mail->send();
6205  }
6206  return true;
6207  }
6208  return false;
6209  }
6210 
6219  public function mergeTSRef($confArr, $prop)
6220  {
6221  if ($confArr[$prop][0] === '<') {
6222  $key = trim(substr($confArr[$prop], 1));
6223  $cF = GeneralUtility::makeInstance(TypoScriptParser::class);
6224  // $name and $conf is loaded with the referenced values.
6225  $old_conf = $confArr[$prop . '.'];
6226  list(, $conf) = $cF->getVal($key, $this->getTypoScriptFrontendController()->tmpl->setup);
6227  if (is_array($old_conf) && !empty($old_conf)) {
6228  $conf = is_array($conf) ? array_replace_recursive($conf, $old_conf) : $old_conf;
6229  }
6230  $confArr[$prop . '.'] = $conf;
6231  }
6232  return $confArr;
6233  }
6234 
6235  /***********************************************
6236  *
6237  * Database functions, making of queries
6238  *
6239  ***********************************************/
6240 
6257  public function enableFields($table, $show_hidden = false, array $ignore_array = [])
6258  {
6259  trigger_error('cObj->enableFields() will be removed in TYPO3 v10.0. should be used from the PageRepository->enableFields() functionality directly.', E_USER_DEPRECATED);
6260  return $this->getTypoScriptFrontendController()->sys_page->enableFields($table, $show_hidden ? true : -1, $ignore_array);
6261  }
6289  public function getTreeList($id, $depth, $begin = 0, $dontCheckEnableFields = false, $addSelectFields = '', $moreWhereClauses = '', array $prevId_array = [], $recursionLevel = 0)
6290  {
6291  $id = (int)$id;
6292  if (!$id) {
6293  return '';
6294  }
6295 
6296  // Init vars:
6297  $allFields = 'uid,hidden,starttime,endtime,fe_group,extendToSubpages,doktype,php_tree_stop,mount_pid,mount_pid_ol,t3ver_state' . $addSelectFields;
6298  $depth = (int)$depth;
6299  $begin = (int)$begin;
6300  $theList = [];
6301  $addId = 0;
6302  $requestHash = '';
6303 
6304  // First level, check id (second level, this is done BEFORE the recursive call)
6305  $tsfe = $this->getTypoScriptFrontendController();
6306  if (!$recursionLevel) {
6307  // Check tree list cache
6308  // First, create the hash for this request - not sure yet whether we need all these parameters though
6309  $parameters = [
6310  $id,
6311  $depth,
6312  $begin,
6313  $dontCheckEnableFields,
6314  $addSelectFields,
6315  $moreWhereClauses,
6316  $prevId_array,
6317  GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('frontend.user', 'groupIds', [0, -1])
6318  ];
6319  $requestHash = md5(serialize($parameters));
6320  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
6321  ->getQueryBuilderForTable('cache_treelist');
6322  $cacheEntry = $queryBuilder->select('treelist')
6323  ->from('cache_treelist')
6324  ->where(
6325  $queryBuilder->expr()->eq(
6326  'md5hash',
6327  $queryBuilder->createNamedParameter($requestHash, \PDO::PARAM_STR)
6328  ),
6329  $queryBuilder->expr()->orX(
6330  $queryBuilder->expr()->gt(
6331  'expires',
6332  $queryBuilder->createNamedParameter(‪$GLOBALS['EXEC_TIME'], \PDO::PARAM_INT)
6333  ),
6334  $queryBuilder->expr()->eq('expires', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
6335  )
6336  )
6337  ->setMaxResults(1)
6338  ->execute()
6339  ->fetch();
6340 
6341  if (is_array($cacheEntry)) {
6342  // Cache hit
6343  return $cacheEntry['treelist'];
6344  }
6345  // If Id less than zero it means we should add the real id to list:
6346  if ($id < 0) {
6347  $addId = $id = abs($id);
6348  }
6349  // Check start page:
6350  if ($tsfe->sys_page->getRawRecord('pages', $id, 'uid')) {
6351  // Find mount point if any:
6352  $mount_info = $tsfe->sys_page->getMountPointInfo($id);
6353  if (is_array($mount_info)) {
6354  $id = $mount_info['mount_pid'];
6355  // In Overlay mode, use the mounted page uid as added ID!:
6356  if ($addId && $mount_info['overlay']) {
6357  $addId = $id;
6358  }
6359  }
6360  } else {
6361  // Return blank if the start page was NOT found at all!
6362  return '';
6363  }
6364  }
6365  // Add this ID to the array of IDs
6366  if ($begin <= 0) {
6367  $prevId_array[] = $id;
6368  }
6369  // Select sublevel:
6370  if ($depth > 0) {
6371  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
6372  $queryBuilder->getRestrictions()
6373  ->removeAll()
6374  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
6375  $queryBuilder->select(...GeneralUtility::trimExplode(',', $allFields, true))
6376  ->from('pages')
6377  ->where(
6378  $queryBuilder->expr()->eq(
6379  'pid',
6380  $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
6381  ),
6382  // tree is only built by language=0 pages
6383  $queryBuilder->expr()->eq('sys_language_uid', 0)
6384  )
6385  ->orderBy('sorting');
6386 
6387  if (!empty($moreWhereClauses)) {
6388  $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($moreWhereClauses));
6389  }
6390 
6391  $result = $queryBuilder->execute();
6392  while ($row = $result->fetch()) {
6394  $versionState = VersionState::cast($row['t3ver_state']);
6395  $tsfe->sys_page->versionOL('pages', $row);
6396  if ((int)$row['doktype'] === PageRepository::DOKTYPE_RECYCLER
6397  || (int)$row['doktype'] === PageRepository::DOKTYPE_BE_USER_SECTION
6398  || $versionState->indicatesPlaceholder()
6399  ) {
6400  // Doing this after the overlay to make sure changes
6401  // in the overlay are respected.
6402  // However, we do not process pages below of and
6403  // including of type recycler and BE user section
6404  continue;
6405  }
6406  // Find mount point if any:
6407  $next_id = $row['uid'];
6408  $mount_info = $tsfe->sys_page->getMountPointInfo($next_id, $row);
6409  // Overlay mode:
6410  if (is_array($mount_info) && $mount_info['overlay']) {
6411  $next_id = $mount_info['mount_pid'];
6412  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
6413  ->getQueryBuilderForTable('pages');
6414  $queryBuilder->getRestrictions()
6415  ->removeAll()
6416  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
6417  $queryBuilder->select(...GeneralUtility::trimExplode(',', $allFields, true))
6418  ->from('pages')
6419  ->where(
6420  $queryBuilder->expr()->eq(
6421  'uid',
6422  $queryBuilder->createNamedParameter($next_id, \PDO::PARAM_INT)
6423  )
6424  )
6425  ->orderBy('sorting')
6426  ->setMaxResults(1);
6427 
6428  if (!empty($moreWhereClauses)) {
6429  $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($moreWhereClauses));
6430  }
6431 
6432  $row = $queryBuilder->execute()->fetch();
6433  $tsfe->sys_page->versionOL('pages', $row);
6434  if ((int)$row['doktype'] === PageRepository::DOKTYPE_RECYCLER
6435  || (int)$row['doktype'] === PageRepository::DOKTYPE_BE_USER_SECTION
6436  || $versionState->indicatesPlaceholder()
6437  ) {
6438  // Doing this after the overlay to make sure
6439  // changes in the overlay are respected.
6440  // see above
6441  continue;
6442  }
6443  }
6444  // Add record:
6445  if ($dontCheckEnableFields || $tsfe->checkPagerecordForIncludeSection($row)) {
6446  // Add ID to list:
6447  if ($begin <= 0) {
6448  if ($dontCheckEnableFields || $tsfe->checkEnableFields($row)) {
6449  $theList[] = $next_id;
6450  }
6451  }
6452  // Next level:
6453  if ($depth > 1 && !$row['php_tree_stop']) {
6454  // Normal mode:
6455  if (is_array($mount_info) && !$mount_info['overlay']) {
6456  $next_id = $mount_info['mount_pid'];
6457  }
6458  // Call recursively, if the id is not in prevID_array:
6459  if (!in_array($next_id, $prevId_array)) {
6460  $theList = array_merge(
6461  GeneralUtility::intExplode(
6462  ',',
6463  $this->getTreeList(
6464  $next_id,
6465  $depth - 1,
6466  $begin - 1,
6467  $dontCheckEnableFields,
6468  $addSelectFields,
6469  $moreWhereClauses,
6470  $prevId_array,
6471  $recursionLevel + 1
6472  ),
6473  true
6474  ),
6475  $theList
6476  );
6477  }
6478  }
6479  }
6480  }
6481  }
6482  // If first run, check if the ID should be returned:
6483  if (!$recursionLevel) {
6484  if ($addId) {
6485  if ($begin > 0) {
6486  $theList[] = 0;
6487  } else {
6488  $theList[] = $addId;
6489  }
6490  }
6491 
6492  $cacheEntry = [
6493  'md5hash' => $requestHash,
6494  'pid' => $id,
6495  'treelist' => implode(',', $theList),
6496  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
6497  ];
6498 
6499  // Only add to cache if not logged into TYPO3 Backend
6500  if (!$this->getFrontendBackendUser() instanceof ‪AbstractUserAuthentication) {
6501  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('cache_treelist');
6502  try {
6503  $connection->transactional(function ($connection) use ($cacheEntry) {
6504  $connection->insert('cache_treelist', $cacheEntry);
6505  });
6506  } catch (\Throwable $e) {
6507  }
6508  }
6509  }
6510 
6511  return implode(',', $theList);
6512  }
6513 
6523  public function searchWhere($searchWords, $searchFieldList, $searchTable)
6524  {
6525  if (!$searchWords) {
6526  return '';
6527  }
6528 
6529  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
6530  ->getQueryBuilderForTable($searchTable);
6531 
6532  $prefixTableName = $searchTable ? $searchTable . '.' : '';
6533 
6534  $where = $queryBuilder->expr()->andX();
6535  $searchFields = explode(',', $searchFieldList);
6536  $searchWords = preg_split('/[ ,]/', $searchWords);
6537  foreach ($searchWords as $searchWord) {
6538  $searchWord = trim($searchWord);
6539  if (strlen($searchWord) < 3) {
6540  continue;
6541  }
6542  $searchWordConstraint = $queryBuilder->expr()->orX();
6543  $searchWord = $queryBuilder->escapeLikeWildcards($searchWord);
6544  foreach ($searchFields as $field) {
6545  $searchWordConstraint->add(
6546  $queryBuilder->expr()->like($prefixTableName . $field, $queryBuilder->quote('%' . $searchWord . '%'))
6547  );
6548  }
6549 
6550  if ($searchWordConstraint->count()) {
6551  $where->add($searchWordConstraint);
6552  }
6553  }
6554 
6555  if ((string)$where === '') {
6556  return '';
6557  }
6558 
6559  return ' AND (' . (string)$where . ')';
6560  }
6571  public function exec_getQuery($table, $conf)
6572  {
6573  $statement = $this->getQuery($table, $conf);
6574  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
6575 
6576  return $connection->executeQuery($statement);
6577  }
6578 
6588  public function getRecords($tableName, array $queryConfiguration)
6589  {
6590  $records = [];
6591 
6592  $statement = $this->exec_getQuery($tableName, $queryConfiguration);
6593 
6594  $tsfe = $this->getTypoScriptFrontendController();
6595  while ($row = $statement->fetch()) {
6596  // Versioning preview:
6597  $tsfe->sys_page->versionOL($tableName, $row, true);
6598 
6599  // Language overlay:
6600  if (is_array($row)) {
6601  $row = $tsfe->sys_page->getLanguageOverlay($tableName, $row);
6602  }
6603 
6604  // Might be unset in the language overlay
6605  if (is_array($row)) {
6606  $records[] = $row;
6607  }
6608  }
6609 
6610  return $records;
6611  }
6612 
6626  public function getQuery($table, $conf, $returnQueryArray = false)
6627  {
6628  // Resolve stdWrap in these properties first
6629  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
6630  $properties = [
6631  'pidInList',
6632  'uidInList',
6633  'languageField',
6634  'selectFields',
6635  'max',
6636  'begin',
6637  'groupBy',
6638  'orderBy',
6639  'join',
6640  'leftjoin',
6641  'rightjoin',
6642  'recursive',
6643  'where'
6644  ];
6645  foreach ($properties as $property) {
6646  $conf[$property] = trim(
6647  isset($conf[$property . '.'])
6648  ? $this->stdWrap($conf[$property], $conf[$property . '.'])
6649  : $conf[$property]
6650  );
6651  if ($conf[$property] === '') {
6652  unset($conf[$property]);
6653  } elseif (in_array($property, ['languageField', 'selectFields', 'join', 'leftjoin', 'rightjoin', 'where'], true)) {
6654  $conf[$property] = QueryHelper::quoteDatabaseIdentifiers($connection, $conf[$property]);
6655  }
6656  if (isset($conf[$property . '.'])) {
6657  // stdWrapping already done, so remove the sub-array
6658  unset($conf[$property . '.']);
6659  }
6660  }
6661  // Handle PDO-style named parameter markers first
6662  $queryMarkers = $this->getQueryMarkers($table, $conf);
6663  // Replace the markers in the non-stdWrap properties
6664  foreach ($queryMarkers as $marker => $markerValue) {
6665  $properties = [
6666  'uidInList',
6667  'selectFields',
6668  'where',
6669  'max',
6670  'begin',
6671  'groupBy',
6672  'orderBy',
6673  'join',
6674  'leftjoin',
6675  'rightjoin'
6676  ];
6677  foreach ($properties as $property) {
6678  if ($conf[$property]) {
6679  $conf[$property] = str_replace('###' . $marker . '###', $markerValue, $conf[$property]);
6680  }
6681  }
6682  }
6683 
6684  // Construct WHERE clause:
6685  // Handle recursive function for the pidInList
6686  if (isset($conf['recursive'])) {
6687  $conf['recursive'] = (int)$conf['recursive'];
6688  if ($conf['recursive'] > 0) {
6689  $pidList = GeneralUtility::trimExplode(',', $conf['pidInList'], true);
6690  array_walk($pidList, function (&$storagePid) {
6691  if ($storagePid === 'this') {
6692  $storagePid = $this->getTypoScriptFrontendController()->id;
6693  }
6694  if ($storagePid > 0) {
6695  $storagePid = -$storagePid;
6696  }
6697  });
6698  $expandedPidList = [];
6699  foreach ($pidList as $value) {
6700  // Implementation of getTreeList allows to pass the id negative to include
6701  // it into the result otherwise only childpages are returned
6702  $expandedPidList = array_merge(
6703  GeneralUtility::intExplode(',', $this->getTreeList($value, $conf['recursive'])),
6704  $expandedPidList
6705  );
6706  }
6707  $conf['pidInList'] = implode(',', $expandedPidList);
6708  }
6709  }
6710  if ((string)$conf['pidInList'] === '') {
6711  $conf['pidInList'] = 'this';
6712  }
6713 
6714  $queryParts = $this->getQueryConstraints($table, $conf);
6715 
6716  $queryBuilder = $connection->createQueryBuilder();
6717  // @todo Check against getQueryConstraints, can probably use FrontendRestrictions
6718  // @todo here and remove enableFields there.
6719  $queryBuilder->getRestrictions()->removeAll();
6720  $queryBuilder->select('*')->from($table);
6721 
6722  if ($queryParts['where']) {
6723  $queryBuilder->where($queryParts['where']);
6724  }
6725 
6726  if ($queryParts['groupBy']) {
6727  $queryBuilder->groupBy(...$queryParts['groupBy']);
6728  }
6729 
6730  if (is_array($queryParts['orderBy'])) {
6731  foreach ($queryParts['orderBy'] as $orderBy) {
6732  $queryBuilder->addOrderBy(...$orderBy);
6733  }
6734  }
6735 
6736  // Fields:
6737  if ($conf['selectFields']) {
6738  $queryBuilder->selectLiteral($this->sanitizeSelectPart($conf['selectFields'], $table));
6739  }
6740 
6741  // Setting LIMIT:
6742  $error = false;
6743  if ($conf['max'] || $conf['begin']) {
6744  // Finding the total number of records, if used:
6745  if (strpos(strtolower($conf['begin'] . $conf['max']), 'total') !== false) {
6746  $countQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
6747  $countQueryBuilder->getRestrictions()->removeAll();
6748  $countQueryBuilder->count('*')
6749  ->from($table)
6750  ->where($queryParts['where']);
6751 
6752  if ($queryParts['groupBy']) {
6753  $countQueryBuilder->groupBy(...$queryParts['groupBy']);
6754  }
6755 
6756  try {
6757  $count = $countQueryBuilder->execute()->fetchColumn(0);
6758  $conf['max'] = str_ireplace('total', $count, $conf['max']);
6759  $conf['begin'] = str_ireplace('total', $count, $conf['begin']);
6760  } catch (DBALException $e) {
6761  $this->getTimeTracker()->setTSlogMessage($e->getPrevious()->getMessage());
6762  $error = true;
6763  }
6764  }
6765 
6766  if (!$error) {
6767  $conf['begin'] = MathUtility::forceIntegerInRange(ceil($this->calc($conf['begin'])), 0);
6768  $conf['max'] = MathUtility::forceIntegerInRange(ceil($this->calc($conf['max'])), 0);
6769  if ($conf['begin'] > 0) {
6770  $queryBuilder->setFirstResult($conf['begin']);
6771  }
6772  $queryBuilder->setMaxResults($conf['max'] ?: 100000);
6773  }
6774  }
6775 
6776  if (!$error) {
6777  // Setting up tablejoins:
6778  if ($conf['join']) {
6779  $joinParts = QueryHelper::parseJoin($conf['join']);
6780  $queryBuilder->join(
6781  $table,
6782  $joinParts['tableName'],
6783  $joinParts['tableAlias'],
6784  $joinParts['joinCondition']
6785  );
6786  } elseif ($conf['leftjoin']) {
6787  $joinParts = QueryHelper::parseJoin($conf['leftjoin']);
6788  $queryBuilder->leftJoin(
6789  $table,
6790  $joinParts['tableName'],
6791  $joinParts['tableAlias'],
6792  $joinParts['joinCondition']
6793  );
6794  } elseif ($conf['rightjoin']) {
6795  $joinParts = QueryHelper::parseJoin($conf['rightjoin']);
6796  $queryBuilder->rightJoin(
6797  $table,
6798  $joinParts['tableName'],
6799  $joinParts['tableAlias'],
6800  $joinParts['joinCondition']
6801  );
6802  }
6803 
6804  // Convert the QueryBuilder object into a SQL statement.
6805  $query = $queryBuilder->getSQL();
6806 
6807  // Replace the markers in the queryParts to handle stdWrap enabled properties
6808  foreach ($queryMarkers as $marker => $markerValue) {
6809  // @todo Ugly hack that needs to be cleaned up, with the current architecture
6810  // @todo for exec_Query / getQuery it's the best we can do.
6811  $query = str_replace('###' . $marker . '###', $markerValue, $query);
6812  foreach ($queryParts as $queryPartKey => &$queryPartValue) {
6813  $queryPartValue = str_replace('###' . $marker . '###', $markerValue, $queryPartValue);
6814  }
6815  unset($queryPartValue);
6816  }
6817 
6818  return $returnQueryArray ? $this->getQueryArray($queryBuilder) : $query;
6819  }
6820 
6821  return '';
6822  }
6823 
6832  protected function getQueryArray(QueryBuilder $queryBuilder)
6833  {
6834  $fromClauses = [];
6835  $knownAliases = [];
6836  $queryParts = [];
6837 
6838  // Loop through all FROM clauses
6839  foreach ($queryBuilder->getQueryPart('from') as $from) {
6840  if ($from['alias'] === null) {
6841  $tableSql = $from['table'];
6842  $tableReference = $from['table'];
6843  } else {
6844  $tableSql = $from['table'] . ' ' . $from['alias'];
6845  $tableReference = $from['alias'];
6846  }
6847 
6848  $knownAliases[$tableReference] = true;
6849 
6850  $fromClauses[$tableReference] = $tableSql . $this->getQueryArrayJoinHelper(
6851  $tableReference,
6852  $queryBuilder->getQueryPart('join'),
6853  $knownAliases
6854  );
6855  }
6856 
6857  $queryParts['SELECT'] = implode(', ', $queryBuilder->getQueryPart('select'));
6858  $queryParts['FROM'] = implode(', ', $fromClauses);
6859  $queryParts['WHERE'] = (string)$queryBuilder->getQueryPart('where') ?: '';
6860  $queryParts['GROUPBY'] = implode(', ', $queryBuilder->getQueryPart('groupBy'));
6861  $queryParts['ORDERBY'] = implode(', ', $queryBuilder->getQueryPart('orderBy'));
6862  if ($queryBuilder->getFirstResult() > 0) {
6863  $queryParts['LIMIT'] = $queryBuilder->getFirstResult() . ',' . $queryBuilder->getMaxResults();
6864  } elseif ($queryBuilder->getMaxResults() > 0) {
6865  $queryParts['LIMIT'] = $queryBuilder->getMaxResults();
6866  }
6867 
6868  return $queryParts;
6869  }
6870 
6880  protected function getQueryArrayJoinHelper(string $fromAlias, array $joinParts, array &$knownAliases): string
6881  {
6882  $sql = '';
6883 
6884  if (isset($joinParts['join'][$fromAlias])) {
6885  foreach ($joinParts['join'][$fromAlias] as $join) {
6886  if (array_key_exists($join['joinAlias'], $knownAliases)) {
6887  throw new \RuntimeException(
6888  'Non unique join alias: "' . $join['joinAlias'] . '" found.',
6889  1472748872
6890  );
6891  }
6892  $sql .= ' ' . strtoupper($join['joinType'])
6893  . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias']
6894  . ' ON ' . ((string)$join['joinCondition']);
6895  $knownAliases[$join['joinAlias']] = true;
6896  }
6897 
6898  foreach ($joinParts['join'][$fromAlias] as $join) {
6899  $sql .= $this->getQueryArrayJoinHelper($join['joinAlias'], $joinParts, $knownAliases);
6900  }
6901  }
6902 
6903  return $sql;
6904  }
6914  protected function getQueryConstraints(string $table, array $conf): array
6915  {
6916  // Init:
6917  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
6918  $expressionBuilder = $queryBuilder->expr();
6919  $tsfe = $this->getTypoScriptFrontendController();
6920  $constraints = [];
6921  $pid_uid_flag = 0;
6922  $enableFieldsIgnore = [];
6923  $queryParts = [
6924  'where' => null,
6925  'groupBy' => null,
6926  'orderBy' => null,
6927  ];
6928 
6929  $isInWorkspace = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'isOffline');
6930  $considerMovePlaceholders = (
6931  $isInWorkspace && $table !== 'pages'
6932  && !empty(‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
6933  );
6934 
6935  if (trim($conf['uidInList'])) {
6936  $listArr = GeneralUtility::intExplode(',', str_replace('this', $tsfe->contentPid, $conf['uidInList']));
6937 
6938  // If move placeholder shall be considered, select via t3ver_move_id
6939  if ($considerMovePlaceholders) {
6940  $constraints[] = (string)$expressionBuilder->orX(
6941  $expressionBuilder->in($table . '.uid', $listArr),
6942  $expressionBuilder->andX(
6943  $expressionBuilder->eq(
6944  $table . '.t3ver_state',
6945  (int)(string)VersionState::cast(VersionState::MOVE_PLACEHOLDER)
6946  ),
6947  $expressionBuilder->in($table . '.t3ver_move_id', $listArr)
6948  )
6949  );
6950  } else {
6951  $constraints[] = (string)$expressionBuilder->in($table . '.uid', $listArr);
6952  }
6953  $pid_uid_flag++;
6954  }
6955 
6956  // Static_* tables are allowed to be fetched from root page
6957  if (strpos($table, 'static_') === 0) {
6958  $pid_uid_flag++;
6959  }
6960 
6961  if (trim($conf['pidInList'])) {
6962  $listArr = GeneralUtility::intExplode(',', str_replace('this', $tsfe->contentPid, $conf['pidInList']));
6963  // Removes all pages which are not visible for the user!
6964  $listArr = $this->checkPidArray($listArr);
6965  if (GeneralUtility::inList($conf['pidInList'], 'root')) {
6966  $listArr[] = 0;
6967  }
6968  if (GeneralUtility::inList($conf['pidInList'], '-1')) {
6969  $listArr[] = -1;
6970  $enableFieldsIgnore['pid'] = true;
6971  }
6972  if (!empty($listArr)) {
6973  $constraints[] = $expressionBuilder->in($table . '.pid', array_map('intval', $listArr));
6974  $pid_uid_flag++;
6975  } else {
6976  // If not uid and not pid then uid is set to 0 - which results in nothing!!
6977  $pid_uid_flag = 0;
6978  }
6979  }
6980 
6981  // If not uid and not pid then uid is set to 0 - which results in nothing!!
6982  if (!$pid_uid_flag) {
6983  $constraints[] = $expressionBuilder->eq($table . '.uid', 0);
6984  }
6985 
6986  $where = isset($conf['where.']) ? trim($this->stdWrap($conf['where'], $conf['where.'])) : trim($conf['where']);
6987  if ($where) {
6988  $constraints[] = QueryHelper::stripLogicalOperatorPrefix($where);
6989  }
6990 
6991  // Check if the default language should be fetched (= doing overlays), or if only the records of a language should be fetched
6992  // but only do this for TCA tables that have languages enabled
6993  $languageConstraint = $this->getLanguageRestriction($expressionBuilder, $table, $conf, GeneralUtility::makeInstance(Context::class));
6994  if ($languageConstraint !== null) {
6995  $constraints[] = $languageConstraint;
6996  }
6997 
6998  // Enablefields
6999  if ($table === 'pages') {
7000  $constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->where_hid_del);
7001  $constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->where_groupAccess);
7002  } else {
7003  $constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->enableFields($table, -1, $enableFieldsIgnore));
7004  }
7005 
7006  // MAKE WHERE:
7007  if (count($constraints) !== 0) {
7008  $queryParts['where'] = $expressionBuilder->andX(...$constraints);
7009  }
7010  // GROUP BY
7011  if (trim($conf['groupBy'])) {
7012  $groupBy = isset($conf['groupBy.'])
7013  ? trim($this->stdWrap($conf['groupBy'], $conf['groupBy.']))
7014  : trim($conf['groupBy']);
7015  $queryParts['groupBy'] = QueryHelper::parseGroupBy($groupBy);
7016  }
7017 
7018  // ORDER BY
7019  if (trim($conf['orderBy'])) {
7020  $orderByString = isset($conf['orderBy.'])
7021  ? trim($this->stdWrap($conf['orderBy'], $conf['orderBy.']))
7022  : trim($conf['orderBy']);
7023 
7024  $queryParts['orderBy'] = QueryHelper::parseOrderBy($orderByString);
7025  }
7026 
7027  // Return result:
7028  return $queryParts;
7029  }
7057  protected function getLanguageRestriction(‪ExpressionBuilder $expressionBuilder, string $table, array $conf, ‪Context $context)
7058  {
7059  $languageField = '';
7060  $localizationParentField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? null;
7061  // Check if the table is translatable, and set the language field by default from the TCA information
7062  if (!empty($conf['languageField']) || !isset($conf['languageField'])) {
7063  if (isset($conf['languageField']) && !empty(‪$GLOBALS['TCA'][$table]['columns'][$conf['languageField']])) {
7064  $languageField = $conf['languageField'];
7065  } elseif (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['languageField']) && !empty($localizationParentField)) {
7066  $languageField = $table . '.' . ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'];
7067  }
7068  }
7069 
7070  // No language restriction enabled explicitly or available via TCA
7071  if (empty($languageField)) {
7072  return null;
7073  }
7074 
7076  $languageAspect = $context->‪getAspect('language');
7077  if ($languageAspect->doOverlays() && !empty($localizationParentField)) {
7078  // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will
7079  // OVERLAY the records with localized versions!
7080  $languageQuery = $expressionBuilder->‪in($languageField, [0, -1]);
7081  // Use this option to include records that don't have a default language counterpart ("free mode")
7082  // (originalpointerfield is 0 and the language field contains the requested language)
7083  if (isset($conf['includeRecordsWithoutDefaultTranslation']) || $conf['includeRecordsWithoutDefaultTranslation.']) {
7084  $includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.']) ?
7085  $this->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.']) : $conf['includeRecordsWithoutDefaultTranslation'];
7086  $includeRecordsWithoutDefaultTranslation = trim($includeRecordsWithoutDefaultTranslation) !== '';
7087  } else {
7088  // Option was not explicitly set, check what's in for the language overlay type.
7089  $includeRecordsWithoutDefaultTranslation = $languageAspect->getOverlayType() === $languageAspect::OVERLAYS_ON_WITH_FLOATING;
7090  }
7091  if ($includeRecordsWithoutDefaultTranslation) {
7092  $languageQuery = $expressionBuilder->‪orX(
7093  $languageQuery,
7094  $expressionBuilder->‪andX(
7095  $expressionBuilder->‪eq($table . '.' . $localizationParentField, 0),
7096  $expressionBuilder->‪eq($languageField, $languageAspect->getContentId())
7097  )
7098  );
7099  }
7100  return $languageQuery;
7101  }
7102  // No overlays = only fetch records given for the requested language and "all languages"
7103  return $expressionBuilder->‪in($languageField, [$languageAspect->getContentId(), -1]);
7104  }
7105 
7118  protected function sanitizeSelectPart($selectPart, $table)
7119  {
7120  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
7121 
7122  // Pattern matching parts
7123  $matchStart = '/(^\\s*|,\\s*|' . $table . '\\.)';
7124  $matchEnd = '(\\s*,|\\s*$)/';
7125  $necessaryFields = ['uid', 'pid'];
7126  $wsFields = ['t3ver_state'];
7127  if (isset(‪$GLOBALS['TCA'][$table]) && !preg_match($matchStart . '\\*' . $matchEnd, $selectPart) && !preg_match('/(count|max|min|avg|sum)\\([^\\)]+\\)|distinct/i', $selectPart)) {
7128  foreach ($necessaryFields as $field) {
7129  $match = $matchStart . $field . $matchEnd;
7130  if (!preg_match($match, $selectPart)) {
7131  $selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
7132  }
7133  }
7134  if (‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
7135  foreach ($wsFields as $field) {
7136  $match = $matchStart . $field . $matchEnd;
7137  if (!preg_match($match, $selectPart)) {
7138  $selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
7139  }
7140  }
7141  }
7142  }
7143  return $selectPart;
7144  }
7145 
7154  public function checkPidArray($listArr)
7155  {
7156  if (!is_array($listArr) || empty($listArr)) {
7157  return [];
7158  }
7159  $outArr = [];
7160  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
7161  $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
7162  $queryBuilder->select('uid')
7163  ->from('pages')
7164  ->where(
7165  $queryBuilder->expr()->in(
7166  'uid',
7167  $queryBuilder->createNamedParameter($listArr, Connection::PARAM_INT_ARRAY)
7168  ),
7169  $queryBuilder->expr()->notIn(
7170  'doktype',
7171  $queryBuilder->createNamedParameter(
7172  GeneralUtility::intExplode(',', $this->checkPid_badDoktypeList, true),
7173  Connection::PARAM_INT_ARRAY
7174  )
7175  )
7176  );
7177  try {
7178  $result = $queryBuilder->execute();
7179  while ($row = $result->fetch()) {
7180  $outArr[] = $row['uid'];
7181  }
7182  } catch (DBALException $e) {
7183  $this->getTimeTracker()->setTSlogMessage($e->getMessage() . ': ' . $queryBuilder->getSQL(), 3);
7184  }
7185 
7186  return $outArr;
7187  }
7188 
7197  public function checkPid($uid)
7198  {
7199  $uid = (int)$uid;
7200  if (!isset($this->checkPid_cache[$uid])) {
7201  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
7202  $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
7203  $count = $queryBuilder->count('*')
7204  ->from('pages')
7205  ->where(
7206  $queryBuilder->expr()->eq(
7207  'uid',
7208  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
7209  ),
7210  $queryBuilder->expr()->notIn(
7211  'doktype',
7212  $queryBuilder->createNamedParameter(
7213  GeneralUtility::intExplode(',', $this->checkPid_badDoktypeList, true),
7214  Connection::PARAM_INT_ARRAY
7215  )
7216  )
7217  )
7218  ->execute()
7219  ->fetchColumn(0);
7220 
7221  $this->checkPid_cache[$uid] = (bool)$count;
7222  }
7223  return $this->checkPid_cache[$uid];
7224  }
7225 
7236  public function getQueryMarkers($table, $conf)
7237  {
7238  if (!is_array($conf['markers.'])) {
7239  return [];
7240  }
7241  // Parse markers and prepare their values
7242  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
7243  $markerValues = [];
7244  foreach ($conf['markers.'] as $dottedMarker => $dummy) {
7245  $marker = rtrim($dottedMarker, '.');
7246  if ($dottedMarker != $marker . '.') {
7247  continue;
7248  }
7249  // Parse definition
7250  $tempValue = isset($conf['markers.'][$dottedMarker])
7251  ? $this->stdWrap($conf['markers.'][$dottedMarker]['value'], $conf['markers.'][$dottedMarker])
7252  : $conf['markers.'][$dottedMarker]['value'];
7253  // Quote/escape if needed
7254  if (is_numeric($tempValue)) {
7255  if ((int)$tempValue == $tempValue) {
7256  // Handle integer
7257  $markerValues[$marker] = (int)$tempValue;
7258  } else {
7259  // Handle float
7260  $markerValues[$marker] = (float)$tempValue;
7261  }
7262  } elseif ($tempValue === null) {
7263  // It represents NULL
7264  $markerValues[$marker] = 'NULL';
7265  } elseif (!empty($conf['markers.'][$dottedMarker]['commaSeparatedList'])) {
7266  // See if it is really a comma separated list of values
7267  $explodeValues = GeneralUtility::trimExplode(',', $tempValue);
7268  if (count($explodeValues) > 1) {
7269  // Handle each element of list separately
7270  $tempArray = [];
7271  foreach ($explodeValues as $listValue) {
7272  if (is_numeric($listValue)) {
7273  if ((int)$listValue == $listValue) {
7274  $tempArray[] = (int)$listValue;
7275  } else {
7276  $tempArray[] = (float)$listValue;
7277  }
7278  } else {
7279  // If quoted, remove quotes before
7280  // escaping.
7281  if (preg_match('/^\'([^\']*)\'$/', $listValue, $matches)) {
7282  $listValue = $matches[1];
7283  } elseif (preg_match('/^\\"([^\\"]*)\\"$/', $listValue, $matches)) {
7284  $listValue = $matches[1];
7285  }
7286  $tempArray[] = $connection->quote($listValue);
7287  }
7288  }
7289  $markerValues[$marker] = implode(',', $tempArray);
7290  } else {
7291  // Handle remaining values as string
7292  $markerValues[$marker] = $connection->quote($tempValue);
7293  }
7294  } else {
7295  // Handle remaining values as string
7296  $markerValues[$marker] = $connection->quote($tempValue);
7297  }
7298  }
7299  return $markerValues;
7300  }
7301 
7302  /***********************************************
7303  *
7304  * Frontend editing functions
7305  *
7306  ***********************************************/
7318  public function editPanel($content, $conf, $currentRecord = '', $dataArray = [])
7319  {
7320  if (!$this->getTypoScriptFrontendController()->isBackendUserLoggedIn()) {
7321  return $content;
7322  }
7323  if (!$this->getTypoScriptFrontendController()->displayEditIcons) {
7324  return $content;
7325  }
7326 
7327  if (!$currentRecord) {
7328  $currentRecord = $this->currentRecord;
7329  }
7330  if (empty($dataArray)) {
7331  $dataArray = $this->data;
7332  }
7333 
7334  if ($conf['newRecordFromTable']) {
7335  $currentRecord = $conf['newRecordFromTable'] . ':NEW';
7336  $conf['allow'] = 'new';
7337  $checkEditAccessInternals = false;
7338  } else {
7339  $checkEditAccessInternals = true;
7340  }
7341  list($table, $uid) = explode(':', $currentRecord);
7342  // Page ID for new records, 0 if not specified
7343  $newRecordPid = (int)$conf['newRecordInPid'];
7344  $newUid = null;
7345  if (!$conf['onlyCurrentPid'] || $dataArray['pid'] == $this->getTypoScriptFrontendController()->id) {
7346  if ($table === 'pages') {
7347  $newUid = $uid;
7348  } else {
7349  if ($conf['newRecordFromTable']) {
7350  $newUid = $this->getTypoScriptFrontendController()->id;
7351  if ($newRecordPid) {
7352  $newUid = $newRecordPid;
7353  }
7354  } else {
7355  $newUid = -1 * $uid;
7356  }
7357  }
7358  }
7359  if ($table && $this->getFrontendBackendUser()->allowedToEdit($table, $dataArray, $conf, $checkEditAccessInternals) && $this->getFrontendBackendUser()->allowedToEditLanguage($table, $dataArray)) {
7360  $editClass = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['edit'];
7361  if ($editClass) {
7362  $edit = GeneralUtility::makeInstance($editClass);
7363  $allowedActions = $this->getFrontendBackendUser()->getAllowedEditActions($table, $conf, $dataArray['pid']);
7364  $content = $edit->editPanel($content, $conf, $currentRecord, $dataArray, $table, $allowedActions, $newUid, []);
7365  }
7366  }
7367  return $content;
7368  }
7369 
7382  public function editIcons($content, $params, array $conf = [], $currentRecord = '', $dataArray = [], $addUrlParamStr = '')
7383  {
7384  if (!$this->getTypoScriptFrontendController()->isBackendUserLoggedIn()) {
7385  return $content;
7386  }
7387  if (!$this->getTypoScriptFrontendController()->displayFieldEditIcons) {
7388  return $content;
7389  }
7390  if (!$currentRecord) {
7391  $currentRecord = $this->currentRecord;
7392  }
7393  if (empty($dataArray)) {
7394  $dataArray = $this->data;
7395  }
7396  // Check incoming params:
7397  list($currentRecordTable, $currentRecordUID) = explode(':', $currentRecord);
7398  list($fieldList, $table) = array_reverse(GeneralUtility::trimExplode(':', $params, true));
7399  // Reverse the array because table is optional
7400  if (!$table) {
7401  $table = $currentRecordTable;
7402  } elseif ($table != $currentRecordTable) {
7403  // If the table is set as the first parameter, and does not match the table of the current record, then just return.
7404  return $content;
7405  }
7406 
7407  $editUid = $dataArray['_LOCALIZED_UID'] ?: $currentRecordUID;
7408  // Edit icons imply that the editing action is generally allowed, assuming page and content element permissions permit it.
7409  if (!array_key_exists('allow', $conf)) {
7410  $conf['allow'] = 'edit';
7411  }
7412  if ($table && $this->getFrontendBackendUser()->allowedToEdit($table, $dataArray, $conf, true) && $fieldList && $this->getFrontendBackendUser()->allowedToEditLanguage($table, $dataArray)) {
7413  $editClass = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['edit'];
7414  if ($editClass) {
7415  $edit = GeneralUtility::makeInstance($editClass);
7416  $content = $edit->editIcons($content, $params, $conf, $currentRecord, $dataArray, $addUrlParamStr, $table, $editUid, $fieldList);
7417  }
7418  }
7419  return $content;
7420  }
7421 
7431  public function isDisabled($table, $row)
7432  {
7433  $tsfe = $this->getTypoScriptFrontendController();
7434  $enablecolumns = ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
7435  return $enablecolumns['disabled'] && $row[$enablecolumns['disabled']]
7436  || $enablecolumns['fe_group'] && $tsfe->simUserGroup && (int)$row[$enablecolumns['fe_group']] === (int)$tsfe->simUserGroup
7437  || $enablecolumns['starttime'] && $row[$enablecolumns['starttime']] > ‪$GLOBALS['EXEC_TIME']
7438  || $enablecolumns['endtime'] && $row[$enablecolumns['endtime']] && $row[$enablecolumns['endtime']] < ‪$GLOBALS['EXEC_TIME'];
7439  }
7440 
7446  protected function getResourceFactory()
7447  {
7448  return ResourceFactory::getInstance();
7449  }
7450 
7458  protected function getEnvironmentVariable($key)
7459  {
7460  return GeneralUtility::getIndpEnv($key);
7461  }
7462 
7470  protected function getFromCache(array $configuration)
7471  {
7472  $content = false;
7473 
7474  if ($this->getTypoScriptFrontendController()->no_cache) {
7475  return $content;
7476  }
7477  $cacheKey = $this->calculateCacheKey($configuration);
7478  if (!empty($cacheKey)) {
7480  $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)
7481  ->getCache('cache_hash');
7482  $content = $cacheFrontend->get($cacheKey);
7483  }
7484  return $content;
7485  }
7486 
7493  protected function calculateCacheLifetime(array $configuration)
7494  {
7495  $lifetimeConfiguration = $configuration['lifetime'] ?? '';
7496  $lifetimeConfiguration = isset($configuration['lifetime.'])
7497  ? $this->stdWrap($lifetimeConfiguration, $configuration['lifetime.'])
7498  : $lifetimeConfiguration;
7499 
7500  $lifetime = null; // default lifetime
7501  if (strtolower($lifetimeConfiguration) === 'unlimited') {
7502  $lifetime = 0; // unlimited
7503  } elseif ($lifetimeConfiguration > 0) {
7504  $lifetime = (int)$lifetimeConfiguration; // lifetime in seconds
7505  }
7506  return $lifetime;
7507  }
7508 
7515  protected function calculateCacheTags(array $configuration)
7516  {
7517  $tags = $configuration['tags'] ?? '';
7518  $tags = isset($configuration['tags.'])
7519  ? $this->stdWrap($tags, $configuration['tags.'])
7520  : $tags;
7521  return empty($tags) ? [] : GeneralUtility::trimExplode(',', $tags);
7522  }
7523 
7530  protected function calculateCacheKey(array $configuration)
7531  {
7532  $key = $configuration['key'] ?? '';
7533  return isset($configuration['key.'])
7534  ? $this->stdWrap($key, $configuration['key.'])
7535  : $key;
7536  }
7537 
7543  protected function getFrontendBackendUser()
7544  {
7545  return ‪$GLOBALS['BE_USER'];
7546  }
7547 
7551  protected function getTimeTracker()
7552  {
7553  return GeneralUtility::makeInstance(TimeTracker::class);
7554  }
7555 
7559  protected function getTypoScriptFrontendController()
7560  {
7561  return $this->typoScriptFrontendController ?: ‪$GLOBALS['TSFE'];
7562  }
7563 
7573  protected function resolveAnchorLink(string $linkText, array $conf): string
7574  {
7575  $anchorTag = '<a ' . $this->getATagParams($conf) . '>';
7576  $aTagParams = GeneralUtility::get_tag_attributes($anchorTag);
7577  // If it looks like a anchor tag, render it anyway
7578  if (isset($aTagParams['id']) || isset($aTagParams['name'])) {
7579  return $anchorTag . $linkText . '</a>';
7580  }
7581  // Otherwise just return the link text
7582  return $linkText;
7583  }
7584 
7585  protected function shallDebug(): bool
7586  {
7587  $tsfe = $this->getTypoScriptFrontendController();
7588  if ($tsfe !== null && isset($tsfe->config['config']['debug'])) {
7589  return (bool)($tsfe->config['config']['debug']);
7590  }
7591  return !empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['debug']);
7592  }
7593 }
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\getQueryPart
‪mixed getQueryPart(string $queryPartName)
Definition: QueryBuilder.php:823
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_noTrimWrap
‪string stdWrap_noTrimWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2677
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$parentRecordNumber
‪int $parentRecordNumber
Definition: ContentObjectRenderer.php:337
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\http_makelinks
‪string http_makelinks($data, $conf)
Definition: ContentObjectRenderer.php:4534
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_case
‪string stdWrap_case($content='', $conf=[])
Definition: ContentObjectRenderer.php:2354
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_htmlSpecialChars
‪string stdWrap_htmlSpecialChars($content='', $conf=[])
Definition: ContentObjectRenderer.php:2444
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectStdWrapHookInterface
Definition: ContentObjectStdWrapHookInterface.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_editIcons
‪string stdWrap_editIcons($content='', $conf=[])
Definition: ContentObjectRenderer.php:2874
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\__construct
‪__construct(TypoScriptFrontendController $typoScriptFrontendController=null)
Definition: ContentObjectRenderer.php:443
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\shallDebug
‪shallDebug()
Definition: ContentObjectRenderer.php:7558
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setCurrentFile
‪setCurrentFile($fileObject)
Definition: ContentObjectRenderer.php:1511
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_expandList
‪string stdWrap_expandList($content='')
Definition: ContentObjectRenderer.php:2271
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFileDataKey
‪string int getFileDataKey($key)
Definition: ContentObjectRenderer.php:5180
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\OBJECTTYPE_USER
‪const OBJECTTYPE_USER
Definition: ContentObjectRenderer.php:438
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cacheRead
‪string stdWrap_cacheRead($content='', $conf=[])
Definition: ContentObjectRenderer.php:1677
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCurrentTable
‪string getCurrentTable()
Definition: ContentObjectRenderer.php:565
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:50
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getImageSourceCollection
‪string getImageSourceCollection($layoutKey, $conf, $file)
Definition: ContentObjectRenderer.php:1127
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTypoScriptFrontendController
‪TYPO3 CMS Frontend Controller TypoScriptFrontendController getTypoScriptFrontendController()
Definition: ContentObjectRenderer.php:7532
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\mailto_makelinks
‪string mailto_makelinks($data, $conf)
Definition: ContentObjectRenderer.php:4610
‪TYPO3\CMS\Frontend\Http\UrlProcessorInterface\CONTEXT_COMMON
‪const CONTEXT_COMMON
Definition: UrlProcessorInterface.php:25
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_ifNull
‪string stdWrap_ifNull($content='', $conf=[])
Definition: ContentObjectRenderer.php:1910
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\typolinkWrap
‪array typolinkWrap($conf)
Definition: ContentObjectRenderer.php:5670
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$contentObjectClassMap
‪array $contentObjectClassMap
Definition: ContentObjectRenderer.php:276
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:33
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_editPanel
‪string stdWrap_editPanel($content='', $conf=[])
Definition: ContentObjectRenderer.php:2893
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryArrayJoinHelper
‪string getQueryArrayJoinHelper(string $fromAlias, array $joinParts, array &$knownAliases)
Definition: ContentObjectRenderer.php:6853
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\filelist
‪string filelist($data, bool $isCoreCall=false)
Definition: ContentObjectRenderer.php:3138
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_insertData
‪string stdWrap_insertData($content='')
Definition: ContentObjectRenderer.php:2806
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$checkPid_cache
‪array $checkPid_cache
Definition: ContentObjectRenderer.php:349
‪TYPO3\CMS\Core\Utility\StringUtility\endsWith
‪static bool endsWith($haystack, $needle)
Definition: StringUtility.php:60
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getUserObjectType
‪mixed getUserObjectType()
Definition: ContentObjectRenderer.php:902
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$recordRegister
‪array $recordRegister
Definition: ContentObjectRenderer.php:375
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_orderedStdWrap
‪string stdWrap_orderedStdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2777
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_csConv
‪string stdWrap_csConv($content='', $conf=[])
Definition: ContentObjectRenderer.php:2107
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\mergeTSRef
‪array mergeTSRef($confArr, $prop)
Definition: ContentObjectRenderer.php:6192
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\round
‪string round($content, array $conf=[])
Definition: ContentObjectRenderer.php:3983
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$checkPid_badDoktypeList
‪string $checkPid_badDoktypeList
Definition: ContentObjectRenderer.php:353
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getResourceFactory
‪ResourceFactory getResourceFactory()
Definition: ContentObjectRenderer.php:7419
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\encaps_lineSplit
‪string encaps_lineSplit($theValue, $conf)
Definition: ContentObjectRenderer.php:4415
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\start
‪start($data, $table='')
Definition: ContentObjectRenderer.php:532
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\imageLinkWrap
‪string imageLinkWrap($string, $imageFile, $conf)
Definition: ContentObjectRenderer.php:1257
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap
‪string stdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:1542
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\substring
‪string substring($content, $options)
Definition: ContentObjectRenderer.php:3341
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪string eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:107
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:37
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$cObjHookObjectsRegistry
‪array $cObjHookObjectsRegistry
Definition: ContentObjectRenderer.php:381
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_listNum
‪string stdWrap_listNum($content='', $conf=[])
Definition: ContentObjectRenderer.php:1959
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_prefixComment
‪string stdWrap_prefixComment($content='', $conf=[])
Definition: ContentObjectRenderer.php:2855
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setUserObjectType
‪setUserObjectType($userObjectType)
Definition: ContentObjectRenderer.php:912
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrap
‪string stdWrap_wrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2659
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:371
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\determineExceptionHandlerClassName
‪string null determineExceptionHandlerClassName($configuration)
Definition: ContentObjectRenderer.php:850
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_filelist
‪string stdWrap_filelist($content='', $conf=[])
Definition: ContentObjectRenderer.php:1836
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_replacement
‪string stdWrap_replacement($content='', $conf=[])
Definition: ContentObjectRenderer.php:2169
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area
Definition: Area.php:21
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGECROPSCALEMASK
‪const CONTEXT_IMAGECROPSCALEMASK
Definition: ProcessedFile.php:56
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentRecord
‪string $currentRecord
Definition: ContentObjectRenderer.php:319
‪TYPO3
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cropHTML
‪string cropHTML($content, $options)
Definition: ContentObjectRenderer.php:3399
‪TYPO3\CMS\Core\Resource\FileReference\getProperty
‪mixed getProperty($key)
Definition: FileReference.php:117
‪TYPO3\CMS\Frontend\ContentObject
Definition: AbstractContentObject.php:2
‪TYPO3\CMS\Frontend\Http\UrlProcessorInterface
Definition: UrlProcessorInterface.php:24
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\uniqueHash
‪string uniqueHash($str='')
Definition: TypoScriptFrontendController.php:4388
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\sendNotifyEmail
‪bool sendNotifyEmail($message, $recipients, $cc, $senderAddress, $senderName='', $replyTo='')
Definition: ContentObjectRenderer.php:6137
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTypoLink_URL
‪string getTypoLink_URL($params, $urlParameters=[], $target='')
Definition: ContentObjectRenderer.php:5656
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setParent
‪setParent($data, $currentRecord)
Definition: ContentObjectRenderer.php:599
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer
Definition: FilePathSanitizer.php:37
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_prepend
‪string stdWrap_prepend($content='', $conf=[])
Definition: ContentObjectRenderer.php:2733
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$alternativeData
‪string $alternativeData
Definition: ContentObjectRenderer.php:302
‪TYPO3\CMS\Core\Mail\MailMessage
Definition: MailMessage.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrap
‪string stdWrap_stdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2021
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stdWrapHookObjects
‪array $stdWrapHookObjects
Definition: ContentObjectRenderer.php:391
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCurrentFile
‪File getCurrentFile()
Definition: ContentObjectRenderer.php:1521
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setCurrentVal
‪setCurrentVal($value)
Definition: ContentObjectRenderer.php:631
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setContentObjectClassMap
‪setContentObjectClassMap(array $contentObjectClassMap)
Definition: ContentObjectRenderer.php:504
‪TYPO3\CMS\Core\Resource\FileReference
Definition: FileReference.php:31
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\HTMLcaseshift
‪string HTMLcaseshift($theValue, $case)
Definition: ContentObjectRenderer.php:6069
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface
Definition: ContentObjectGetImageResourceHookInterface.php:21
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\getMaxResults
‪int getMaxResults()
Definition: QueryBuilder.php:342
‪TYPO3\CMS\Core\Resource\ResourceFactory\getInstance
‪static ResourceFactory getInstance()
Definition: ResourceFactory.php:39
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\typoLink
‪string typoLink($linkText, $conf)
Definition: ContentObjectRenderer.php:5393
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\extLinkATagParams
‪string extLinkATagParams($URL, $TYPE)
Definition: ContentObjectRenderer.php:1488
‪TYPO3\CMS\Frontend\ContentObject\Exception\ExceptionHandlerInterface
Definition: ExceptionHandlerInterface.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\callUserFunction
‪string callUserFunction($funcName, $conf, $content)
Definition: ContentObjectRenderer.php:5973
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:614
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_round
‪string stdWrap_round($content='', $conf=[])
Definition: ContentObjectRenderer.php:2246
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentRecordNumber
‪int $currentRecordNumber
Definition: ContentObjectRenderer.php:331
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$typoScriptFrontendController
‪TypoScriptFrontendController $typoScriptFrontendController
Definition: ContentObjectRenderer.php:425
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stripHtml
‪string stdWrap_stripHtml($content='')
Definition: ContentObjectRenderer.php:2405
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_HTMLparser
‪string stdWrap_HTMLparser($content='', $conf=[])
Definition: ContentObjectRenderer.php:2139
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_lang
‪string stdWrap_lang($content='', $conf=[])
Definition: ContentObjectRenderer.php:1740
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\registerContentObjectClass
‪registerContentObjectClass($className, $contentObjectName)
Definition: ContentObjectRenderer.php:519
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_br
‪string stdWrap_br($content='')
Definition: ContentObjectRenderer.php:2487
‪TYPO3\CMS\Frontend\ContentObject\Exception\ContentRenderingException
Definition: ContentRenderingException.php:22
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrapAlign
‪string stdWrap_wrapAlign($content='', $conf=[])
Definition: ContentObjectRenderer.php:2623
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getEnvironmentVariable
‪string getEnvironmentVariable($key)
Definition: ContentObjectRenderer.php:7431
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCropAreaFromFileReference
‪Area null getCropAreaFromFileReference(FileReference $fileReference, array $fileArray)
Definition: ContentObjectRenderer.php:4820
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_split
‪string stdWrap_split($content='', $conf=[])
Definition: ContentObjectRenderer.php:2156
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getImageTagTemplate
‪string getImageTagTemplate($layoutKey, $conf)
Definition: ContentObjectRenderer.php:1105
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\_parseFunc
‪string _parseFunc($theValue, $conf)
Definition: ContentObjectRenderer.php:4176
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_numRows
‪string stdWrap_numRows($content='', $conf=[])
Definition: ContentObjectRenderer.php:1822
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stdWrapOrder
‪$stdWrapOrder
Definition: ContentObjectRenderer.php:107
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cacheStore
‪string stdWrap_cacheStore($content='', $conf=[])
Definition: ContentObjectRenderer.php:2924
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTypoLink
‪string getTypoLink($label, $params, $urlParameters=[], $target='')
Definition: ContentObjectRenderer.php:5603
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$getImgResourceHookObjects
‪array $getImgResourceHookObjects
Definition: ContentObjectRenderer.php:397
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapProcess
‪string stdWrap_stdWrapProcess($content='', $conf=[])
Definition: ContentObjectRenderer.php:2035
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_if
‪string stdWrap_if($content='', $conf=[])
Definition: ContentObjectRenderer.php:2070
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\decryptEmail
‪string decryptEmail(string $string, $type)
Definition: ContentObjectRenderer.php:5820
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:39
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getUrlToCurrentLocation
‪string getUrlToCurrentLocation($addQueryString=true)
Definition: ContentObjectRenderer.php:5630
‪TYPO3\CMS\Core\Service\FlexFormService
Definition: FlexFormService.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapPreProcess
‪string stdWrap_stdWrapPreProcess($content='', $conf=[])
Definition: ContentObjectRenderer.php:1661
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\wrap
‪string wrap($content, $wrap, $char='|')
Definition: ContentObjectRenderer.php:5933
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calcIntExplode
‪array calcIntExplode($delim, $string)
Definition: ContentObjectRenderer.php:3798
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getLanguageRestriction
‪string TYPO3 CMS Core Database Query Expression CompositeExpression null getLanguageRestriction(ExpressionBuilder $expressionBuilder, string $table, array $conf, Context $context)
Definition: ContentObjectRenderer.php:7030
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:25
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_brTag
‪string stdWrap_brTag($content='', $conf=[])
Definition: ContentObjectRenderer.php:2500
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cImage
‪string cImage($file, $conf)
Definition: ContentObjectRenderer.php:1022
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_rawUrlEncode
‪string stdWrap_rawUrlEncode($content='')
Definition: ContentObjectRenderer.php:2430
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getContentObject
‪AbstractContentObject null getContentObject($name)
Definition: ContentObjectRenderer.php:748
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getGetImgResourceHookObjects
‪array getGetImgResourceHookObjects()
Definition: ContentObjectRenderer.php:576
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrap3
‪string stdWrap_wrap3($content='', $conf=[])
Definition: ContentObjectRenderer.php:2760
‪TYPO3\CMS\Core\TimeTracker\TimeTracker\setTSlogMessage
‪setTSlogMessage($content, $num=0)
Definition: TimeTracker.php:193
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getATagParams
‪string getATagParams($conf, $addGlobal=1)
Definition: ContentObjectRenderer.php:1451
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:179
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_preIfEmptyListNum
‪string stdWrap_preIfEmptyListNum($content='', $conf=[])
Definition: ContentObjectRenderer.php:1897
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\caseshift
‪string caseshift($theValue, $case)
Definition: ContentObjectRenderer.php:6027
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$parentRecord
‪array $parentRecord
Definition: ContentObjectRenderer.php:343
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\in
‪string in(string $fieldName, $value)
Definition: ExpressionBuilder.php:242
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_date
‪string stdWrap_date($content='', $conf=[])
Definition: ContentObjectRenderer.php:2285
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\createExceptionHandler
‪ExceptionHandlerInterface null createExceptionHandler($configuration=[])
Definition: ContentObjectRenderer.php:830
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_htmlSanitize
‪stdWrap_htmlSanitize(string $content='', array $conf=[])
Definition: ContentObjectRenderer.php:2901
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_keywords
‪string stdWrap_keywords($content='')
Definition: ContentObjectRenderer.php:2526
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_preCObject
‪string stdWrap_preCObject($content='', $conf=[])
Definition: ContentObjectRenderer.php:2596
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\resolveMixedLinkParameter
‪array string resolveMixedLinkParameter($linkText, $mixedLinkParameter, &$configuration=[])
Definition: ContentObjectRenderer.php:5338
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_required
‪string stdWrap_required($content='')
Definition: ContentObjectRenderer.php:2052
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_current
‪string stdWrap_current($content='', $conf=[])
Definition: ContentObjectRenderer.php:1794
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$userObjectType
‪$userObjectType
Definition: ContentObjectRenderer.php:413
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\__sleep
‪array __sleep()
Definition: ContentObjectRenderer.php:456
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_setContentToCurrent
‪string stdWrap_setContentToCurrent($content='')
Definition: ContentObjectRenderer.php:1712
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\andX
‪CompositeExpression andX(... $expressions)
Definition: ExpressionBuilder.php:68
‪TYPO3\CMS\Core\Utility\DebugUtility\debugTrail
‪static string debugTrail($prependFileNames=false)
Definition: DebugUtility.php:139
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cObjGet
‪string cObjGet($setup, $addKey='')
Definition: ContentObjectRenderer.php:645
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:30
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\encryptEmail
‪string encryptEmail(string $string, $type)
Definition: ContentObjectRenderer.php:5782
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_numberFormat
‪string stdWrap_numberFormat($content='', $conf=[])
Definition: ContentObjectRenderer.php:2259
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_setCurrent
‪string stdWrap_setCurrent($content='', $conf=[])
Definition: ContentObjectRenderer.php:1726
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\convertToUserIntObject
‪convertToUserIntObject()
Definition: ContentObjectRenderer.php:920
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_intval
‪string stdWrap_intval($content='')
Definition: ContentObjectRenderer.php:2215
‪TYPO3\CMS\Frontend\Page\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\insertData
‪string insertData($str)
Definition: ContentObjectRenderer.php:3279
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_ifEmpty
‪string stdWrap_ifEmpty($content='', $conf=[])
Definition: ContentObjectRenderer.php:1924
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryArguments
‪string getQueryArguments($conf, $overruleQueryArguments=[], $forceOverruleArguments=false)
Definition: ContentObjectRenderer.php:5881
‪TYPO3\CMS\Core\Resource\FileReference\getOriginalFile
‪File getOriginalFile()
Definition: FileReference.php:489
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\encryptCharcode
‪string encryptCharcode($n, $start, $end, $offset)
Definition: ContentObjectRenderer.php:5861
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_parseFunc
‪string stdWrap_parseFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:2125
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectGetSingleHookInterface
Definition: ContentObjectGetSingleHookInterface.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_hash
‪string stdWrap_hash($content='', array $conf=[])
Definition: ContentObjectRenderer.php:2228
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\isDisabled
‪bool isDisabled($table, $row)
Definition: ContentObjectRenderer.php:7404
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$data
‪array $data
Definition: ContentObjectRenderer.php:286
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:33
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\__wakeup
‪__wakeup()
Definition: ContentObjectRenderer.php:475
‪TYPO3\CMS\Core\Utility\DebugUtility\viewArray
‪static string viewArray($array_in)
Definition: DebugUtility.php:195
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:29
‪TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
Definition: ResourceDoesNotExistException.php:21
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_outerWrap
‪string stdWrap_outerWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2794
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$doConvertToUserIntObject
‪$doConvertToUserIntObject
Definition: ContentObjectRenderer.php:406
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\numberFormat
‪string numberFormat($content, $conf)
Definition: ContentObjectRenderer.php:4015
‪TYPO3\CMS\Core\Configuration\Features
Definition: Features.php:54
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\keywords
‪string keywords($content)
Definition: ContentObjectRenderer.php:6010
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectGetDataHookInterface
Definition: ContentObjectGetDataHookInterface.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFrontendBackendUser
‪TYPO3 CMS Backend FrontendBackendUserAuthentication getFrontendBackendUser()
Definition: ContentObjectRenderer.php:7516
‪TYPO3\CMS\Core\Html\SanitizerInitiator
Definition: SanitizerInitiator.php:25
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\orX
‪CompositeExpression orX(... $expressions)
Definition: ExpressionBuilder.php:80
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\currentPageUrl
‪string currentPageUrl($urlParameters=[], $id=0)
Definition: ContentObjectRenderer.php:5686
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection\getCropArea
‪Area getCropArea(string $id='default')
Definition: CropVariantCollection.php:127
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\noTrimWrap
‪string noTrimWrap($content, $wrap, $char='|')
Definition: ContentObjectRenderer.php:5952
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$lastTypoLinkLD
‪array $lastTypoLinkLD
Definition: ContentObjectRenderer.php:369
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:34
‪TYPO3\CMS\Core\Service\DependencyOrderingService
Definition: DependencyOrderingService.php:31
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\editIcons
‪string editIcons($content, $params, array $conf=[], $currentRecord='', $dataArray=[], $addUrlParamStr='')
Definition: ContentObjectRenderer.php:7355
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFieldVal
‪string null getFieldVal($field)
Definition: ContentObjectRenderer.php:4898
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileReferenceObject
‪FileReference getFileReferenceObject($uid, array $fileReferenceData=[], $raw=false)
Definition: ResourceFactory.php:629
‪TYPO3\CMS\Core\Utility\MailUtility
Definition: MailUtility.php:24
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\HTMLparser_TSbridge
‪string HTMLparser_TSbridge($theValue, $conf)
Definition: ContentObjectRenderer.php:3246
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentValKey
‪string $currentValKey
Definition: ContentObjectRenderer.php:312
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_postCObject
‪string stdWrap_postCObject($content='', $conf=[])
Definition: ContentObjectRenderer.php:2609
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentRecordTotal
‪int $currentRecordTotal
Definition: ContentObjectRenderer.php:325
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\filelink
‪string filelink($theValue, $conf, $isCoreCall=false)
Definition: ContentObjectRenderer.php:3593
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\dataWrap
‪string dataWrap($content, $wrap)
Definition: ContentObjectRenderer.php:3261
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getRecords
‪array getRecords($tableName, array $queryConfiguration)
Definition: ContentObjectRenderer.php:6561
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_strftime
‪string stdWrap_strftime($content='', $conf=[])
Definition: ContentObjectRenderer.php:2302
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_addParams
‪string stdWrap_addParams($content='', $conf=[])
Definition: ContentObjectRenderer.php:2568
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calculateCacheTags
‪array calculateCacheTags(array $configuration)
Definition: ContentObjectRenderer.php:7488
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject
Definition: AbstractContentObject.php:24
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$align
‪array $align
Definition: ContentObjectRenderer.php:96
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_substring
‪string stdWrap_substring($content='', $conf=[])
Definition: ContentObjectRenderer.php:2380
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:55
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_innerWrap2
‪string stdWrap_innerWrap2($content='', $conf=[])
Definition: ContentObjectRenderer.php:2554
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileObjectFromCombinedIdentifier
‪File ProcessedFile null getFileObjectFromCombinedIdentifier($identifier)
Definition: ResourceFactory.php:424
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_field
‪string stdWrap_field($content='', $conf=[])
Definition: ContentObjectRenderer.php:1780
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_ifBlank
‪string stdWrap_ifBlank($content='', $conf=[])
Definition: ContentObjectRenderer.php:1941
‪TYPO3\CMS\Core\Context\Context\getAspect
‪AspectInterface getAspect(string $name)
Definition: Context.php:106
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\linkWrap
‪string linkWrap($content, $wrap)
Definition: ContentObjectRenderer.php:1393
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapOverride
‪string stdWrap_stdWrapOverride($content='', $conf=[])
Definition: ContentObjectRenderer.php:1863
‪TYPO3\CMS\Core\Utility\DebugUtility
Definition: DebugUtility.php:24
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryArray
‪array getQueryArray(QueryBuilder $queryBuilder)
Definition: ContentObjectRenderer.php:6805
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$parameters
‪array $parameters
Definition: ContentObjectRenderer.php:308
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_debug
‪string stdWrap_debug($content='')
Definition: ContentObjectRenderer.php:2975
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getBorderAttr
‪string getBorderAttr($borderAttr)
Definition: ContentObjectRenderer.php:1083
‪TYPO3\CMS\Frontend\Imaging\GifBuilder
Definition: GifBuilder.php:52
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$lastTypoLinkUrl
‪string $lastTypoLinkUrl
Definition: ContentObjectRenderer.php:359
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\getFirstResult
‪int getFirstResult()
Definition: QueryBuilder.php:317
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_typolink
‪string stdWrap_typolink($content='', $conf=[])
Definition: ContentObjectRenderer.php:2642
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_dataWrap
‪string stdWrap_dataWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2720
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\parseFunc
‪string parseFunc($theValue, $conf, $ref='')
Definition: ContentObjectRenderer.php:4048
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stdWrapRecursionLevel
‪int $stdWrapRecursionLevel
Definition: ContentObjectRenderer.php:421
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stopRendering
‪array $stopRendering
Definition: ContentObjectRenderer.php:417
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentFile
‪File $currentFile
Definition: ContentObjectRenderer.php:401
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:23
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:42
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\addParams
‪string addParams($content, $conf, $isCoreCall=false)
Definition: ContentObjectRenderer.php:3541
‪TYPO3\CMS\Core\TypoScript\TypoScriptService
Definition: TypoScriptService.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\createCropAreaFromJsonString
‪Area createCropAreaFromJsonString(string $cropSettings, string $cropVariant)
Definition: ContentObjectRenderer.php:4882
‪TYPO3\CMS\Core\Utility\MathUtility\calculateWithParentheses
‪static int calculateWithParentheses($string)
Definition: MathUtility.php:170
‪$output
‪$output
Definition: annotationChecker.php:113
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calculateCacheLifetime
‪int null calculateCacheLifetime(array $configuration)
Definition: ContentObjectRenderer.php:7466
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\listNum
‪string listNum($content, $listNum, $char)
Definition: ContentObjectRenderer.php:3035
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\exec_getQuery
‪Statement exec_getQuery($table, $conf)
Definition: ContentObjectRenderer.php:6544
‪debug
‪debug($variable='', $title=null, $group=null)
Definition: GlobalDebugFunctions.php:5
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_encapsLines
‪string stdWrap_encapsLines($content='', $conf=[])
Definition: ContentObjectRenderer.php:2514
‪TYPO3\CMS\Core\Resource\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:31
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\editPanel
‪string editPanel($content, $conf, $currentRecord='', $dataArray=[])
Definition: ContentObjectRenderer.php:7291
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calc
‪int calc($val)
Definition: ContentObjectRenderer.php:3758
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_append
‪string stdWrap_append($content='', $conf=[])
Definition: ContentObjectRenderer.php:2746
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\render
‪string render(AbstractContentObject $contentObject, $configuration=[])
Definition: ContentObjectRenderer.php:778
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\resolveAnchorLink
‪string resolveAnchorLink(string $linkText, array $conf)
Definition: ContentObjectRenderer.php:7546
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\enableFields
‪string enableFields($table, $show_hidden=false, array $ignore_array=[])
Definition: ContentObjectRenderer.php:6230
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_bytes
‪string stdWrap_bytes($content='', $conf=[])
Definition: ContentObjectRenderer.php:2367
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_crop
‪string stdWrap_crop($content='', $conf=[])
Definition: ContentObjectRenderer.php:2418
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getData
‪string getData($string, $fieldArray=null)
Definition: ContentObjectRenderer.php:4921
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\addCacheTags
‪addCacheTags(array $tags)
Definition: TypoScriptFrontendController.php:3371
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:97
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrapValue
‪string stdWrapValue($key, array $config, $defaultValue='')
Definition: ContentObjectRenderer.php:1637
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪string getExtension()
Definition: AbstractFile.php:252
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setJS
‪setJS($key, $content='')
Definition: TypoScriptFrontendController.php:4332
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryConstraints
‪array getQueryConstraints(string $table, array $conf)
Definition: ContentObjectRenderer.php:6887
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_debugData
‪string stdWrap_debugData($content='')
Definition: ContentObjectRenderer.php:3001
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectOneSourceCollectionHookInterface
Definition: ContentObjectOneSourceCollectionHookInterface.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrap2
‪string stdWrap_wrap2($content='', $conf=[])
Definition: ContentObjectRenderer.php:2702
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCropAreaFromFromTypoScriptSettings
‪Area null getCropAreaFromFromTypoScriptSettings(FileInterface $file, array $fileArray)
Definition: ContentObjectRenderer.php:4841
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:25
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_filelink
‪string stdWrap_filelink($content='', $conf=[])
Definition: ContentObjectRenderer.php:2583
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\crop
‪string crop($content, $options)
Definition: ContentObjectRenderer.php:3359
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cObject
‪string stdWrap_cObject($content='', $conf=[])
Definition: ContentObjectRenderer.php:1808
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_prioriCalc
‪string stdWrap_prioriCalc($content='', $conf=[])
Definition: ContentObjectRenderer.php:2183
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\replacementSingle
‪string replacementSingle($content, array $configuration)
Definition: ContentObjectRenderer.php:3906
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\lastChanged
‪lastChanged($tstamp)
Definition: ContentObjectRenderer.php:1375
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection
Definition: CropVariantCollection.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_char
‪string stdWrap_char($content='', $conf=[])
Definition: ContentObjectRenderer.php:2203
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapPostProcess
‪string stdWrap_stdWrapPostProcess($content='', $conf=[])
Definition: ContentObjectRenderer.php:2959
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:91
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\processUrl
‪string null processUrl($context, $url, $typolinkConfiguration=[])
Definition: ContentObjectRenderer.php:5702
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\numRows
‪int numRows($conf)
Definition: ContentObjectRenderer.php:3019
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileObject
‪File getFileObject($uid, array $fileData=[])
Definition: ResourceFactory.php:399
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_debugFunc
‪string stdWrap_debugFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:2988
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getImgResource
‪array null getImgResource($file, $fileArray)
Definition: ContentObjectRenderer.php:4669
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTimeTracker
‪TimeTracker getTimeTracker()
Definition: ContentObjectRenderer.php:7524
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$cObjHookObjectsArr
‪array $cObjHookObjectsArr
Definition: ContentObjectRenderer.php:385
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\rootLineValue
‪string rootLineValue($key, $field, $slideBack=false, $altRootLine='')
Definition: ContentObjectRenderer.php:5246
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$oldData
‪array $oldData
Definition: ContentObjectRenderer.php:296
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\checkPid
‪bool checkPid($uid)
Definition: ContentObjectRenderer.php:7170
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\prefixComment
‪string prefixComment($str, $conf, $content)
Definition: ContentObjectRenderer.php:3316
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\mergeExceptionHandlerConfiguration
‪array mergeExceptionHandlerConfiguration($configuration)
Definition: ContentObjectRenderer.php:880
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\searchWhere
‪string searchWhere($searchWords, $searchFieldList, $searchTable)
Definition: ContentObjectRenderer.php:6496
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cObjGetSingle
‪string cObjGetSingle($name, $conf, $TSkey='__')
Definition: ContentObjectRenderer.php:671
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_override
‪string stdWrap_override($content='', $conf=[])
Definition: ContentObjectRenderer.php:1880
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getAltParam
‪string getAltParam($conf, $longDesc=true)
Definition: ContentObjectRenderer.php:1414
‪TYPO3\CMS\Core\Service\MarkerBasedTemplateService
Definition: MarkerBasedTemplateService.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\readFlexformIntoConf
‪readFlexformIntoConf($flexData, &$conf, $recursive=false)
Definition: ContentObjectRenderer.php:941
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_innerWrap
‪string stdWrap_innerWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2540
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getSlidePids
‪string getSlidePids($pidList, $pidConf)
Definition: ContentObjectRenderer.php:987
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_age
‪string stdWrap_age($content='', $conf=[])
Definition: ContentObjectRenderer.php:2340
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calcAge
‪string calcAge($seconds, $labels)
Definition: ContentObjectRenderer.php:6097
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$table
‪string $table
Definition: ContentObjectRenderer.php:290
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cropHTML
‪string stdWrap_cropHTML($content='', $conf=[])
Definition: ContentObjectRenderer.php:2393
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTreeList
‪string getTreeList($id, $depth, $begin=0, $dontCheckEnableFields=false, $addSelectFields='', $moreWhereClauses='', array $prevId_array=[], $recursionLevel=0)
Definition: ContentObjectRenderer.php:6262
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCurrentVal
‪mixed getCurrentVal()
Definition: ContentObjectRenderer.php:620
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection\create
‪static CropVariantCollection create(string $jsonString, array $tcaConfig=[])
Definition: CropVariantCollection.php:40
‪TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer
Definition: FrontendRestrictionContainer.php:29
‪TYPO3\CMS\Core\Resource\Exception\InvalidPathException
Definition: InvalidPathException.php:21
‪TYPO3\CMS\Core\TimeTracker\TimeTracker
Definition: TimeTracker.php:27
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_data
‪string stdWrap_data($content='', $conf=[])
Definition: ContentObjectRenderer.php:1764
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFromCache
‪string bool getFromCache(array $configuration)
Definition: ContentObjectRenderer.php:7443
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_addPageCacheTags
‪string stdWrap_addPageCacheTags($content='', $conf=[])
Definition: ContentObjectRenderer.php:1693
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\sanitizeSelectPart
‪string sanitizeSelectPart($selectPart, $table)
Definition: ContentObjectRenderer.php:7091
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQuery
‪mixed getQuery($table, $conf, $returnQueryArray=false)
Definition: ContentObjectRenderer.php:6599
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_strtotime
‪string stdWrap_strtotime($content='', $conf=[])
Definition: ContentObjectRenderer.php:2324
‪TYPO3\CMS\Core\Utility\ArrayUtility\filterAndSortByNumericKeys
‪static array filterAndSortByNumericKeys($setupArr, $acceptAnyKeys=false)
Definition: ArrayUtility.php:772
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\OBJECTTYPE_USER_INT
‪const OBJECTTYPE_USER_INT
Definition: ContentObjectRenderer.php:432
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_trim
‪string stdWrap_trim($content='')
Definition: ContentObjectRenderer.php:1971
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:2
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_preUserFunc
‪string stdWrap_preUserFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:1849
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calculateCacheKey
‪string calculateCacheKey(array $configuration)
Definition: ContentObjectRenderer.php:7503
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getKey
‪int getKey($key, $arr)
Definition: ContentObjectRenderer.php:5304
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_postUserFuncInt
‪string stdWrap_postUserFuncInt($content='', $conf=[])
Definition: ContentObjectRenderer.php:2833
‪TYPO3\CMS\Core\Html\SanitizerBuilderFactory
Definition: SanitizerBuilderFactory.php:35
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_doubleBrTag
‪string stdWrap_doubleBrTag($content='', $conf=[])
Definition: ContentObjectRenderer.php:2474
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\checkPidArray
‪array checkPidArray($listArr)
Definition: ContentObjectRenderer.php:7127
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\typoLink_URL
‪string typoLink_URL($conf)
Definition: ContentObjectRenderer.php:5584
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\splitObj
‪string splitObj($value, $conf)
Definition: ContentObjectRenderer.php:3819
‪TYPO3\CMS\Frontend\ContentObject\Exception\ProductionExceptionHandler
Definition: ProductionExceptionHandler.php:29
‪TYPO3\CMS\Core\Resource\ResourceFactory\retrieveFileOrFolderObject
‪File Folder null retrieveFileOrFolderObject($input)
Definition: ResourceFactory.php:491
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_strPad
‪string stdWrap_strPad($content='', $conf=[])
Definition: ContentObjectRenderer.php:1984
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject\render
‪string render($conf=[])
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface
Definition: ContentObjectPostInitHookInterface.php:22
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$lastTypoLinkTarget
‪string $lastTypoLinkTarget
Definition: ContentObjectRenderer.php:365
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_encodeForJavaScriptValue
‪string stdWrap_encodeForJavaScriptValue($content='')
Definition: ContentObjectRenderer.php:2461
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication
Definition: AbstractUserAuthentication.php:51
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\checkIf
‪bool checkIf($conf)
Definition: ContentObjectRenderer.php:3059
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\replacement
‪string replacement($content, array $configuration)
Definition: ContentObjectRenderer.php:3886
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_fieldRequired
‪string stdWrap_fieldRequired($content='', $conf=[])
Definition: ContentObjectRenderer.php:2088
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getMailTo
‪array getMailTo($mailAddress, $linktxt)
Definition: ContentObjectRenderer.php:5742
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_postUserFunc
‪string stdWrap_postUserFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:2819
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryMarkers
‪array getQueryMarkers($table, $conf)
Definition: ContentObjectRenderer.php:7209
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getGlobal
‪mixed getGlobal($keyString, $source=null)
Definition: ContentObjectRenderer.php:5271