‪TYPO3CMS  ‪main
ContentObjectRenderer.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Doctrine\DBAL\Exception as DBALException;
19 use Doctrine\DBAL\Result;
20 use Psr\Container\ContainerInterface;
21 use Psr\Http\Message\ServerRequestInterface;
22 use Psr\Log\LoggerAwareInterface;
23 use Psr\Log\LoggerAwareTrait;
24 use Psr\Log\LogLevel;
31 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
59 use TYPO3\CMS\Core\Type\File\ImageInfo;
76 use TYPO3\CMS\Frontend\Typolink\LinkResult;
79 use TYPO3\HtmlSanitizer\Builder\BuilderInterface;
80 
88 class ‪ContentObjectRenderer implements LoggerAwareInterface
89 {
90  use LoggerAwareTrait;
92 
96  protected ‪$container;
97 
104  public array ‪$stdWrapOrder = [
105  'stdWrapPreProcess' => 'hook',
106  // this is a placeholder for the first Hook
107  'cacheRead' => 'hook',
108  // this is a placeholder for checking if the content is available in cache
109  'setContentToCurrent' => 'boolean',
110  'setContentToCurrent.' => 'array',
111  'addPageCacheTags' => 'string',
112  'addPageCacheTags.' => 'array',
113  'setCurrent' => 'string',
114  'setCurrent.' => 'array',
115  'lang.' => 'array',
116  'data' => 'getText',
117  'data.' => 'array',
118  'field' => 'fieldName',
119  'field.' => 'array',
120  'current' => 'boolean',
121  'current.' => 'array',
122  'cObject' => 'cObject',
123  'cObject.' => 'array',
124  'numRows.' => 'array',
125  'preUserFunc' => 'functionName',
126  'stdWrapOverride' => 'hook',
127  // this is a placeholder for the second Hook
128  'override' => 'string',
129  'override.' => 'array',
130  'preIfEmptyListNum' => 'listNum',
131  'preIfEmptyListNum.' => 'array',
132  'ifNull' => 'string',
133  'ifNull.' => 'array',
134  'ifEmpty' => 'string',
135  'ifEmpty.' => 'array',
136  'ifBlank' => 'string',
137  'ifBlank.' => 'array',
138  'listNum' => 'listNum',
139  'listNum.' => 'array',
140  'trim' => 'boolean',
141  'trim.' => 'array',
142  'strPad.' => 'array',
143  'stdWrap' => 'stdWrap',
144  'stdWrap.' => 'array',
145  'stdWrapProcess' => 'hook',
146  // this is a placeholder for the third Hook
147  'required' => 'boolean',
148  'required.' => 'array',
149  'if.' => 'array',
150  'fieldRequired' => 'fieldName',
151  'fieldRequired.' => 'array',
152  'csConv' => 'string',
153  'csConv.' => 'array',
154  'parseFunc' => 'objectpath',
155  'parseFunc.' => 'array',
156  'HTMLparser' => 'boolean',
157  'HTMLparser.' => 'array',
158  'split.' => 'array',
159  'replacement.' => 'array',
160  'prioriCalc' => 'boolean',
161  'prioriCalc.' => 'array',
162  'char' => 'integer',
163  'char.' => 'array',
164  'intval' => 'boolean',
165  'intval.' => 'array',
166  'hash' => 'string',
167  'hash.' => 'array',
168  'round' => 'boolean',
169  'round.' => 'array',
170  'numberFormat.' => 'array',
171  'expandList' => 'boolean',
172  'expandList.' => 'array',
173  'date' => 'dateconf',
174  'date.' => 'array',
175  'strtotime' => 'strtotimeconf',
176  'strtotime.' => 'array',
177  'strftime' => 'strftimeconf',
178  'strftime.' => 'array',
179  'formattedDate' => 'formattedDateconf',
180  'formattedDate.' => 'array',
181  'age' => 'boolean',
182  'age.' => 'array',
183  'case' => 'case',
184  'case.' => 'array',
185  'bytes' => 'boolean',
186  'bytes.' => 'array',
187  'substring' => 'parameters',
188  'substring.' => 'array',
189  'cropHTML' => 'crop',
190  'cropHTML.' => 'array',
191  'stripHtml' => 'boolean',
192  'stripHtml.' => 'array',
193  'crop' => 'crop',
194  'crop.' => 'array',
195  'rawUrlEncode' => 'boolean',
196  'rawUrlEncode.' => 'array',
197  'htmlSpecialChars' => 'boolean',
198  'htmlSpecialChars.' => 'array',
199  'encodeForJavaScriptValue' => 'boolean',
200  'encodeForJavaScriptValue.' => 'array',
201  'doubleBrTag' => 'string',
202  'doubleBrTag.' => 'array',
203  'br' => 'boolean',
204  'br.' => 'array',
205  'brTag' => 'string',
206  'brTag.' => 'array',
207  'encapsLines.' => 'array',
208  'keywords' => 'boolean',
209  'keywords.' => 'array',
210  'innerWrap' => 'wrap',
211  'innerWrap.' => 'array',
212  'innerWrap2' => 'wrap',
213  'innerWrap2.' => 'array',
214  'preCObject' => 'cObject',
215  'preCObject.' => 'array',
216  'postCObject' => 'cObject',
217  'postCObject.' => 'array',
218  'wrapAlign' => 'align',
219  'wrapAlign.' => 'array',
220  'typolink.' => 'array',
221  'wrap' => 'wrap',
222  'wrap.' => 'array',
223  'noTrimWrap' => 'wrap',
224  'noTrimWrap.' => 'array',
225  'wrap2' => 'wrap',
226  'wrap2.' => 'array',
227  'dataWrap' => 'dataWrap',
228  'dataWrap.' => 'array',
229  'prepend' => 'cObject',
230  'prepend.' => 'array',
231  'append' => 'cObject',
232  'append.' => 'array',
233  'wrap3' => 'wrap',
234  'wrap3.' => 'array',
235  'orderedStdWrap' => 'stdWrap',
236  'orderedStdWrap.' => 'array',
237  'outerWrap' => 'wrap',
238  'outerWrap.' => 'array',
239  'insertData' => 'boolean',
240  'insertData.' => 'array',
241  'postUserFunc' => 'functionName',
242  'postUserFuncInt' => 'functionName',
243  'prefixComment' => 'string',
244  'prefixComment.' => 'array',
245  'htmlSanitize' => 'boolean',
246  'htmlSanitize.' => 'array',
247  'cacheStore' => 'hook',
248  // this is a placeholder for storing the content in cache
249  'stdWrapPostProcess' => 'hook',
250  // this is a placeholder for the last Hook
251  'debug' => 'boolean',
252  'debug.' => 'array',
253  'debugFunc' => 'boolean',
254  'debugFunc.' => 'array',
255  'debugData' => 'boolean',
256  'debugData.' => 'array',
257  ];
258 
268  public ‪$data = [];
269 
273  protected ‪$table = '';
274 
280  public ‪$parameters = [];
281 
285  public ‪$currentValKey = 'currentValue_kidjls9dksoje';
286 
293  public ‪$currentRecord = '';
294 
300  public ‪$currentRecordNumber = 0;
301 
307  public ‪$parentRecordNumber = 0;
308 
314  public ‪$parentRecord = [];
315 
321 
323 
329  protected ‪$stdWrapHookObjects = [];
330 
337 
341  protected ‪$currentFile;
342 
347  public ‪$doConvertToUserIntObject = false;
348 
355  protected ‪$userObjectType = false;
356 
360  protected ‪$stopRendering = [];
361 
365  protected ‪$stdWrapRecursionLevel = 0;
366 
371 
375  private ?ServerRequestInterface ‪$request = null;
376 
382  public const ‪OBJECTTYPE_USER_INT = 1;
388  public const ‪OBJECTTYPE_USER = 2;
389 
391  {
392  $this->typoScriptFrontendController = ‪$typoScriptFrontendController;
393  $this->container = ‪$container;
394  }
395 
396  public function ‪setRequest(?ServerRequestInterface ‪$request): void
397  {
398  $this->request = ‪$request;
399  }
400 
408  public function ‪__sleep()
409  {
410  $vars = get_object_vars($this);
411  unset($vars['typoScriptFrontendController'], $vars['logger'], $vars['container'], $vars['request']);
412  if ($this->currentFile instanceof ‪FileReference) {
413  $this->currentFile = 'FileReference:' . $this->currentFile->getUid();
414  } elseif ($this->currentFile instanceof ‪File) {
415  $this->currentFile = 'File:' . $this->currentFile->getIdentifier();
416  } else {
417  unset($vars['currentFile']);
418  }
419  return array_keys($vars);
420  }
421 
427  public function ‪__wakeup()
428  {
429  if (isset(‪$GLOBALS['TSFE'])) {
430  $this->typoScriptFrontendController = ‪$GLOBALS['TSFE'];
431  }
432  if (is_string($this->currentFile)) {
433  [$objectType, ‪$identifier] = explode(':', $this->currentFile, 2);
434  try {
435  if ($objectType === 'File') {
436  $this->currentFile = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject(‪$identifier);
437  } elseif ($objectType === 'FileReference') {
438  $this->currentFile = GeneralUtility::makeInstance(ResourceFactory::class)->getFileReferenceObject(‪$identifier);
439  }
440  } catch (ResourceDoesNotExistException $e) {
441  $this->currentFile = null;
442  }
443  }
444  $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
445  $this->container = GeneralUtility::getContainer();
446 
447  // We do not derive $this->request from globals here. The request is expected to be injected
448  // using setRequest(), a fallback to $GLOBALS['TYPO3_REQUEST'] is available in getRequest() for BC.
449  }
450 
459  public function ‪start(‪$data, ‪$table = '')
460  {
461  $this->data = ‪$data;
462  $this->table = ‪$table;
463  $this->currentRecord = ‪$table !== ''
464  ? ‪$table . ':' . ($this->data['uid'] ?? '')
465  : '';
466  $this->parameters = [];
467  $this->stdWrapHookObjects = [];
468  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] ?? [] as $className) {
469  $hookObject = GeneralUtility::makeInstance($className);
470  if (!$hookObject instanceof ContentObjectStdWrapHookInterface) {
471  throw new \UnexpectedValueException($className . ' must implement interface ' . ContentObjectStdWrapHookInterface::class, 1195043965);
472  }
473  $this->stdWrapHookObjects[] = $hookObject;
474  }
475  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] ?? [] as $className) {
476  $postInitializationProcessor = GeneralUtility::makeInstance($className);
477  if (!$postInitializationProcessor instanceof ContentObjectPostInitHookInterface) {
478  throw new \UnexpectedValueException($className . ' must implement interface ' . ContentObjectPostInitHookInterface::class, 1274563549);
479  }
480  $postInitializationProcessor->postProcessContentObjectInitialization($this);
481  }
482  }
483 
489  public function ‪getCurrentTable()
490  {
491  return ‪$this->table;
492  }
493 
500  protected function ‪getGetImgResourceHookObjects()
501  {
502  if (!isset($this->getImgResourceHookObjects)) {
503  $this->getImgResourceHookObjects = [];
504  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] ?? [] as $className) {
505  $hookObject = GeneralUtility::makeInstance($className);
506  if (!$hookObject instanceof ‪ContentObjectGetImageResourceHookInterface) {
507  throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetImageResourceHookInterface::class, 1218636383);
508  }
509  $this->getImgResourceHookObjects[] = $hookObject;
510  }
511  }
513  }
514 
523  public function ‪setParent(‪$data, ‪$currentRecord)
524  {
525  $this->parentRecord = [
526  'data' => ‪$data,
527  'currentRecord' => ‪$currentRecord,
528  ];
529  }
530 
531  /***********************************************
532  *
533  * CONTENT_OBJ:
534  *
535  ***********************************************/
544  public function ‪getCurrentVal()
545  {
546  return $this->data[‪$this->currentValKey] ?? null;
547  }
548 
555  public function ‪setCurrentVal($value)
556  {
557  $this->data[‪$this->currentValKey] = $value;
558  }
559 
569  public function ‪cObjGet($setup, $addKey = '')
570  {
571  if (!is_array($setup)) {
572  return '';
573  }
574  return implode('', $this->‪cObjGetSeparated($setup, $addKey));
575  }
576 
583  public function ‪cObjGetSeparated(?array $setup, string $addKey = ''): array
584  {
585  if ($setup === null || $setup === []) {
586  return [];
587  }
588  $sKeyArray = ArrayUtility::filterAndSortByNumericKeys($setup);
589  $contentObjects = [];
590  foreach ($sKeyArray as $theKey) {
591  $theValue = $setup[$theKey];
592  if ((int)$theKey && !str_contains($theKey, '.')) {
593  $conf = $setup[$theKey . '.'] ?? [];
594  $contentObjects[] = $this->‪cObjGetSingle($theValue, $conf, $addKey . $theKey);
595  }
596  }
597  return $contentObjects;
598  }
599 
609  public function ‪cObjGetSingle(string $name, $conf, $TSkey = '__')
610  {
611  $timeTracker = $this->‪getTimeTracker();
612  $name = trim($name);
613  if ($timeTracker->LR) {
614  $timeTracker->push($TSkey, $name);
615  }
616  $fullConfigArray = [
617  'tempKey' => $name,
618  'tempKey.' => is_array($conf) ? $conf : [],
619  ];
620  // Resolve '=<' operator if needed
621  $fullConfigArray = $this->‪mergeTSRef($fullConfigArray, 'tempKey');
622  $contentObject = $this->‪getContentObject($fullConfigArray['tempKey']);
623  $content = '';
624  if ($contentObject) {
625  $content = $this->‪render($contentObject, $fullConfigArray['tempKey.']);
626  }
627  if ($timeTracker->LR) {
628  $timeTracker->pull($content);
629  }
630  return $content;
631  }
632 
639  public function ‪getContentObject($name): ?AbstractContentObject
640  {
641  $contentObjectFactory = $this->container
642  ? $this->container->get(ContentObjectFactory::class)
643  : GeneralUtility::makeInstance(ContentObjectFactory::class);
644  return $contentObjectFactory->getContentObject($name, $this->‪getRequest(), $this);
645  }
646 
647  /********************************************
648  *
649  * Functions rendering content objects (cObjects)
650  *
651  ********************************************/
662  public function ‪render(‪AbstractContentObject $contentObject, $configuration = []): string
663  {
664  $content = '';
665 
666  // Evaluate possible cache and return
667  $cacheConfiguration = $configuration['cache.'] ?? null;
668  if ($cacheConfiguration !== null) {
669  unset($configuration['cache.']);
670  $cache = $this->‪getFromCache($cacheConfiguration);
671  if ($cache !== false) {
672  return $cache;
673  }
674  }
675 
676  // Render content
677  try {
678  $content .= $contentObject->‪render($configuration);
679  } catch (ContentRenderingException $exception) {
680  // Content rendering Exceptions indicate a critical problem which should not be
681  // caught e.g. when something went wrong with Exception handling itself
682  throw $exception;
683  } catch (\Exception $exception) {
684  $exceptionHandler = $this->‪createExceptionHandler($configuration);
685  if ($exceptionHandler === null) {
686  throw $exception;
687  }
688  $content = $exceptionHandler->handle($exception, $contentObject, $configuration);
689  }
690 
691  // Store cache
692  if ($cacheConfiguration !== null && !$this->‪getTypoScriptFrontendController()->no_cache) {
693  $key = $this->‪calculateCacheKey($cacheConfiguration);
694  if (!empty($key)) {
695  $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('hash');
696  $tags = $this->‪calculateCacheTags($cacheConfiguration);
697  $lifetime = $this->‪calculateCacheLifetime($cacheConfiguration);
698  $cachedData = [
699  'content' => $content,
700  'cacheTags' => $tags,
701  ];
702  $cacheFrontend->set($key, $cachedData, $tags, $lifetime);
704  }
705  }
706 
707  return $content;
708  }
709 
718  protected function ‪createExceptionHandler($configuration = [])
719  {
720  $exceptionHandler = null;
721  $exceptionHandlerClassName = $this->‪determineExceptionHandlerClassName($configuration);
722  if (!empty($exceptionHandlerClassName)) {
723  $exceptionHandler = GeneralUtility::makeInstance($exceptionHandlerClassName);
724  if (!$exceptionHandler instanceof ‪ExceptionHandlerInterface) {
725  throw new ‪ContentRenderingException('An exception handler was configured but the class does not exist or does not implement the ExceptionHandlerInterface', 1403653369);
726  }
727  $exceptionHandler->setConfiguration($this->‪mergeExceptionHandlerConfiguration($configuration));
728  }
729 
730  return $exceptionHandler;
731  }
732 
739  protected function ‪determineExceptionHandlerClassName($configuration)
740  {
741  $exceptionHandlerClassName = null;
742  $tsfe = $this->‪getTypoScriptFrontendController();
743  if (!isset($tsfe->config['config']['contentObjectExceptionHandler'])) {
744  if (‪Environment::getContext()->isProduction()) {
745  $exceptionHandlerClassName = '1';
746  }
747  } else {
748  $exceptionHandlerClassName = $tsfe->config['config']['contentObjectExceptionHandler'];
749  }
750 
751  if (isset($configuration['exceptionHandler'])) {
752  $exceptionHandlerClassName = $configuration['exceptionHandler'];
753  }
754 
755  if ($exceptionHandlerClassName === '1') {
756  $exceptionHandlerClassName = ProductionExceptionHandler::class;
757  }
758 
759  return $exceptionHandlerClassName;
760  }
761 
769  protected function ‪mergeExceptionHandlerConfiguration($configuration)
770  {
771  $exceptionHandlerConfiguration = [];
772  $tsfe = $this->‪getTypoScriptFrontendController();
773  if (!empty($tsfe->config['config']['contentObjectExceptionHandler.'])) {
774  $exceptionHandlerConfiguration = $tsfe->config['config']['contentObjectExceptionHandler.'];
775  }
776  if (!empty($configuration['exceptionHandler.'])) {
777  $exceptionHandlerConfiguration = array_replace_recursive($exceptionHandlerConfiguration, $configuration['exceptionHandler.']);
778  }
779 
780  return $exceptionHandlerConfiguration;
781  }
782 
791  public function ‪getUserObjectType()
792  {
794  }
795 
802  {
803  $this->userObjectType = ‪$userObjectType;
804  }
805 
809  public function ‪convertToUserIntObject()
810  {
811  if ($this->userObjectType !== self::OBJECTTYPE_USER) {
812  $this->‪getTimeTracker()->‪setTSlogMessage(self::class . '::convertToUserIntObject() is called in the wrong context or for the wrong object type', LogLevel::WARNING);
813  } else {
814  $this->doConvertToUserIntObject = true;
815  }
816  }
817 
818  /************************************
819  *
820  * Various helper functions for content objects:
821  *
822  ************************************/
830  public function ‪readFlexformIntoConf($flexData, &$conf, $recursive = false)
831  {
832  if ($recursive === false && is_string($flexData)) {
833  $flexData = ‪GeneralUtility::xml2array($flexData, 'T3');
834  }
835  if (is_array($flexData) && isset($flexData['data']['sDEF']['lDEF'])) {
836  $flexData = $flexData['data']['sDEF']['lDEF'];
837  }
838  if (!is_array($flexData)) {
839  return;
840  }
841  foreach ($flexData as $key => $value) {
842  if (!is_array($value)) {
843  continue;
844  }
845  if (isset($value['el'])) {
846  if (is_array($value['el']) && !empty($value['el'])) {
847  foreach ($value['el'] as $ekey => $element) {
848  if (isset($element['vDEF'])) {
849  $conf[$ekey] = $element['vDEF'];
850  } else {
851  if (is_array($element)) {
852  $this->‪readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], true);
853  } else {
854  $this->‪readFlexformIntoConf($element, $conf[$key][$ekey], true);
855  }
856  }
857  }
858  } else {
859  $this->‪readFlexformIntoConf($value['el'], $conf[$key], true);
860  }
861  }
862  if (isset($value['vDEF'])) {
863  $conf[$key] = $value['vDEF'];
864  }
865  }
866  }
867 
876  public function ‪getSlidePids($pidList, $pidConf)
877  {
878  // todo: phpstan states that $pidConf always exists and is not nullable. At the moment, this is a false positive
879  // as null can be passed into this method via $pidConf. As soon as more strict types are used, this isset
880  // check must be replaced with a more appropriate check like empty or count.
881  $pidList = isset($pidConf) ? trim((string)$this->‪stdWrap($pidList, $pidConf)) : trim($pidList);
882  if ($pidList === '') {
883  $pidList = 'this';
884  }
885  $tsfe = $this->‪getTypoScriptFrontendController();
886  $listArr = null;
887  if (trim($pidList)) {
888  $listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $pidList));
889  $listArr = $this->‪checkPidArray($listArr);
890  }
891  $pidList = [];
892  if (is_array($listArr) && !empty($listArr)) {
893  foreach ($listArr as ‪$uid) {
894  $page = $tsfe->sys_page->getPage(‪$uid);
895  if (!$page['is_siteroot']) {
896  $pidList[] = $page['pid'];
897  }
898  }
899  }
900  return implode(',', $pidList);
901  }
902 
912  public function ‪imageLinkWrap($string, $imageFile, $conf)
913  {
914  $string = (string)$string;
915  $enable = $this->‪stdWrapValue('enable', $conf ?? []);
916  if (!$enable) {
917  return $string;
918  }
919  $content = (string)$this->‪typoLink($string, $conf['typolink.'] ?? []);
920  if (isset($conf['file.']) && is_scalar($imageFile)) {
921  $imageFile = $this->‪stdWrap((string)$imageFile, $conf['file.']);
922  }
923 
924  if ($imageFile instanceof File) {
925  $file = $imageFile;
926  } elseif ($imageFile instanceof FileReference) {
927  $file = $imageFile->getOriginalFile();
928  } else {
930  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObject((int)$imageFile);
931  } else {
932  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier($imageFile);
933  }
934  }
935 
936  // Create imageFileLink if not created with typolink
937  if ($content === $string && $file !== null) {
938  $parameterNames = ['width', 'height', 'effects', 'bodyTag', 'title', 'wrap', 'crop'];
939  ‪$parameters = [];
940  $sample = $this->‪stdWrapValue('sample', $conf ?? []);
941  if ($sample) {
942  ‪$parameters['sample'] = 1;
943  }
944  foreach ($parameterNames as $parameterName) {
945  if (isset($conf[$parameterName . '.'])) {
946  $conf[$parameterName] = $this->‪stdWrap($conf[$parameterName] ?? '', $conf[$parameterName . '.'] ?? []);
947  }
948  if (isset($conf[$parameterName]) && $conf[$parameterName]) {
949  ‪$parameters[$parameterName] = $conf[$parameterName];
950  }
951  }
952  $parametersEncoded = base64_encode((string)json_encode(‪$parameters));
953  $hmac = ‪GeneralUtility::hmac(implode('|', [$file->getUid(), $parametersEncoded]));
954  $params = '&md5=' . $hmac;
955  foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
956  $params .= '&parameters' . rawurlencode('[') . $index . rawurlencode(']') . '=' . rawurlencode($chunk);
957  }
958  ‪$url = $this->‪getTypoScriptFrontendController()->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . $file->getUid() . $params;
959  $directImageLink = $this->‪stdWrapValue('directImageLink', $conf ?? []);
960  if ($directImageLink) {
961  $imgResourceConf = [
962  'file' => $imageFile,
963  'file.' => $conf,
964  ];
965  ‪$url = $this->‪cObjGetSingle('IMG_RESOURCE', $imgResourceConf);
966  if (!‪$url) {
967  // If no imagemagick / gm is available
968  ‪$url = $imageFile;
969  }
970  }
971  $target = (string)$this->‪stdWrapValue('target', $conf ?? []);
972  if ($target === '') {
973  $target = 'thePicture';
974  }
975  $a1 = '';
976  $a2 = '';
977  $conf['JSwindow'] = $this->‪stdWrapValue('JSwindow', $conf ?? []);
978  if ($conf['JSwindow']) {
979  $altUrl = $this->‪stdWrapValue('altUrl', $conf['JSwindow.'] ?? []);
980  if ($altUrl) {
981  ‪$url = $altUrl . (($conf['JSwindow.']['altUrl_noDefaultParams'] ?? false) ? '' : '?file=' . rawurlencode((string)$imageFile) . $params);
982  }
983 
984  $processedFile = $file->process(‪ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $conf);
985  $JSwindowExpand = $this->‪stdWrapValue('expand', $conf['JSwindow.'] ?? []);
986  $offset = GeneralUtility::intExplode(',', $JSwindowExpand . ',');
987  $newWindow = $this->‪stdWrapValue('newWindow', $conf['JSwindow.'] ?? []);
988  $params = [
989  'width' => ($processedFile->getProperty('width') + $offset[0]),
990  'height' => ($processedFile->getProperty('height') + $offset[1]),
991  'status' => '0',
992  'menubar' => '0',
993  ];
994  // params override existing parameters from above, or add more
995  $windowParams = (string)$this->‪stdWrapValue('params', $conf['JSwindow.'] ?? []);
996  $windowParams = explode(',', $windowParams);
997  foreach ($windowParams as $windowParam) {
998  $windowParamParts = explode('=', $windowParam);
999  $paramKey = $windowParamParts[0];
1000  $paramValue = $windowParamParts[1] ?? null;
1001 
1002  if ($paramKey === '') {
1003  continue;
1004  }
1005 
1006  if ($paramValue !== '') {
1007  $params[$paramKey] = $paramValue;
1008  } else {
1009  unset($params[$paramKey]);
1010  }
1011  }
1012  $paramString = '';
1013  foreach ($params as $paramKey => $paramValue) {
1014  $paramString .= htmlspecialchars((string)$paramKey) . '=' . htmlspecialchars((string)$paramValue) . ',';
1015  }
1016 
1017  $attrs = [
1018  'href' => (string)‪$url,
1019  'data-window-url' => ‪$url,
1020  'data-window-target' => $newWindow ? md5((string)‪$url) : 'thePicture',
1021  'data-window-features' => rtrim($paramString, ','),
1022  ];
1023  if ($target !== '') {
1024  $attrs['target'] = $target;
1025  }
1026 
1027  $a1 = sprintf(
1028  '<a %s%s>',
1029  GeneralUtility::implodeAttributes($attrs, true),
1030  trim($this->‪getTypoScriptFrontendController()->config['config']['ATagParams'] ?? '') ? ' ' . trim($this->‪getTypoScriptFrontendController()->config['config']['ATagParams']) : ''
1031  );
1032  $a2 = '</a>';
1033  $this->addDefaultFrontendJavaScript();
1034  } else {
1035  $conf['linkParams.']['directImageLink'] = (bool)($conf['directImageLink'] ?? false);
1036  $conf['linkParams.']['parameter'] = ‪$url;
1037  $string = (string)$this->‪typoLink($string, $conf['linkParams.']);
1038  }
1039  if (isset($conf['stdWrap.'])) {
1040  $string = (string)$this->‪stdWrap($string, $conf['stdWrap.']);
1041  }
1042  $content = $a1 . $string . $a2;
1043  }
1044  return $content;
1045  }
1046 
1055  public function ‪lastChanged($tstamp)
1056  {
1057  $tstamp = (int)$tstamp;
1058  $tsfe = $this->‪getTypoScriptFrontendController();
1059  if ($tstamp > (int)($tsfe->register['SYS_LASTCHANGED'] ?? 0)) {
1060  $tsfe->register['SYS_LASTCHANGED'] = $tstamp;
1061  }
1062  }
1063 
1064  /***********************************************
1065  *
1066  * HTML template processing functions
1067  *
1068  ***********************************************/
1069 
1075  public function ‪setCurrentFile($fileObject)
1076  {
1077  $this->currentFile = $fileObject;
1078  }
1079 
1085  public function ‪getCurrentFile()
1086  {
1087  return ‪$this->currentFile;
1088  }
1089 
1090  /***********************************************
1091  *
1092  * "stdWrap" + sub functions
1093  *
1094  ***********************************************/
1104  public function ‪stdWrap($content = '', $conf = [])
1105  {
1106  $content = (string)$content;
1107  // If there is any hook object, activate all of the process and override functions.
1108  // The hook interface ContentObjectStdWrapHookInterface takes care that all 4 methods exist.
1109  if ($this->stdWrapHookObjects) {
1110  $conf['stdWrapPreProcess'] = 1;
1111  $conf['stdWrapOverride'] = 1;
1112  $conf['stdWrapProcess'] = 1;
1113  $conf['stdWrapPostProcess'] = 1;
1114  }
1115 
1116  if (!is_array($conf) || !$conf) {
1117  return $content;
1118  }
1119 
1120  // Cache handling
1121  if (isset($conf['cache.']) && is_array($conf['cache.'])) {
1122  $conf['cache.']['key'] = $this->‪stdWrapValue('key', $conf['cache.'] ?? []);
1123  $conf['cache.']['tags'] = $this->‪stdWrapValue('tags', $conf['cache.'] ?? []);
1124  $conf['cache.']['lifetime'] = $this->‪stdWrapValue('lifetime', $conf['cache.'] ?? []);
1125  $conf['cacheRead'] = 1;
1126  $conf['cacheStore'] = 1;
1127  }
1128  // The configuration is sorted and filtered by intersection with the defined stdWrapOrder.
1129  $sortedConf = array_keys(array_intersect_key($this->stdWrapOrder, $conf));
1130  // Functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
1131  $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
1132  // Additional Array to check whether a function has already been executed
1133  $isExecuted = [];
1134  // Additional switch to make sure 'required', 'if' and 'fieldRequired'
1135  // will still stop rendering immediately in case they return FALSE
1136  $this->stdWrapRecursionLevel++;
1137  $this->stopRendering[‪$this->stdWrapRecursionLevel] = false;
1138  // execute each function in the predefined order
1139  foreach ($sortedConf as $stdWrapName) {
1140  // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
1141  if ((!isset($isExecuted[$stdWrapName]) || !$isExecuted[$stdWrapName]) && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
1142  $functionName = rtrim($stdWrapName, '.');
1143  $functionProperties = $functionName . '.';
1144  $functionType = $this->stdWrapOrder[$functionName] ?? '';
1145  // If there is any code on the next level, check if it contains "official" stdWrap functions
1146  // if yes, execute them first - will make each function stdWrap aware
1147  // so additional stdWrap calls within the functions can be removed, since the result will be the same
1148  if (!empty($conf[$functionProperties]) && !‪GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
1149  if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
1150  // Check if there's already content available before processing
1151  // any ifEmpty or ifBlank stdWrap properties
1152  if (($functionName === 'ifBlank' && $content !== '') ||
1153  ($functionName === 'ifEmpty' && !empty(trim((string)$content)))) {
1154  continue;
1155  }
1156 
1157  $conf[$functionName] = $this->‪stdWrap($conf[$functionName] ?? '', $conf[$functionProperties]);
1158  }
1159  }
1160  // Check if key is still containing something, since it might have been changed by next level stdWrap before
1161  if ((isset($conf[$functionName]) || ($conf[$functionProperties] ?? null))
1162  && ($functionType !== 'boolean' || ($conf[$functionName] ?? null))
1163  ) {
1164  // Get just that part of $conf that is needed for the particular function
1165  $singleConf = [
1166  $functionName => $conf[$functionName] ?? null,
1167  $functionProperties => $conf[$functionProperties] ?? null,
1168  ];
1169  // Hand over the whole $conf array to the stdWrapHookObjects
1170  if ($functionType === 'hook') {
1171  $singleConf = $conf;
1172  }
1173  // Add both keys - with and without the dot - to the set of executed functions
1174  $isExecuted[$functionName] = true;
1175  $isExecuted[$functionProperties] = true;
1176  // Call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
1177  $functionName = 'stdWrap_' . $functionName;
1178  $content = $this->{$functionName}($content, $singleConf);
1179  } elseif ($functionType === 'boolean' && !($conf[$functionName] ?? null)) {
1180  $isExecuted[$functionName] = true;
1181  $isExecuted[$functionProperties] = true;
1182  }
1183  }
1184  }
1185  unset($this->stopRendering[$this->stdWrapRecursionLevel]);
1186  $this->stdWrapRecursionLevel--;
1187 
1188  return $content;
1189  }
1190 
1199  public function ‪stdWrapValue($key, array $config, $defaultValue = '')
1200  {
1201  if (isset($config[$key])) {
1202  if (!isset($config[$key . '.'])) {
1203  return $config[$key];
1204  }
1205  } elseif (isset($config[$key . '.'])) {
1206  $config[$key] = '';
1207  } else {
1208  return $defaultValue;
1209  }
1210  $stdWrapped = $this->‪stdWrap($config[$key], $config[$key . '.']);
1211  // The string "0" should be returned.
1212  return $stdWrapped !== '' ? $stdWrapped : $defaultValue;
1213  }
1214 
1224  public function ‪stdWrap_stdWrapPreProcess($content = '', $conf = [])
1225  {
1226  foreach ($this->stdWrapHookObjects as $hookObject) {
1228  $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
1229  }
1230  return $content;
1231  }
1232 
1240  public function ‪stdWrap_cacheRead($content = '', $conf = [])
1241  {
1242  if (!isset($conf['cache.'])) {
1243  return $content;
1244  }
1245  $result = $this->‪getFromCache($conf['cache.']);
1246  return $result === false ? $content : $result;
1247  }
1248 
1256  public function ‪stdWrap_addPageCacheTags($content = '', $conf = [])
1257  {
1258  $tags = (string)$this->‪stdWrapValue('addPageCacheTags', $conf ?? []);
1259  if (!empty($tags)) {
1260  $cacheTags = GeneralUtility::trimExplode(',', $tags, true);
1262  }
1263  return $content;
1264  }
1265 
1273  public function ‪stdWrap_setContentToCurrent($content = '')
1274  {
1275  $this->data[‪$this->currentValKey] = $content;
1276  return $content;
1277  }
1278 
1287  public function ‪stdWrap_setCurrent($content = '', $conf = [])
1288  {
1289  $this->data[‪$this->currentValKey] = $conf['setCurrent'] ?? null;
1290  return $content;
1291  }
1292 
1301  public function ‪stdWrap_lang($content = '', $conf = [])
1302  {
1303  $siteLanguage = $this->‪getTypoScriptFrontendController()->‪getLanguage();
1304  $currentLanguageCode = $siteLanguage->getTypo3Language();
1305  if (!$currentLanguageCode) {
1306  return $content;
1307  }
1308  if (isset($conf['lang.'][$currentLanguageCode])) {
1309  $content = $conf['lang.'][$currentLanguageCode];
1310  } else {
1311  // @todo: use the Locale object and its dependencies in TYPO3 v13
1312  // Check language dependencies
1313  $locales = GeneralUtility::makeInstance(Locales::class);
1314  foreach ($locales->getLocaleDependencies($currentLanguageCode) as $languageCode) {
1315  if (isset($conf['lang.'][$languageCode])) {
1316  $content = $conf['lang.'][$languageCode];
1317  break;
1318  }
1319  }
1320  }
1321  return $content;
1322  }
1323 
1331  public function ‪stdWrap_data($_ = '', $conf = [])
1332  {
1333  return $this->‪getData($conf['data'], $this->data);
1334  }
1335 
1344  public function ‪stdWrap_field($content = '', $conf = [])
1345  {
1346  return $this->‪getFieldVal($conf['field']);
1347  }
1348 
1358  public function ‪stdWrap_current($content = '', $conf = [])
1359  {
1360  return $this->‪getCurrentVal();
1361  }
1362 
1372  public function ‪stdWrap_cObject($content = '', $conf = [])
1373  {
1374  return $this->‪cObjGetSingle($conf['cObject'] ?? '', $conf['cObject.'] ?? [], '/stdWrap/.cObject');
1375  }
1376 
1386  public function ‪stdWrap_numRows($content = '', $conf = [])
1387  {
1388  return $this->‪numRows($conf['numRows.']);
1389  }
1390 
1399  public function ‪stdWrap_preUserFunc($content = '', $conf = [])
1400  {
1401  return $this->‪callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'] ?? [], $content);
1402  }
1403 
1413  public function ‪stdWrap_stdWrapOverride($content = '', $conf = [])
1414  {
1415  foreach ($this->stdWrapHookObjects as $hookObject) {
1417  $content = $hookObject->stdWrapOverride($content, $conf, $this);
1418  }
1419  return $content;
1420  }
1421 
1430  public function ‪stdWrap_override($content = '', $conf = [])
1431  {
1432  if (trim($conf['override'] ?? false)) {
1433  $content = $conf['override'];
1434  }
1435  return $content;
1436  }
1437 
1447  public function ‪stdWrap_preIfEmptyListNum($content = '', $conf = [])
1448  {
1449  return $this->‪listNum($content, $conf['preIfEmptyListNum'] ?? '0', $conf['preIfEmptyListNum.']['splitChar'] ?? ',');
1450  }
1451 
1460  public function ‪stdWrap_ifNull($content = '', $conf = [])
1461  {
1462  return $content ?? $conf['ifNull'];
1463  }
1464 
1474  public function ‪stdWrap_ifEmpty($content = '', $conf = [])
1475  {
1476  if (empty(trim((string)$content))) {
1477  $content = $conf['ifEmpty'];
1478  }
1479  return $content;
1480  }
1481 
1491  public function ‪stdWrap_ifBlank($content = '', $conf = [])
1492  {
1493  if (trim((string)$content) === '') {
1494  $content = $conf['ifBlank'];
1495  }
1496  return $content;
1497  }
1498 
1509  public function ‪stdWrap_listNum($content = '', $conf = [])
1510  {
1511  return $this->‪listNum($content, $conf['listNum'] ?? '0', $conf['listNum.']['splitChar'] ?? ',');
1512  }
1513 
1521  public function ‪stdWrap_trim($content = '')
1522  {
1523  return trim((string)$content);
1524  }
1525 
1534  public function ‪stdWrap_strPad($content = '', $conf = [])
1535  {
1536  // Must specify a length in conf for this to make sense
1537  $length = (int)$this->‪stdWrapValue('length', $conf['strPad.'] ?? [], 0);
1538  // Padding with space is PHP-default
1539  $padWith = (string)$this->‪stdWrapValue('padWith', $conf['strPad.'] ?? [], ' ');
1540  // Padding on the right side is PHP-default
1541  $padType = STR_PAD_RIGHT;
1542 
1543  if (!empty($conf['strPad.']['type'])) {
1544  $type = (string)$this->‪stdWrapValue('type', $conf['strPad.'] ?? []);
1545  if (strtolower($type) === 'left') {
1546  $padType = STR_PAD_LEFT;
1547  } elseif (strtolower($type) === 'both') {
1548  $padType = STR_PAD_BOTH;
1549  }
1550  }
1551  return ‪StringUtility::multibyteStringPad($content, $length, $padWith, $padType);
1552  }
1553 
1565  public function ‪stdWrap_stdWrap($content = '', $conf = [])
1566  {
1567  return $this->‪stdWrap($content, $conf['stdWrap.']);
1568  }
1569 
1579  public function ‪stdWrap_stdWrapProcess($content = '', $conf = [])
1580  {
1581  foreach ($this->stdWrapHookObjects as $hookObject) {
1583  $content = $hookObject->stdWrapProcess($content, $conf, $this);
1584  }
1585  return $content;
1586  }
1587 
1596  public function ‪stdWrap_required($content = '')
1597  {
1598  if ((string)$content === '') {
1599  $content = '';
1600  $this->stopRendering[‪$this->stdWrapRecursionLevel] = true;
1601  }
1602  return $content;
1603  }
1604 
1614  public function ‪stdWrap_if($content = '', $conf = [])
1615  {
1616  if (empty($conf['if.']) || $this->‪checkIf($conf['if.'])) {
1617  return $content;
1618  }
1619  $this->stopRendering[‪$this->stdWrapRecursionLevel] = true;
1620  return '';
1621  }
1622 
1632  public function ‪stdWrap_fieldRequired($content = '', $conf = [])
1633  {
1634  if (!trim($this->data[$conf['fieldRequired'] ?? null] ?? '')) {
1635  $content = '';
1636  $this->stopRendering[‪$this->stdWrapRecursionLevel] = true;
1637  }
1638  return $content;
1639  }
1640 
1651  public function ‪stdWrap_csConv($content = '', $conf = [])
1652  {
1653  if (!empty($conf['csConv'])) {
1654  ‪$output = mb_convert_encoding($content, 'utf-8', trim(strtolower($conf['csConv'])));
1655  return ‪$output !== false && ‪$output !== '' ? ‪$output : $content;
1656  }
1657  return $content;
1658  }
1659 
1669  public function ‪stdWrap_parseFunc($content = '', $conf = [])
1670  {
1671  return $this->‪parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
1672  }
1673 
1683  public function ‪stdWrap_HTMLparser($content = '', $conf = [])
1684  {
1685  if (isset($conf['HTMLparser.']) && is_array($conf['HTMLparser.'])) {
1686  $content = $this->‪HTMLparser_TSbridge($content, $conf['HTMLparser.']);
1687  }
1688  return $content;
1689  }
1690 
1700  public function ‪stdWrap_split($content = '', $conf = [])
1701  {
1702  return $this->‪splitObj($content, $conf['split.']);
1703  }
1704 
1713  public function ‪stdWrap_replacement($content = '', $conf = [])
1714  {
1715  return $this->‪replacement($content, $conf['replacement.']);
1716  }
1717 
1727  public function ‪stdWrap_prioriCalc($content = '', $conf = [])
1728  {
1730  if (!empty($conf['prioriCalc']) && $conf['prioriCalc'] === 'intval') {
1731  $content = (int)$content;
1732  }
1733  return $content;
1734  }
1735 
1747  public function ‪stdWrap_char($content = '', $conf = [])
1748  {
1749  return chr((int)$conf['char']);
1750  }
1751 
1759  public function ‪stdWrap_intval($content = '')
1760  {
1761  return (int)$content;
1762  }
1763 
1772  public function ‪stdWrap_hash($content = '', array $conf = [])
1773  {
1774  $algorithm = (string)$this->‪stdWrapValue('hash', $conf ?? []);
1775  if (in_array($algorithm, hash_algos())) {
1776  return hash($algorithm, $content);
1777  }
1778  // Non-existing hashing algorithm
1779  return '';
1780  }
1781 
1790  public function ‪stdWrap_round($content = '', $conf = [])
1791  {
1792  return $this->‪round($content, $conf['round.']);
1793  }
1794 
1803  public function ‪stdWrap_numberFormat($content = '', $conf = [])
1804  {
1805  return $this->‪numberFormat((float)$content, $conf['numberFormat.'] ?? []);
1806  }
1807 
1815  public function ‪stdWrap_expandList($content = '')
1816  {
1817  return ‪GeneralUtility::expandList($content);
1818  }
1819 
1829  public function ‪stdWrap_date($content = '', $conf = [])
1830  {
1831  // Check for zero length string to mimic default case of date/gmdate.
1832  $content = (string)$content === '' ? ‪$GLOBALS['EXEC_TIME'] : (int)$content;
1833  $content = !empty($conf['date.']['GMT']) ? gmdate($conf['date'] ?? null, $content) : date($conf['date'] ?? null, $content);
1834  return $content;
1835  }
1836 
1846  public function ‪stdWrap_strftime($content = '', $conf = [])
1847  {
1848  // Check for zero length string to mimic default case of strtime/gmstrftime
1849  $content = (string)$content === '' ? ‪$GLOBALS['EXEC_TIME'] : (int)$content;
1850  $content = (isset($conf['strftime.']['GMT']) && $conf['strftime.']['GMT'])
1851  ? (new ‪DateFormatter())->strftime($conf['strftime'] ?? '', $content, null, true)
1852  : (new ‪DateFormatter())->strftime($conf['strftime'] ?? '', $content);
1853  if (!empty($conf['strftime.']['charset'])) {
1854  ‪$output = mb_convert_encoding((string)$content, 'utf-8', trim(strtolower($conf['strftime.']['charset'])));
1855  return ‪$output ?: $content;
1856  }
1857  return $content;
1858  }
1859 
1868  public function ‪stdWrap_strtotime($content = '', $conf = [])
1869  {
1870  if ($conf['strtotime'] !== '1') {
1871  $content .= ' ' . $conf['strtotime'];
1872  }
1873  return strtotime($content, ‪$GLOBALS['EXEC_TIME']);
1874  }
1875 
1885  public function ‪stdWrap_formattedDate(string $content, array $conf): string
1886  {
1887  $pattern = $conf['formattedDate'] ?? 'LONG';
1888  $locale = $conf['formattedDate.']['locale'] ?? $this->‪getTypoScriptFrontendController()->‪getLanguage()->getLocale();
1889 
1890  if ($content === '' || $content === '0') {
1891  $content = $this->‪getTypoScriptFrontendController()->‪getContext()->getAspect('date')->getDateTime();
1892  } else {
1893  // format this to a timestamp now
1894  $content = strtotime((‪MathUtility::canBeInterpretedAsInteger($content) ? '@' : '') . $content);
1895  if ($content === false) {
1896  $content = $this->‪getTypoScriptFrontendController()->‪getContext()->getAspect('date')->getDateTime();
1897  }
1898  }
1899  return (new DateFormatter())->format($content, $pattern, $locale);
1900  }
1901 
1910  public function ‪stdWrap_age($content = '', $conf = [])
1911  {
1912  return $this->‪calcAge((int)(‪$GLOBALS['EXEC_TIME'] ?? 0) - (int)$content, $conf['age'] ?? null);
1913  }
1914 
1924  public function ‪stdWrap_case($content = '', $conf = [])
1925  {
1926  return $this->‪HTMLcaseshift($content, $conf['case']);
1927  }
1928 
1937  public function ‪stdWrap_bytes($content = '', $conf = [])
1938  {
1939  return GeneralUtility::formatSize((int)$content, $conf['bytes.']['labels'] ?? '', $conf['bytes.']['base'] ?? 0);
1940  }
1941 
1950  public function ‪stdWrap_substring($content = '', $conf = [])
1951  {
1952  return $this->‪substring($content, $conf['substring']);
1953  }
1954 
1963  public function ‪stdWrap_cropHTML($content = '', $conf = [])
1964  {
1965  return $this->‪cropHTML($content, $conf['cropHTML'] ?? '');
1966  }
1967 
1975  public function ‪stdWrap_stripHtml($content = '')
1976  {
1977  return strip_tags($content);
1978  }
1979 
1988  public function ‪stdWrap_crop($content = '', $conf = [])
1989  {
1990  return $this->‪crop($content, $conf['crop']);
1991  }
1992 
2000  public function ‪stdWrap_rawUrlEncode($content = '')
2001  {
2002  return rawurlencode($content);
2003  }
2004 
2014  public function ‪stdWrap_htmlSpecialChars($content = '', $conf = [])
2015  {
2016  if (!empty($conf['htmlSpecialChars.']['preserveEntities'])) {
2017  $content = htmlspecialchars($content, ENT_COMPAT, 'UTF-8', false);
2018  } else {
2019  $content = htmlspecialchars($content);
2020  }
2021  return $content;
2022  }
2023 
2031  public function ‪stdWrap_encodeForJavaScriptValue($content = '')
2032  {
2033  return GeneralUtility::quoteJSvalue($content);
2034  }
2035 
2044  public function ‪stdWrap_doubleBrTag($content = '', $conf = [])
2045  {
2046  return preg_replace('/\R{1,2}[\t\x20]*\R{1,2}/', $conf['doubleBrTag'] ?? '', $content);
2047  }
2048 
2057  public function ‪stdWrap_br($content = '')
2058  {
2059  $docType = GeneralUtility::makeInstance(PageRenderer::class)->getDocType();
2060  return nl2br($content, $docType->isXmlCompliant());
2061  }
2062 
2071  public function ‪stdWrap_brTag($content = '', $conf = [])
2072  {
2073  return str_replace(LF, (string)($conf['brTag'] ?? ''), $content);
2074  }
2075 
2085  public function ‪stdWrap_encapsLines($content = '', $conf = [])
2086  {
2087  return $this->‪encaps_lineSplit($content, $conf['encapsLines.']);
2088  }
2089 
2097  public function ‪stdWrap_keywords($content = '')
2098  {
2099  return $this->‪keywords($content);
2100  }
2101 
2111  public function ‪stdWrap_innerWrap($content = '', $conf = [])
2112  {
2113  return $this->‪wrap($content, $conf['innerWrap'] ?? null);
2114  }
2115 
2125  public function ‪stdWrap_innerWrap2($content = '', $conf = [])
2126  {
2127  return $this->‪wrap($content, $conf['innerWrap2'] ?? null);
2128  }
2129 
2138  public function ‪stdWrap_preCObject($content = '', $conf = [])
2139  {
2140  return $this->‪cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content;
2141  }
2142 
2151  public function ‪stdWrap_postCObject($content = '', $conf = [])
2152  {
2153  return $content . $this->‪cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject');
2154  }
2155 
2165  public function ‪stdWrap_wrapAlign($content = '', $conf = [])
2166  {
2167  $wrapAlign = trim($conf['wrapAlign'] ?? '');
2168  if ($wrapAlign) {
2169  $content = $this->‪wrap($content, '<div style="text-align:' . htmlspecialchars($wrapAlign) . ';">|</div>');
2170  }
2171  return $content;
2172  }
2173 
2184  public function ‪stdWrap_typolink($content = '', $conf = [])
2185  {
2186  return $this->‪typoLink((string)$content, $conf['typolink.'] ?? []);
2187  }
2188 
2201  public function ‪stdWrap_wrap($content = '', $conf = [])
2202  {
2203  return $this->‪wrap(
2204  $content,
2205  $conf['wrap'] ?? null,
2206  $conf['wrap.']['splitChar'] ?? '|'
2207  );
2208  }
2209 
2219  public function ‪stdWrap_noTrimWrap($content = '', $conf = [])
2220  {
2221  $splitChar = isset($conf['noTrimWrap.']['splitChar.'])
2222  ? $this->‪stdWrap($conf['noTrimWrap.']['splitChar'] ?? '', $conf['noTrimWrap.']['splitChar.'])
2223  : $conf['noTrimWrap.']['splitChar'] ?? '';
2224  if ($splitChar === null || $splitChar === '') {
2225  $splitChar = '|';
2226  }
2227  $content = $this->‪noTrimWrap(
2228  $content,
2229  $conf['noTrimWrap'],
2230  $splitChar
2231  );
2232  return $content;
2233  }
2234 
2244  public function ‪stdWrap_wrap2($content = '', $conf = [])
2245  {
2246  return $this->‪wrap(
2247  $content,
2248  $conf['wrap2'] ?? null,
2249  $conf['wrap2.']['splitChar'] ?? '|'
2250  );
2251  }
2252 
2262  public function ‪stdWrap_dataWrap($content = '', $conf = [])
2263  {
2264  return $this->‪dataWrap($content, $conf['dataWrap']);
2265  }
2266 
2275  public function ‪stdWrap_prepend($content = '', $conf = [])
2276  {
2277  return $this->‪cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content;
2278  }
2279 
2288  public function ‪stdWrap_append($content = '', $conf = [])
2289  {
2290  return $content . $this->‪cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append');
2291  }
2292 
2302  public function ‪stdWrap_wrap3($content = '', $conf = [])
2303  {
2304  return $this->‪wrap(
2305  $content,
2306  $conf['wrap3'] ?? null,
2307  $conf['wrap3.']['splitChar'] ?? '|'
2308  );
2309  }
2310 
2319  public function ‪stdWrap_orderedStdWrap($content = '', $conf = [])
2320  {
2321  $sortedKeysArray = ArrayUtility::filterAndSortByNumericKeys($conf['orderedStdWrap.'], true);
2322  foreach ($sortedKeysArray as $key) {
2323  $content = (string)$this->‪stdWrap($content, $conf['orderedStdWrap.'][$key . '.'] ?? null);
2324  }
2325  return $content;
2326  }
2327 
2336  public function ‪stdWrap_outerWrap($content = '', $conf = [])
2337  {
2338  return $this->‪wrap($content, $conf['outerWrap'] ?? null);
2339  }
2340 
2348  public function ‪stdWrap_insertData($content = '')
2349  {
2350  return $this->‪insertData($content);
2351  }
2352 
2361  public function ‪stdWrap_postUserFunc($content = '', $conf = [])
2362  {
2363  return $this->‪callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'] ?? [], $content);
2364  }
2365 
2375  public function ‪stdWrap_postUserFuncInt($content = '', $conf = [])
2376  {
2377  $substKey = 'INT_SCRIPT.' . $this->‪getTypoScriptFrontendController()->‪uniqueHash();
2378  $this->‪getTypoScriptFrontendController()->config['INTincScript'][$substKey] = [
2379  'content' => $content,
2380  'postUserFunc' => $conf['postUserFuncInt'],
2381  'conf' => $conf['postUserFuncInt.'],
2382  'type' => 'POSTUSERFUNC',
2383  'cObj' => serialize($this),
2384  ];
2385  $content = '<!--' . $substKey . '-->';
2386  return $content;
2387  }
2388 
2397  public function ‪stdWrap_prefixComment($content = '', $conf = [])
2398  {
2399  if (
2400  (!isset($this->‪getTypoScriptFrontendController()->config['config']['disablePrefixComment']) || !$this->‪getTypoScriptFrontendController()->config['config']['disablePrefixComment'])
2401  && !empty($conf['prefixComment'])
2402  ) {
2403  $content = $this->‪prefixComment($conf['prefixComment'], [], $content);
2404  }
2405  return $content;
2406  }
2407 
2408  public function ‪stdWrap_htmlSanitize(string $content = '', array $conf = []): string
2409  {
2410  $build = $conf['build'] ?? 'default';
2411  if (class_exists($build) && is_a($build, BuilderInterface::class, true)) {
2412  $builder = GeneralUtility::makeInstance($build);
2413  } else {
2414  $factory = GeneralUtility::makeInstance(SanitizerBuilderFactory::class);
2415  $builder = $factory->build($build);
2416  }
2417  $sanitizer = $builder->build();
2418  $initiator = $this->‪shallDebug()
2419  ? GeneralUtility::makeInstance(SanitizerInitiator::class, ‪DebugUtility::debugTrail())
2420  : null;
2421  return $sanitizer->sanitize($content, $initiator);
2422  }
2423 
2431  public function ‪stdWrap_cacheStore($content = '', $conf = [])
2432  {
2433  if (!isset($conf['cache.'])) {
2434  return $content;
2435  }
2436  $key = $this->‪calculateCacheKey($conf['cache.']);
2437  if (empty($key)) {
2438  return $content;
2439  }
2440  $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('hash');
2441  $tags = $this->‪calculateCacheTags($conf['cache.']);
2442  $lifetime = $this->‪calculateCacheLifetime($conf['cache.']);
2443  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'] ?? [] as $_funcRef) {
2444  $params = [
2445  'key' => $key,
2446  'content' => $content,
2447  'lifetime' => $lifetime,
2448  'tags' => $tags,
2449  ];
2450  $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
2451  GeneralUtility::callUserFunction($_funcRef, $params, $ref);
2452  }
2453  $cachedData = [
2454  'content' => $content,
2455  'cacheTags' => $tags,
2456  ];
2457  $cacheFrontend->set($key, $cachedData, $tags, $lifetime);
2459  return $content;
2460  }
2461 
2471  public function ‪stdWrap_stdWrapPostProcess($content = '', $conf = [])
2472  {
2473  foreach ($this->stdWrapHookObjects as $hookObject) {
2475  $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
2476  }
2477  return $content;
2478  }
2479 
2487  public function ‪stdWrap_debug($content = '')
2488  {
2489  return '<pre>' . htmlspecialchars($content) . '</pre>';
2490  }
2491 
2500  public function ‪stdWrap_debugFunc($content = '', $conf = [])
2501  {
2502  ‪debug((int)$conf['debugFunc'] === 2 ? [$content] : $content);
2503  return $content;
2504  }
2505 
2513  public function ‪stdWrap_debugData($content = '')
2514  {
2515  ‪debug($this->data, '$cObj->data:');
2516  return $content;
2517  }
2518 
2528  public function ‪numRows($conf)
2529  {
2530  $conf['select.']['selectFields'] = 'count(*)';
2531  $statement = $this->‪exec_getQuery($conf['table'], $conf['select.']);
2532 
2533  return (int)$statement->fetchOne();
2534  }
2535 
2544  public function ‪listNum($content, $listNum, $delimeter = ',')
2545  {
2546  $delimeter = $delimeter ?: ',';
2548  $delimeter = chr((int)$delimeter);
2549  }
2550  $temp = explode($delimeter, $content);
2551  if (empty($temp)) {
2552  return '';
2553  }
2554  $last = '' . (count($temp) - 1);
2555  // Take a random item if requested
2556  if ($listNum === 'rand') {
2557  $listNum = (string)random_int(0, count($temp) - 1);
2558  }
2559  $index = $this->‪calc(str_ireplace('last', $last, $listNum));
2560  return $temp[$index] ?? '';
2561  }
2562 
2569  public function ‪checkIf($conf): bool
2570  {
2571  if (!is_array($conf)) {
2572  return true;
2573  }
2574  if (isset($conf['directReturn'])) {
2575  return (bool)$conf['directReturn'];
2576  }
2577  $flag = true;
2578  if (isset($conf['isNull.'])) {
2579  $isNull = $this->‪stdWrap('', $conf['isNull.']);
2580  if ($isNull !== null) {
2581  $flag = false;
2582  }
2583  }
2584  if (isset($conf['isTrue']) || isset($conf['isTrue.'])) {
2585  $isTrue = trim((string)$this->‪stdWrapValue('isTrue', $conf));
2586  if (!$isTrue) {
2587  $flag = false;
2588  }
2589  }
2590  if (isset($conf['isFalse']) || isset($conf['isFalse.'])) {
2591  $isFalse = trim((string)$this->‪stdWrapValue('isFalse', $conf));
2592  if ($isFalse) {
2593  $flag = false;
2594  }
2595  }
2596  if (isset($conf['isPositive']) || isset($conf['isPositive.'])) {
2597  $number = $this->‪calc((string)$this->‪stdWrapValue('isPositive', $conf));
2598  if ($number < 1) {
2599  $flag = false;
2600  }
2601  }
2602  if ($flag) {
2603  $comparisonValue = trim((string)$this->‪stdWrapValue('value', $conf));
2604  if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) {
2605  $number = trim((string)$this->‪stdWrapValue('isGreaterThan', $conf));
2606  if ($number <= $comparisonValue) {
2607  $flag = false;
2608  }
2609  }
2610  if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) {
2611  $number = trim((string)$this->‪stdWrapValue('isLessThan', $conf));
2612  if ($number >= $comparisonValue) {
2613  $flag = false;
2614  }
2615  }
2616  if (isset($conf['equals']) || isset($conf['equals.'])) {
2617  $number = trim((string)$this->‪stdWrapValue('equals', $conf));
2618  if ($number != $comparisonValue) {
2619  $flag = false;
2620  }
2621  }
2622  if (isset($conf['contains']) || isset($conf['contains.'])) {
2623  $needle = trim((string)$this->‪stdWrapValue('contains', $conf));
2624  if (!str_contains($comparisonValue, $needle)) {
2625  $flag = false;
2626  }
2627  }
2628  if (isset($conf['startsWith']) || isset($conf['startsWith.'])) {
2629  $needle = trim((string)$this->‪stdWrapValue('startsWith', $conf));
2630  if (!str_starts_with($comparisonValue, $needle)) {
2631  $flag = false;
2632  }
2633  }
2634  if (isset($conf['endsWith']) || isset($conf['endsWith.'])) {
2635  $needle = trim((string)$this->‪stdWrapValue('endsWith', $conf));
2636  if (!str_ends_with($comparisonValue, $needle)) {
2637  $flag = false;
2638  }
2639  }
2640  if (isset($conf['isInList']) || isset($conf['isInList.'])) {
2641  $singleValueWhichNeedsToBeInList = trim((string)$this->‪stdWrapValue('isInList', $conf));
2642  if (!‪GeneralUtility::inList($comparisonValue, $singleValueWhichNeedsToBeInList)) {
2643  $flag = false;
2644  }
2645  }
2646  if (isset($conf['bitAnd']) || isset($conf['bitAnd.'])) {
2647  $number = (int)trim((string)$this->‪stdWrapValue('bitAnd', $conf));
2648  if ((new BitSet($number))->get($comparisonValue) === false) {
2649  $flag = false;
2650  }
2651  }
2652  }
2653  if ($conf['negate'] ?? false) {
2654  $flag = !$flag;
2655  }
2656  return $flag;
2657  }
2658 
2671  public function ‪HTMLparser_TSbridge($theValue, $conf)
2672  {
2673  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
2674  $htmlParserCfg = $htmlParser->HTMLparserConfig($conf);
2675  return $htmlParser->HTMLcleaner($theValue, $htmlParserCfg[0], $htmlParserCfg[1], $htmlParserCfg[2], $htmlParserCfg[3]);
2676  }
2677 
2687  public function ‪dataWrap($content, $wrap)
2688  {
2689  return $this->‪wrap($content, $this->‪insertData($wrap));
2690  }
2691 
2707  public function ‪insertData($str)
2708  {
2709  $inside = 0;
2710  $newVal = '';
2711  $pointer = 0;
2712  $totalLen = strlen($str);
2713  do {
2714  if (!$inside) {
2715  $len = strcspn(substr($str, $pointer), '{');
2716  $newVal .= substr($str, $pointer, $len);
2717  $inside = true;
2718  if (substr($str, $pointer + $len + 1, 1) === '#') {
2719  $len2 = strcspn(substr($str, $pointer + $len), '}');
2720  $newVal .= substr($str, $pointer + $len, $len2);
2721  $len += $len2;
2722  $inside = false;
2723  }
2724  } else {
2725  $len = strcspn(substr($str, $pointer), '}') + 1;
2726  $newVal .= $this->‪getData(substr($str, $pointer + 1, $len - 2), $this->data);
2727  $inside = false;
2728  }
2729  $pointer += $len;
2730  } while ($pointer < $totalLen);
2731  return $newVal;
2732  }
2733 
2744  public function ‪prefixComment($str, $conf, $content)
2745  {
2746  if (empty($str)) {
2747  return $content;
2748  }
2749  $parts = explode('|', $str);
2750  $indent = (int)$parts[0];
2751  $comment = htmlspecialchars($this->‪insertData($parts[1]));
2752  ‪$output = LF
2753  . str_pad('', $indent, "\t") . '<!-- ' . $comment . ' [begin] -->' . LF
2754  . str_pad('', $indent + 1, "\t") . $content . LF
2755  . str_pad('', $indent, "\t") . '<!-- ' . $comment . ' [end] -->' . LF
2756  . str_pad('', $indent + 1, "\t");
2757  return ‪$output;
2758  }
2759 
2769  public function ‪substring($content, $options)
2770  {
2771  $options = GeneralUtility::intExplode(',', $options . ',');
2772  if ($options[1]) {
2773  return mb_substr($content, $options[0], $options[1], 'utf-8');
2774  }
2775  return mb_substr($content, $options[0], null, 'utf-8');
2776  }
2777 
2787  public function ‪crop($content, $options)
2788  {
2789  $options = explode('|', $options);
2790  $numberOfChars = (int)$options[0];
2791  $replacementForEllipsis = trim($options[1] ?? '');
2792  $cropToSpace = trim($options[2] ?? '') === '1';
2793  return GeneralUtility::makeInstance(TextCropper::class)
2794  ->crop(
2795  content: $content,
2796  numberOfChars: $numberOfChars,
2797  replacementForEllipsis: $replacementForEllipsis,
2798  cropToSpace: $cropToSpace
2799  );
2800  }
2801 
2815  public function ‪cropHTML(string $content, string $options): string
2816  {
2817  $options = explode('|', $options);
2818  $numberOfChars = (int)$options[0];
2819  $replacementForEllipsis = trim($options[1] ?? '');
2820  $cropToSpace = trim($options[2] ?? '') === '1';
2821  return GeneralUtility::makeInstance(HtmlCropper::class)
2822  ->crop(
2823  content: $content,
2824  numberOfChars: $numberOfChars,
2825  replacementForEllipsis: $replacementForEllipsis,
2826  cropToSpace: $cropToSpace
2827  );
2828  }
2829 
2837  public function ‪calc($val)
2838  {
2839  $parts = GeneralUtility::splitCalc($val, '+-*/');
2840  $value = 0;
2841  foreach ($parts as $part) {
2842  $theVal = $part[1];
2843  $sign = $part[0];
2844  if ((string)(int)$theVal === (string)$theVal) {
2845  $theVal = (int)$theVal;
2846  } else {
2847  $theVal = 0;
2848  }
2849  if ($sign === '-') {
2850  $value -= $theVal;
2851  }
2852  if ($sign === '+') {
2853  $value += $theVal;
2854  }
2855  if ($sign === '/') {
2856  if ((int)$theVal) {
2857  $value /= (int)$theVal;
2858  }
2859  }
2860  if ($sign === '*') {
2861  $value *= $theVal;
2862  }
2863  }
2864  return $value;
2865  }
2866 
2879  public function ‪splitObj($value, $conf)
2880  {
2881  $conf['token'] = isset($conf['token.']) ? $this->‪stdWrap($conf['token'] ?? '', $conf['token.']) : $conf['token'] ?? '';
2882  if ($conf['token'] === '') {
2883  return $value;
2884  }
2885  $valArr = explode($conf['token'], $value);
2886 
2887  // return value directly by returnKey. No further processing
2888  if (!empty($valArr) && (‪MathUtility::canBeInterpretedAsInteger($conf['returnKey'] ?? null) || ($conf['returnKey.'] ?? false))) {
2889  $key = (int)$this->‪stdWrapValue('returnKey', $conf ?? []);
2890  return $valArr[$key] ?? '';
2891  }
2892 
2893  // return the amount of elements. No further processing
2894  if (!empty($valArr) && (($conf['returnCount'] ?? false) || ($conf['returnCount.'] ?? false))) {
2895  $returnCount = (bool)$this->‪stdWrapValue('returnCount', $conf ?? []);
2896  return $returnCount ? count($valArr) : 0;
2897  }
2898 
2899  // calculate splitCount
2900  $splitCount = count($valArr);
2901  $max = (int)$this->‪stdWrapValue('max', $conf ?? []);
2902  if ($max && $splitCount > $max) {
2903  $splitCount = $max;
2904  }
2905  $min = (int)$this->‪stdWrapValue('min', $conf ?? []);
2906  if ($min && $splitCount < $min) {
2907  $splitCount = $min;
2908  }
2909  $wrap = (string)$this->‪stdWrapValue('wrap', $conf ?? []);
2910  $cObjNumSplitConf = isset($conf['cObjNum.']) ? $this->‪stdWrap($conf['cObjNum'] ?? '', $conf['cObjNum.'] ?? []) : (string)($conf['cObjNum'] ?? '');
2911  $splitArr = [];
2912  if ($wrap !== '' || $cObjNumSplitConf !== '') {
2913  $splitArr['wrap'] = $wrap;
2914  $splitArr['cObjNum'] = $cObjNumSplitConf;
2915  $splitArr = GeneralUtility::makeInstance(TypoScriptService::class)
2916  ->explodeConfigurationForOptionSplit($splitArr, $splitCount);
2917  }
2918  $content = '';
2919  for ($a = 0; $a < $splitCount; $a++) {
2920  $this->‪getTypoScriptFrontendController()->register['SPLIT_COUNT'] = $a;
2921  $value = '' . $valArr[$a];
2922  $this->data[‪$this->currentValKey] = $value;
2923  if ($splitArr[$a]['cObjNum'] ?? false) {
2924  $objName = (int)$splitArr[$a]['cObjNum'];
2925  $value = (string)(isset($conf[$objName . '.'])
2926  ? $this->‪stdWrap($this->‪cObjGet($conf[$objName . '.'], $objName . '.'), $conf[$objName . '.'])
2927  : '');
2928  }
2929  $wrap = (string)$this->‪stdWrapValue('wrap', $splitArr[$a] ?? []);
2930  if ($wrap) {
2931  $value = $this->‪wrap($value, $wrap);
2932  }
2933  $content .= $value;
2934  }
2935  return $content;
2936  }
2937 
2945  protected function ‪replacement($content, array $configuration)
2946  {
2947  // Sorts actions in configuration by numeric index
2948  ksort($configuration, SORT_NUMERIC);
2949  foreach ($configuration as $index => $action) {
2950  // Checks whether we have a valid action and a numeric key ending with a dot ("10.")
2951  if (is_array($action) && substr($index, -1) === '.' && ‪MathUtility::canBeInterpretedAsInteger(substr($index, 0, -1))) {
2952  $content = $this->‪replacementSingle($content, $action);
2953  }
2954  }
2955  return $content;
2956  }
2957 
2965  protected function ‪replacementSingle($content, array $configuration)
2966  {
2967  if ((isset($configuration['search']) || isset($configuration['search.'])) && (isset($configuration['replace']) || isset($configuration['replace.']))) {
2968  // Gets the strings
2969  $search = (string)$this->‪stdWrapValue('search', $configuration ?? []);
2970  $replace = (string)$this->‪stdWrapValue('replace', $configuration, null);
2971 
2972  // Determines whether regular expression shall be used
2973  $useRegularExpression = (bool)$this->‪stdWrapValue('useRegExp', $configuration, false);
2974 
2975  // Determines whether replace-pattern uses option-split
2976  $useOptionSplitReplace = (bool)$this->‪stdWrapValue('useOptionSplitReplace', $configuration, false);
2977 
2978  // Performs a replacement by preg_replace()
2979  if ($useRegularExpression) {
2980  // Get separator-character which precedes the string and separates search-string from the modifiers
2981  $separator = $search[0];
2982  $startModifiers = strrpos($search, $separator);
2983  if ($separator !== false && $startModifiers > 0) {
2984  $modifiers = substr($search, $startModifiers + 1);
2985  // remove "e" (eval-modifier), which would otherwise allow to run arbitrary PHP-code
2986  $modifiers = str_replace('e', '', $modifiers);
2987  $search = substr($search, 0, $startModifiers + 1) . $modifiers;
2988  }
2989  if ($useOptionSplitReplace) {
2990  // init for replacement
2991  $splitCount = preg_match_all($search, $content, $matches);
2992  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
2993  $replaceArray = $typoScriptService->explodeConfigurationForOptionSplit([$replace], $splitCount);
2994  $replaceCount = 0;
2995 
2996  $replaceCallback = static function ($match) use ($replaceArray, $search, &$replaceCount) {
2997  $replaceCount++;
2998  return preg_replace($search, $replaceArray[$replaceCount - 1][0], $match[0]);
2999  };
3000  $content = preg_replace_callback($search, $replaceCallback, $content);
3001  } else {
3002  $content = preg_replace($search, $replace, $content);
3003  }
3004  } elseif ($useOptionSplitReplace) {
3005  // turn search-string into a preg-pattern
3006  $searchPreg = '#' . preg_quote($search, '#') . '#';
3007 
3008  // init for replacement
3009  $splitCount = preg_match_all($searchPreg, $content, $matches);
3010  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
3011  $replaceArray = $typoScriptService->explodeConfigurationForOptionSplit([$replace], $splitCount);
3012  $replaceCount = 0;
3013 
3014  $replaceCallback = static function () use ($replaceArray, &$replaceCount) {
3015  $replaceCount++;
3016  return $replaceArray[$replaceCount - 1][0];
3017  };
3018  $content = preg_replace_callback($searchPreg, $replaceCallback, $content);
3019  } else {
3020  $content = str_replace($search, $replace, $content);
3021  }
3022  }
3023  return $content;
3024  }
3025 
3034  protected function ‪round($content, array $conf = [])
3035  {
3036  $decimals = (int)$this->‪stdWrapValue('decimals', $conf, 0);
3037  $type = $this->‪stdWrapValue('roundType', $conf);
3038  $floatVal = (float)$content;
3039  switch ($type) {
3040  case 'ceil':
3041  $content = ceil($floatVal);
3042  break;
3043  case 'floor':
3044  $content = floor($floatVal);
3045  break;
3046  case 'round':
3047 
3048  default:
3049  $content = ‪round($floatVal, $decimals);
3050  }
3051  return $content;
3052  }
3053 
3062  public function ‪numberFormat($content, $conf)
3063  {
3064  $decimals = (int)$this->‪stdWrapValue('decimals', $conf, 0);
3065  $dec_point = (string)$this->‪stdWrapValue('dec_point', $conf, '.');
3066  $thousands_sep = (string)$this->‪stdWrapValue('thousands_sep', $conf, ',');
3067  return number_format((float)$content, $decimals, $dec_point, $thousands_sep);
3068  }
3069 
3088  public function ‪parseFunc($theValue, ?array $conf, ?string $ref = null)
3089  {
3090  // Fetch / merge reference, if any
3091  if (!empty($ref)) {
3092  $temp_conf = [
3093  'parseFunc' => $ref,
3094  'parseFunc.' => $conf ?? [],
3095  ];
3096  $temp_conf = $this->‪mergeTSRef($temp_conf, 'parseFunc');
3097  $conf = $temp_conf['parseFunc.'];
3098  }
3099  if (empty($conf)) {
3100  // `parseFunc` relies on configuration, either given in `$conf` or resolved from `$ref`
3101  throw new \LogicException('Invoked ContentObjectRenderer::parseFunc without any configuration', 1641989097);
3102  }
3103  // Handle HTML sanitizer invocation
3104  $conf['htmlSanitize'] = (bool)($conf['htmlSanitize'] ?? true);
3105  // Process:
3106  if ((string)($conf['externalBlocks'] ?? '') === '') {
3107  $result = $this->‪parseFuncInternal($theValue, $conf);
3108  if ($conf['htmlSanitize']) {
3109  $result = $this->‪stdWrap_htmlSanitize($result, $conf['htmlSanitize.'] ?? []);
3110  }
3111  return $result;
3112  }
3113  $tags = strtolower(implode(',', GeneralUtility::trimExplode(',', $conf['externalBlocks'])));
3114  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
3115  $parts = $htmlParser->splitIntoBlock($tags, $theValue);
3116  foreach ($parts as $k => $v) {
3117  if ($k % 2) {
3118  // font:
3119  $tagName = strtolower($htmlParser->getFirstTagName($v));
3120  $cfg = $conf['externalBlocks.'][$tagName . '.'] ?? [];
3121  if ($cfg === []) {
3122  continue;
3123  }
3124  if (($cfg['stripNLprev'] ?? false) || ($cfg['stripNL'] ?? false)) {
3125  $parts[$k - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $parts[$k - 1]);
3126  }
3127  if (($cfg['stripNLnext'] ?? false) || ($cfg['stripNL'] ?? false)) {
3128  if (!isset($parts[$k + 1])) {
3129  $parts[$k + 1] = '';
3130  }
3131  $parts[$k + 1] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $parts[$k + 1]);
3132  }
3133  }
3134  }
3135  foreach ($parts as $k => $v) {
3136  if ($k % 2) {
3137  $tag = $htmlParser->getFirstTag($v);
3138  $tagName = strtolower($htmlParser->getFirstTagName($v));
3139  $cfg = $conf['externalBlocks.'][$tagName . '.'] ?? [];
3140  if ($cfg === []) {
3141  continue;
3142  }
3143  if ($cfg['callRecursive'] ?? false) {
3144  $parts[$k] = $this->‪parseFunc($htmlParser->removeFirstAndLastTag($v), $conf);
3145  if (!($cfg['callRecursive.']['dontWrapSelf'] ?? false)) {
3146  if ($cfg['callRecursive.']['alternativeWrap'] ?? false) {
3147  $parts[$k] = $this->‪wrap($parts[$k], $cfg['callRecursive.']['alternativeWrap']);
3148  } else {
3149  if (is_array($cfg['callRecursive.']['tagStdWrap.'] ?? false)) {
3150  $tag = $this->‪stdWrap($tag, $cfg['callRecursive.']['tagStdWrap.']);
3151  }
3152  $parts[$k] = $tag . $parts[$k] . '</' . $tagName . '>';
3153  }
3154  }
3155  } elseif ($cfg['HTMLtableCells'] ?? false) {
3156  $rowParts = $htmlParser->splitIntoBlock('tr', $parts[$k]);
3157  foreach ($rowParts as $kk => $vv) {
3158  if ($kk % 2) {
3159  $colParts = $htmlParser->splitIntoBlock('td,th', $vv);
3160  $cc = 0;
3161  foreach ($colParts as $kkk => $vvv) {
3162  if ($kkk % 2) {
3163  $cc++;
3164  $tag = $htmlParser->getFirstTag($vvv);
3165  $tagName = strtolower($htmlParser->getFirstTagName($vvv));
3166  $colParts[$kkk] = $htmlParser->removeFirstAndLastTag($vvv);
3167  if (($cfg['HTMLtableCells.'][$cc . '.']['callRecursive'] ?? false)
3168  || (!isset($cfg['HTMLtableCells.'][$cc . '.']['callRecursive']) && ($cfg['HTMLtableCells.']['default.']['callRecursive'] ?? false))) {
3169  if ($cfg['HTMLtableCells.']['addChr10BetweenParagraphs'] ?? false) {
3170  $colParts[$kkk] = str_replace(
3171  '</p><p>',
3172  '</p>' . LF . '<p>',
3173  $colParts[$kkk]
3174  );
3175  }
3176  $colParts[$kkk] = $this->‪parseFunc($colParts[$kkk], $conf);
3177  }
3178  $tagStdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.'] ?? false)
3179  ? $cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.']
3180  : ($cfg['HTMLtableCells.']['default.']['tagStdWrap.'] ?? null);
3181  if (is_array($tagStdWrap)) {
3182  $tag = $this->‪stdWrap($tag, $tagStdWrap);
3183  }
3184  $stdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['stdWrap.'] ?? false)
3185  ? $cfg['HTMLtableCells.'][$cc . '.']['stdWrap.']
3186  : ($cfg['HTMLtableCells.']['default.']['stdWrap.'] ?? null);
3187  if (is_array($stdWrap)) {
3188  $colParts[$kkk] = $this->‪stdWrap($colParts[$kkk], $stdWrap);
3189  }
3190  $colParts[$kkk] = $tag . $colParts[$kkk] . '</' . $tagName . '>';
3191  }
3192  }
3193  $rowParts[$kk] = implode('', $colParts);
3194  }
3195  }
3196  $parts[$k] = implode('', $rowParts);
3197  }
3198  if (is_array($cfg['stdWrap.'] ?? false)) {
3199  $parts[$k] = $this->‪stdWrap($parts[$k], $cfg['stdWrap.']);
3200  }
3201  } else {
3202  $parts[$k] = $this->‪parseFuncInternal($parts[$k], $conf);
3203  }
3204  }
3205  $result = implode('', $parts);
3206  if ($conf['htmlSanitize']) {
3207  $result = $this->‪stdWrap_htmlSanitize($result, $conf['htmlSanitize.'] ?? []);
3208  }
3209  return $result;
3210  }
3211 
3220  protected function ‪parseFuncInternal($theValue, $conf)
3221  {
3222  if (!empty($conf['if.']) && !$this->‪checkIf($conf['if.'])) {
3223  return $theValue;
3224  }
3225  // Indicates that the data is from within a tag.
3226  $inside = false;
3227  // Pointer to the total string position
3228  $pointer = 0;
3229  // Loaded with the current typo-tag if any.
3230  $currentTag = null;
3231  $stripNL = 0;
3232  $contentAccum = [];
3233  $contentAccumP = 0;
3234  $allowTags = strtolower(str_replace(' ', '', $conf['allowTags'] ?? ''));
3235  $denyTags = strtolower(str_replace(' ', '', $conf['denyTags'] ?? ''));
3236  $totalLen = strlen($theValue);
3237  do {
3238  if (!$inside) {
3239  if ($currentTag === null) {
3240  // These operations should only be performed on code outside the typotags...
3241  // data: this checks that we enter tags ONLY if the first char in the tag is alphanumeric OR '/'
3242  $len_p = 0;
3243  $c = 100;
3244  do {
3245  $len = strcspn(substr($theValue, $pointer + $len_p), '<');
3246  $len_p += $len + 1;
3247  $endChar = ord(strtolower(substr($theValue, $pointer + $len_p, 1)));
3248  $c--;
3249  } while ($c > 0 && $endChar && ($endChar < 97 || $endChar > 122) && $endChar != 47);
3250  $len = $len_p - 1;
3251  } else {
3252  $len = $this->‪getContentLengthOfCurrentTag($theValue, $pointer, (string)$currentTag[0]);
3253  }
3254  // $data is the content until the next <tag-start or end is detected.
3255  // In case of a currentTag set, this would mean all data between the start- and end-tags
3256  ‪$data = substr($theValue, $pointer, $len);
3257  if (‪$data !== false) {
3258  if ($stripNL) {
3259  // If the previous tag was set to strip NewLines in the beginning of the next data-chunk.
3260  ‪$data = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', ‪$data);
3261  if (‪$data === null) {
3262  $this->logger->debug('Stripping new lines failed for "{data}"', ['data' => ‪$data]);
3263  ‪$data = '';
3264  }
3265  }
3266  // These operations should only be performed on code outside the tags...
3267  if (!is_array($currentTag)) {
3268  // Short
3269  if (isset($conf['short.']) && is_array($conf['short.'])) {
3270  $shortWords = $conf['short.'];
3271  krsort($shortWords);
3272  foreach ($shortWords as $key => $val) {
3273  if (is_string($val)) {
3274  ‪$data = str_replace($key, $val, ‪$data);
3275  }
3276  }
3277  }
3278  // stdWrap
3279  if (isset($conf['plainTextStdWrap.']) && is_array($conf['plainTextStdWrap.'])) {
3280  ‪$data = $this->‪stdWrap(‪$data, $conf['plainTextStdWrap.']);
3281  }
3282  // userFunc
3283  if ($conf['userFunc'] ?? false) {
3284  ‪$data = $this->‪callUserFunction($conf['userFunc'], $conf['userFunc.'] ?? [], ‪$data);
3285  }
3286  }
3287  // Search for tags to process in current data and
3288  // call this method recursively if found
3289  if (str_contains(‪$data, '<') && isset($conf['tags.']) && is_array($conf['tags.'])) {
3290  // @todo probably use a DOM tree traversal for the whole stuff
3291  // This iterations basically re-processes the markup string, as
3292  // long as there are `<$tag ` or `<$tag>` "tags" found...
3293  foreach (array_keys($conf['tags.']) as $tag) {
3294  // only match tag `a` in `<a href"...">` but not in `<abbr>`
3295  if (preg_match('#<' . $tag . '[\s/>]#', ‪$data)) {
3296  ‪$data = $this->‪parseFuncInternal(‪$data, $conf);
3297  break;
3298  }
3299  }
3300  }
3301  if (!is_array($currentTag) && ($conf['makelinks'] ?? false)) {
3302  ‪$data = $this->‪http_makelinks(‪$data, $conf['makelinks.']['http.'] ?? []);
3303  ‪$data = $this->‪mailto_makelinks(‪$data, $conf['makelinks.']['mailto.'] ?? []);
3304  }
3305  $contentAccum[$contentAccumP] = isset($contentAccum[$contentAccumP])
3306  ? $contentAccum[$contentAccumP] . ‪$data
3307  : ‪$data;
3308  }
3309  $inside = true;
3310  } else {
3311  // tags
3312  $len = strcspn(substr($theValue, $pointer), '>') + 1;
3313  ‪$data = substr($theValue, $pointer, $len);
3314  if (str_ends_with(‪$data, '/>') && !str_starts_with(‪$data, '<link ')) {
3315  $tagContent = substr(‪$data, 1, -2);
3316  } else {
3317  $tagContent = substr(‪$data, 1, -1);
3318  }
3319  $tag = explode(' ', trim($tagContent), 2);
3320  $tag[0] = strtolower($tag[0]);
3321  // end tag like </li>
3322  if (str_starts_with($tag[0], '/')) {
3323  $tag[0] = substr($tag[0], 1);
3324  $tag['out'] = 1;
3325  }
3326  if ($conf['tags.'][$tag[0]] ?? false) {
3327  $treated = false;
3328  $stripNL = false;
3329  // in-tag
3330  if (!$currentTag && (!isset($tag['out']) || !$tag['out'])) {
3331  // $currentTag (array!) is the tag we are currently processing
3332  $currentTag = $tag;
3333  $contentAccumP++;
3334  $treated = true;
3335  // in-out-tag: img and other empty tags
3336  if (preg_match('/^(area|base|br|col|hr|img|input|meta|param)$/i', (string)$tag[0])) {
3337  $tag['out'] = 1;
3338  }
3339  }
3340  // out-tag
3341  if (isset($currentTag[0], $tag['out']) && $currentTag[0] === $tag[0] && $tag['out']) {
3342  $theName = $conf['tags.'][$tag[0]];
3343  $theConf = $conf['tags.'][$tag[0] . '.'];
3344  // This flag indicates, that NL- (13-10-chars) should be stripped first and last.
3345  $stripNL = (bool)($theConf['stripNL'] ?? false);
3346  // This flag indicates, that this TypoTag section should NOT be included in the nonTypoTag content.
3347  $breakOut = (bool)($theConf['breakoutTypoTagContent'] ?? false);
3348  $this->parameters = [];
3349  if (isset($currentTag[1])) {
3350  // decode HTML entities in attributes, since they're processed
3351  $params = GeneralUtility::get_tag_attributes((string)$currentTag[1], true);
3352  if (is_array($params)) {
3353  foreach ($params as $option => $val) {
3354  // contains non-encoded values
3355  $this->parameters[strtolower($option)] = $val;
3356  }
3357  }
3358  $this->parameters['allParams'] = trim((string)$currentTag[1]);
3359  }
3360  // Removes NL in the beginning and end of the tag-content AND at the end of the currentTagBuffer.
3361  // $stripNL depends on the configuration of the current tag
3362  if ($stripNL) {
3363  $contentAccum[$contentAccumP - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP - 1] ?? '');
3364  $contentAccum[$contentAccumP] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $contentAccum[$contentAccumP] ?? '');
3365  $contentAccum[$contentAccumP] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP] ?? '');
3366  }
3367  $this->data[‪$this->currentValKey] = $contentAccum[$contentAccumP] ?? null;
3368  $newInput = $this->‪cObjGetSingle($theName, $theConf, '/parseFunc/.tags.' . $tag[0]);
3369  // fetch the content object
3370  $contentAccum[$contentAccumP] = $newInput;
3371  $contentAccumP++;
3372  // If the TypoTag section
3373  if (!$breakOut) {
3374  if (!isset($contentAccum[$contentAccumP - 2])) {
3375  $contentAccum[$contentAccumP - 2] = '';
3376  }
3377  $contentAccum[$contentAccumP - 2] .= ($contentAccum[$contentAccumP - 1] ?? '') . ($contentAccum[$contentAccumP] ?? '');
3378  unset($contentAccum[$contentAccumP]);
3379  unset($contentAccum[$contentAccumP - 1]);
3380  $contentAccumP -= 2;
3381  }
3382  $currentTag = null;
3383  $treated = true;
3384  }
3385  // other tags
3386  if (!$treated) {
3387  $contentAccum[$contentAccumP] .= ‪$data;
3388  }
3389  } else {
3390  // If a tag was not a typo tag, then it is just added to the content
3391  $stripNL = false;
3392  if (‪GeneralUtility::inList($allowTags, (string)$tag[0]) ||
3393  ($denyTags !== '*' && !‪GeneralUtility::inList($denyTags, (string)$tag[0]))) {
3394  $contentAccum[$contentAccumP] = isset($contentAccum[$contentAccumP])
3395  ? $contentAccum[$contentAccumP] . ‪$data
3396  : ‪$data;
3397  } else {
3398  $contentAccum[$contentAccumP] = isset($contentAccum[$contentAccumP])
3399  ? $contentAccum[$contentAccumP] . htmlspecialchars(‪$data)
3400  : htmlspecialchars(‪$data);
3401  }
3402  }
3403  $inside = false;
3404  }
3405  $pointer += $len;
3406  } while ($pointer < $totalLen);
3407  // Parsing nonTypoTag content (all even keys):
3408  reset($contentAccum);
3409  $contentAccumCount = count($contentAccum);
3410  for ($a = 0; $a < $contentAccumCount; $a++) {
3411  if ($a % 2 != 1) {
3412  // stdWrap
3413  if (isset($conf['nonTypoTagStdWrap.']) && is_array($conf['nonTypoTagStdWrap.'])) {
3414  $contentAccum[$a] = $this->‪stdWrap((string)($contentAccum[$a] ?? ''), $conf['nonTypoTagStdWrap.']);
3415  }
3416  // userFunc
3417  if (!empty($conf['nonTypoTagUserFunc'])) {
3418  $contentAccum[$a] = $this->‪callUserFunction($conf['nonTypoTagUserFunc'], $conf['nonTypoTagUserFunc.'] ?? [], (string)($contentAccum[$a] ?? ''));
3419  }
3420  }
3421  }
3422  return implode('', $contentAccum);
3423  }
3424 
3433  public function ‪encaps_lineSplit($theValue, $conf)
3434  {
3435  if ((string)$theValue === '') {
3436  return '';
3437  }
3438  $lParts = explode(LF, $theValue);
3439 
3440  // When the last element is an empty linebreak we need to remove it, otherwise we will have a duplicate empty line.
3441  $lastPartIndex = count($lParts) - 1;
3442  if ($lParts[$lastPartIndex] === '' && trim($lParts[$lastPartIndex - 1], CR) === '') {
3443  array_pop($lParts);
3444  }
3445 
3446  $encapTags = GeneralUtility::trimExplode(',', strtolower($conf['encapsTagList'] ?? ''), true);
3447  $defaultAlign = trim((string)$this->‪stdWrapValue('defaultAlign', $conf ?? []));
3448 
3449  $str_content = '';
3450  foreach ($lParts as $k => $l) {
3451  $sameBeginEnd = false;
3452  $emptyTag = false;
3453  $l = trim($l);
3454  $attrib = [];
3455  $nonWrapped = false;
3456  $tagName = '';
3457  if (isset($l[0]) && $l[0] === '<' && str_ends_with($l, '>')) {
3458  $fwParts = explode('>', substr($l, 1), 2);
3459  [$tagName] = explode(' ', $fwParts[0], 2);
3460  if (!$fwParts[1]) {
3461  if (str_ends_with($tagName, '/')) {
3462  $tagName = substr($tagName, 0, -1);
3463  }
3464  if (str_ends_with($fwParts[0], '/')) {
3465  $sameBeginEnd = true;
3466  $emptyTag = true;
3467  // decode HTML entities, they're encoded later again
3468  $attrib = GeneralUtility::get_tag_attributes('<' . substr($fwParts[0], 0, -1) . '>', true);
3469  }
3470  } else {
3471  $backParts = GeneralUtility::revExplode('<', substr($fwParts[1], 0, -1), 2);
3472  // decode HTML entities, they're encoded later again
3473  $attrib = GeneralUtility::get_tag_attributes('<' . $fwParts[0] . '>', true);
3474  $str_content = $backParts[0];
3475  // Ensure that $backParts could be exploded into 2 items
3476  if (isset($backParts[1])) {
3477  $sameBeginEnd = strtolower(substr($backParts[1], 1, strlen($tagName))) === strtolower($tagName);
3478  }
3479  }
3480  }
3481  if ($sameBeginEnd && in_array(strtolower($tagName), $encapTags)) {
3482  $uTagName = strtoupper($tagName);
3483  $uTagName = strtoupper($conf['remapTag.'][$uTagName] ?? $uTagName);
3484  } else {
3485  $uTagName = strtoupper($conf['nonWrappedTag'] ?? '');
3486  // The line will be wrapped: $uTagName should not be an empty tag
3487  $emptyTag = false;
3488  $str_content = $lParts[$k];
3489  $nonWrapped = true;
3490  $attrib = [];
3491  }
3492  // Wrapping all inner-content:
3493  if (is_array($conf['innerStdWrap_all.'] ?? null)) {
3494  $str_content = (string)$this->‪stdWrap($str_content, $conf['innerStdWrap_all.']);
3495  }
3496  if ($uTagName) {
3497  // Setting common attributes
3498  if (isset($conf['addAttributes.'][$uTagName . '.']) && is_array($conf['addAttributes.'][$uTagName . '.'])) {
3499  foreach ($conf['addAttributes.'][$uTagName . '.'] as $kk => $vv) {
3500  if (!is_array($vv)) {
3501  if ((string)($conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] ?? '') === 'blank') {
3502  if ((string)($attrib[$kk] ?? '') === '') {
3503  $attrib[$kk] = $vv;
3504  }
3505  } elseif ((string)($conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] ?? '') === 'exists') {
3506  if (!isset($attrib[$kk])) {
3507  $attrib[$kk] = $vv;
3508  }
3509  } else {
3510  $attrib[$kk] = $vv;
3511  }
3512  }
3513  }
3514  }
3515  // Wrapping all inner-content:
3516  if (isset($conf['encapsLinesStdWrap.'][$uTagName . '.']) && is_array($conf['encapsLinesStdWrap.'][$uTagName . '.'])) {
3517  $str_content = (string)$this->‪stdWrap($str_content, $conf['encapsLinesStdWrap.'][$uTagName . '.']);
3518  }
3519  // Default align
3520  if ((!isset($attrib['align']) || !$attrib['align']) && $defaultAlign) {
3521  $attrib['align'] = $defaultAlign;
3522  }
3523  // implode (insecure) attributes, that's why `htmlspecialchars` is used here
3524  $params = GeneralUtility::implodeAttributes($attrib, true);
3525  if (!isset($conf['removeWrapping']) || !$conf['removeWrapping'] || ($emptyTag && $conf['removeWrapping.']['keepSingleTag'])) {
3526  $selfClosingTagList = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
3527  if ($emptyTag && in_array(strtolower($uTagName), $selfClosingTagList, true)) {
3528  $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . ' />';
3529  } else {
3530  $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . '>' . $str_content . '</' . strtolower($uTagName) . '>';
3531  }
3532  }
3533  }
3534  if ($nonWrapped && isset($conf['wrapNonWrappedLines']) && $conf['wrapNonWrappedLines']) {
3535  $str_content = $this->‪wrap($str_content, $conf['wrapNonWrappedLines']);
3536  }
3537  $lParts[$k] = $str_content;
3538  }
3539  return implode(LF, $lParts);
3540  }
3541 
3554  protected function ‪http_makelinks(string ‪$data, array $conf): string
3555  {
3556  $parts = [];
3557  foreach (['http://', 'https://'] as $scheme) {
3558  $textpieces = explode($scheme, ‪$data);
3559  $pieces = count($textpieces);
3560  $textstr = $textpieces[0];
3561  for ($i = 1; $i < $pieces; $i++) {
3562  $len = strcspn($textpieces[$i], chr(32) . "\t" . CRLF);
3563  if (!(trim(substr($textstr, -1)) === '' && $len)) {
3564  $textstr .= $scheme . $textpieces[$i];
3565  continue;
3566  }
3567  $lastChar = substr($textpieces[$i], $len - 1, 1);
3568  if (!preg_match('/[A-Za-z0-9\\/#_-]/', $lastChar)) {
3569  $len--;
3570  }
3571  // Included '\/' 3/12
3572  $parts[0] = substr($textpieces[$i], 0, $len);
3573  $parts[1] = substr($textpieces[$i], $len);
3574  $keep = $conf['keep'] ?? '';
3575  $linkParts = parse_url($scheme . $parts[0]);
3576  // Check if link couldn't be parsed properly
3577  if (!is_array($linkParts)) {
3578  $textstr .= $scheme . $textpieces[$i];
3579  continue;
3580  }
3581  $linktxt = '';
3582  if (str_contains($keep, 'scheme')) {
3583  $linktxt = $scheme;
3584  }
3585  $linktxt .= $linkParts['host'] ?? '';
3586  if (str_contains($keep, 'path')) {
3587  $linktxt .= ($linkParts['path'] ?? '');
3588  // Added $linkParts['query'] 3/12
3589  if (str_contains($keep, 'query') && $linkParts['query']) {
3590  $linktxt .= '?' . $linkParts['query'];
3591  } elseif (($linkParts['path'] ?? '') === '/') {
3592  $linktxt = substr($linktxt, 0, -1);
3593  }
3594  }
3595  $typolinkConfiguration = $conf;
3596  $typolinkConfiguration['parameter'] = $scheme . $parts[0];
3597  $textstr .= $this->‪typoLink($linktxt, $typolinkConfiguration) . $parts[1];
3598  }
3599  ‪$data = $textstr;
3600  }
3601  return $textstr;
3602  }
3603 
3615  protected function ‪mailto_makelinks(string ‪$data, array $conf): string
3616  {
3617  $conf = (array)$conf;
3618  $parts = [];
3619  // split by mailto logic
3620  $textpieces = explode('mailto:', ‪$data);
3621  $pieces = count($textpieces);
3622  $textstr = $textpieces[0] ?? '';
3623  for ($i = 1; $i < $pieces; $i++) {
3624  $len = strcspn($textpieces[$i], chr(32) . "\t" . CRLF);
3625  if (trim(substr($textstr, -1)) === '' && $len) {
3626  $lastChar = substr($textpieces[$i], $len - 1, 1);
3627  if (!preg_match('/[A-Za-z0-9]/', $lastChar)) {
3628  $len--;
3629  }
3630  $parts[0] = substr($textpieces[$i], 0, $len);
3631  $parts[1] = substr($textpieces[$i], $len);
3632  $linktxt = (string)preg_replace('/\\?.*/', '', $parts[0]);
3633  $typolinkConfiguration = $conf;
3634  $typolinkConfiguration['parameter'] = 'mailto:' . $parts[0];
3635  $textstr .= (string)$this->‪typoLink($linktxt, $typolinkConfiguration) . $parts[1];
3636  } else {
3637  $textstr .= 'mailto:' . $textpieces[$i];
3638  }
3639  }
3640  return $textstr;
3641  }
3642 
3668  public function ‪getImgResource($file, $fileArray)
3669  {
3670  $importedFile = null;
3671  $fileReference = null;
3672  if (empty($file) && empty($fileArray)) {
3673  return null;
3674  }
3675  if (!is_array($fileArray)) {
3676  $fileArray = (array)$fileArray;
3677  }
3678  $imageResource = null;
3679  if ($file === 'GIFBUILDER') {
3680  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
3681  $gifCreator->start($fileArray, $this->data);
3682  $theImage = $gifCreator->gifBuild();
3683  if ($theImage !== '') {
3684  $fullPath = ‪Environment::getPublicPath() . '/' . $theImage;
3685  $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $fullPath);
3686  if ($imageInfo->getWidth() > 0) {
3687  $imageResource = [
3688  0 => $imageInfo->getWidth(),
3689  1 => $imageInfo->getHeight(),
3690  2 => $imageInfo->getExtension(),
3691  3 => $fullPath,
3692  'origFile' => $theImage,
3693  ];
3694  }
3695  }
3696  } else {
3697  if ($file instanceof File) {
3698  $fileObject = $file;
3699  } elseif ($file instanceof FileReference) {
3700  $fileReference = $file;
3701  $fileObject = $file->getOriginalFile();
3702  } else {
3703  try {
3704  if (isset($fileArray['import.']) && $fileArray['import.']) {
3705  $importedFile = trim((string)$this->‪stdWrap('', $fileArray['import.']));
3706  if (!empty($importedFile)) {
3707  $file = $importedFile;
3708  }
3709  }
3710 
3712  $treatIdAsReference = $this->‪stdWrapValue('treatIdAsReference', $fileArray);
3713  if (!empty($treatIdAsReference)) {
3714  $fileReference = $this->‪getResourceFactory()->‪getFileReferenceObject($file);
3715  $fileObject = $fileReference->getOriginalFile();
3716  } else {
3717  $fileObject = $this->‪getResourceFactory()->‪getFileObject($file);
3718  }
3719  } elseif (preg_match('/^(0|[1-9][0-9]*):/', $file)) { // combined identifier
3720  $fileObject = $this->‪getResourceFactory()->‪retrieveFileOrFolderObject($file);
3721  } else {
3722  if ($importedFile && !empty($fileArray['import'])) {
3723  $file = $fileArray['import'] . $file;
3724  }
3725  $fileObject = $this->‪getResourceFactory()->‪retrieveFileOrFolderObject($file);
3726  }
3727  } catch (Exception $exception) {
3728  $this->logger->warning('The image "{file}" could not be found and won\'t be included in frontend output', [
3729  'file' => $file,
3730  'exception' => $exception,
3731  ]);
3732  return null;
3733  }
3734  }
3735  if ($fileObject instanceof File) {
3736  $processingConfiguration['width'] = $this->‪stdWrapValue('width', $fileArray);
3737  $processingConfiguration['height'] = $this->‪stdWrapValue('height', $fileArray);
3738  $processingConfiguration['fileExtension'] = $this->‪stdWrapValue('ext', $fileArray);
3739  $processingConfiguration['maxWidth'] = (int)$this->‪stdWrapValue('maxW', $fileArray);
3740  $processingConfiguration['maxHeight'] = (int)$this->‪stdWrapValue('maxH', $fileArray);
3741  $processingConfiguration['minWidth'] = (int)$this->‪stdWrapValue('minW', $fileArray);
3742  $processingConfiguration['minHeight'] = (int)$this->‪stdWrapValue('minH', $fileArray);
3743  $processingConfiguration['noScale'] = $this->‪stdWrapValue('noScale', $fileArray);
3744  $processingConfiguration['sample'] = (bool)$this->‪stdWrapValue('sample', $fileArray);
3745  $processingConfiguration['additionalParameters'] = $this->‪stdWrapValue('params', $fileArray);
3746  $processingConfiguration['frame'] = (int)$this->‪stdWrapValue('frame', $fileArray);
3747  if ($fileReference instanceof FileReference) {
3748  $processingConfiguration['crop'] = $this->‪getCropAreaFromFileReference($fileReference, $fileArray);
3749  } else {
3750  $processingConfiguration['crop'] = $this->‪getCropAreaFromFromTypoScriptSettings($fileObject, $fileArray);
3751  }
3752 
3753  // Possibility to cancel/force profile extraction
3754  // see $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_stripColorProfileCommand']
3755  if (isset($fileArray['stripProfile'])) {
3756  $processingConfiguration['stripProfile'] = $fileArray['stripProfile'];
3757  }
3758  // Check if we can handle this type of file for editing
3759  if ($fileObject->isImage()) {
3760  $maskArray = $fileArray['m.'] ?? false;
3761  // Must render mask images and include in hash-calculating
3762  // - otherwise we cannot be sure the filename is unique for the setup!
3763  if (is_array($maskArray)) {
3764  $processingConfiguration['maskImages']['maskImage'] = $this->‪getImgResource($maskArray['mask'] ?? '', $maskArray['mask.'] ?? [])['processedFile'] ?? null;
3765  $processingConfiguration['maskImages']['backgroundImage'] = $this->‪getImgResource($maskArray['bgImg'] ?? '', $maskArray['bgImg.'] ?? [])['processedFile'] ?? null;
3766  $processingConfiguration['maskImages']['maskBottomImage'] = $this->‪getImgResource($maskArray['bottomImg'] ?? '', $maskArray['bottomImg.'] ?? [])['processedFile'] ?? null;
3767  $processingConfiguration['maskImages']['maskBottomImageMask'] = $this->‪getImgResource($maskArray['bottomImg_mask'] ?? '', $maskArray['bottomImg_mask.'] ?? [])['processedFile'] ?? null;
3768  }
3769  $processedFileObject = $fileObject->process(‪ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration);
3770  if ($processedFileObject->isProcessed()) {
3771  $imageResource = [
3772  0 => (int)$processedFileObject->getProperty('width'),
3773  1 => (int)$processedFileObject->getProperty('height'),
3774  2 => $processedFileObject->getExtension(),
3775  3 => ‪Environment::getPublicPath() . '/' . $processedFileObject->getPublicUrl(),
3776  'origFile' => $fileObject->getPublicUrl(),
3777  'origFile_mtime' => $fileObject->getModificationTime(),
3778  // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder,
3779  // in order for the setup-array to create a unique filename hash.
3780  'originalFile' => $fileObject,
3781  'processedFile' => $processedFileObject,
3782  ];
3783  }
3784  }
3785  }
3786  }
3787  // Hook 'getImgResource': Post-processing of image resources
3788  if (isset($imageResource)) {
3790  foreach ($this->‪getGetImgResourceHookObjects() as $hookObject) {
3791  $imageResource = $hookObject->getImgResourcePostProcess($file, (array)$fileArray, $imageResource, $this);
3792  }
3793  }
3794  return $imageResource;
3795  }
3814  protected function ‪getCropAreaFromFileReference(‪FileReference $fileReference, array $fileArray)
3815  {
3816  // Use cropping area from file reference if nothing is configured in TypoScript.
3817  if (!isset($fileArray['crop']) && !isset($fileArray['crop.'])) {
3818  // Set crop variant from TypoScript settings. If not set, use default.
3819  $cropVariant = $fileArray['cropVariant'] ?? 'default';
3820  $fileCropArea = $this->‪createCropAreaFromJsonString((string)$fileReference->‪getProperty('crop'), $cropVariant);
3821  return $fileCropArea->isEmpty() ? null : $fileCropArea->makeAbsoluteBasedOnFile($fileReference);
3822  }
3823 
3824  return $this->‪getCropAreaFromFromTypoScriptSettings($fileReference, $fileArray);
3825  }
3826 
3833  protected function ‪getCropAreaFromFromTypoScriptSettings(‪FileInterface $file, array $fileArray)
3834  {
3836  $cropArea = null;
3837  // Resolve TypoScript configured cropping.
3838  $cropSettings = isset($fileArray['crop.'])
3839  ? $this->‪stdWrap($fileArray['crop'] ?? '', $fileArray['crop.'])
3840  : ($fileArray['crop'] ?? null);
3841 
3842  if (is_string($cropSettings)) {
3843  // Set crop variant from TypoScript settings. If not set, use default.
3844  $cropVariant = $fileArray['cropVariant'] ?? 'default';
3845  // Get cropArea from CropVariantCollection, if cropSettings is a valid json.
3846  // CropVariantCollection::create does json_decode.
3847  $jsonCropArea = $this->‪createCropAreaFromJsonString($cropSettings, $cropVariant);
3848  $cropArea = $jsonCropArea->isEmpty() ? null : $jsonCropArea->makeAbsoluteBasedOnFile($file);
3849 
3850  // Cropping is configured in TypoScript in the following way: file.crop = 50,50,100,100
3851  if ($jsonCropArea->isEmpty() && preg_match('/^[0-9]+,[0-9]+,[0-9]+,[0-9]+$/', $cropSettings)) {
3852  $cropSettings = explode(',', $cropSettings);
3853  if (count($cropSettings) === 4) {
3854  $cropSettings = array_map(floatval(...), $cropSettings);
3855  $stringCropArea = GeneralUtility::makeInstance(
3856  Area::class,
3857  ...$cropSettings
3858  );
3859  $cropArea = $stringCropArea->isEmpty() ? null : $stringCropArea;
3860  }
3861  }
3862  }
3863 
3864  return $cropArea;
3865  }
3866 
3871  protected function ‪createCropAreaFromJsonString(string $cropSettings, string $cropVariant): Area
3872  {
3873  return ‪CropVariantCollection::create($cropSettings)->getCropArea($cropVariant);
3874  }
3875 
3876  /***********************************************
3877  *
3878  * Data retrieval etc.
3879  *
3880  ***********************************************/
3887  public function ‪getFieldVal($field)
3888  {
3889  if (!str_contains($field, '//')) {
3890  return $this->data[trim($field)] ?? null;
3891  }
3892  $sections = GeneralUtility::trimExplode('//', $field, true);
3893  foreach ($sections as $k) {
3894  if ((string)($this->data[$k] ?? '') !== '') {
3895  return $this->data[$k];
3896  }
3897  }
3898 
3899  return '';
3900  }
3901 
3910  public function ‪getData($string, $fieldArray = null)
3911  {
3912  $tsfe = $this->‪getTypoScriptFrontendController();
3913  if (!is_array($fieldArray)) {
3914  $fieldArray = $tsfe->page;
3915  }
3916  $retVal = '';
3917  // @todo: getData should not be called with non-string as $string. example trigger:
3918  // SecureHtmlRenderingTest htmlViewHelperAvoidsCrossSiteScripting set #07 PHP 8
3919  $sections = is_string($string) ? explode('//', $string) : [];
3920  foreach ($sections as $secKey => $secVal) {
3921  if ($retVal) {
3922  break;
3923  }
3924  $parts = explode(':', $secVal, 2);
3925  $type = strtolower(trim($parts[0]));
3926  $typesWithOutParameters = ['level', 'date', 'current', 'pagelayout'];
3927  $key = trim($parts[1] ?? '');
3928  if (($key != '') || in_array($type, $typesWithOutParameters)) {
3929  switch ($type) {
3930  case 'gp':
3931  // Merge GET and POST and get $key out of the merged array
3932  $requestParameters = $this->‪getRequest()->getQueryParams();
3933  $requestParameters = array_replace_recursive($requestParameters, (array)$this->‪getRequest()->getParsedBody());
3934  $retVal = $this->‪getGlobal($key, $requestParameters);
3935  break;
3936  case 'request':
3937  $retVal = $this->‪getValueFromRecursiveData(GeneralUtility::trimExplode('|', $key), $this->‪getRequest());
3938  break;
3939  case 'tsfe':
3940  $retVal = $this->‪getValueFromRecursiveData(GeneralUtility::trimExplode('|', $key), $this->‪getTypoScriptFrontendController());
3941  break;
3942  case 'getenv':
3943  $retVal = getenv($key);
3944  break;
3945  case 'getindpenv':
3946  $retVal = $this->‪getEnvironmentVariable($key);
3947  break;
3948  case 'field':
3949  $retVal = $this->‪getGlobal($key, $fieldArray);
3950  break;
3951  case 'file':
3952  $retVal = $this->‪getFileDataKey($key);
3953  break;
3954  case 'parameters':
3955  $retVal = $this->parameters[$key] ?? null;
3956  break;
3957  case 'register':
3958  $retVal = $tsfe->register[$key] ?? null;
3959  break;
3960  case 'global':
3961  $retVal = $this->‪getGlobal($key);
3962  break;
3963  case 'level':
3964  $retVal = count($tsfe->config['rootLine'] ?? []) - 1;
3965  break;
3966  case 'leveltitle':
3967  $keyParts = GeneralUtility::trimExplode(',', $key);
3968  $pointer = (int)($keyParts[0] ?? 0);
3969  $slide = (string)($keyParts[1] ?? '');
3970 
3971  $numericKey = $this->‪getKey($pointer, $tsfe->config['rootLine'] ?? []);
3972  $retVal = $this->‪rootLineValue($numericKey, 'title', strtolower($slide) === 'slide');
3973  break;
3974  case 'levelmedia':
3975  $keyParts = GeneralUtility::trimExplode(',', $key);
3976  $pointer = (int)($keyParts[0] ?? 0);
3977  $slide = (string)($keyParts[1] ?? '');
3978 
3979  $numericKey = $this->‪getKey($pointer, $tsfe->config['rootLine'] ?? []);
3980  $retVal = $this->‪rootLineValue($numericKey, 'media', strtolower($slide) === 'slide');
3981  break;
3982  case 'leveluid':
3983  $numericKey = $this->‪getKey((int)$key, $tsfe->config['rootLine'] ?? []);
3984  $retVal = $this->‪rootLineValue($numericKey, 'uid');
3985  break;
3986  case 'levelfield':
3987  $keyParts = GeneralUtility::trimExplode(',', $key);
3988  $pointer = (int)($keyParts[0] ?? 0);
3989  $field = (string)($keyParts[1] ?? '');
3990  $slide = (string)($keyParts[2] ?? '');
3991 
3992  $numericKey = $this->‪getKey($pointer, $tsfe->config['rootLine'] ?? []);
3993  $retVal = $this->‪rootLineValue($numericKey, $field, strtolower($slide) === 'slide');
3994  break;
3995  case 'fullrootline':
3996  $keyParts = GeneralUtility::trimExplode(',', $key);
3997  $pointer = (int)($keyParts[0] ?? 0);
3998  $field = (string)($keyParts[1] ?? '');
3999  $slide = (string)($keyParts[2] ?? '');
4000 
4001  $fullKey = (int)($pointer - count($tsfe->config['rootLine'] ?? []) + count($tsfe->rootLine));
4002  if ($fullKey >= 0) {
4003  $retVal = $this->‪rootLineValue($fullKey, $field, stristr($slide, 'slide') !== false, $tsfe->rootLine);
4004  }
4005  break;
4006  case 'date':
4007  if (!$key) {
4008  $key = 'd/m Y';
4009  }
4010  $retVal = date($key, ‪$GLOBALS['EXEC_TIME']);
4011  break;
4012  case 'page':
4013  $retVal = $tsfe->page[$key] ?? '';
4014  break;
4015  case 'pagelayout':
4016  $retVal = GeneralUtility::makeInstance(PageLayoutResolver::class)
4017  ->getLayoutForPage($tsfe->page, $tsfe->rootLine);
4018  break;
4019  case 'current':
4020  $retVal = $this->data[‪$this->currentValKey] ?? null;
4021  break;
4022  case 'db':
4023  $selectParts = GeneralUtility::trimExplode(':', $key, true);
4024  if (!isset($selectParts[1])) {
4025  break;
4026  }
4027  $dbRecord = $tsfe->sys_page->getRawRecord($selectParts[0], $selectParts[1]);
4028  if (is_array($dbRecord) && isset($selectParts[2])) {
4029  $retVal = $dbRecord[$selectParts[2]] ?? '';
4030  }
4031  break;
4032  case 'lll':
4033  $languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class)->createFromSiteLanguage($this->‪getTypoScriptFrontendController()->getLanguage());
4034  $retVal = $languageService->sL('LLL:' . $key);
4035  break;
4036  case 'path':
4037  try {
4038  $retVal = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($key);
4039  } catch (Exception $e) {
4040  // do nothing in case the file path is invalid
4041  $retVal = null;
4042  }
4043  break;
4044  case 'cobj':
4045  switch ($key) {
4046  case 'parentRecordNumber':
4047  $retVal = ‪$this->parentRecordNumber;
4048  break;
4049  }
4050  break;
4051  case 'debug':
4052  switch ($key) {
4053  case 'rootLine':
4054  $retVal = ‪DebugUtility::viewArray($tsfe->config['rootLine'] ?? []);
4055  break;
4056  case 'fullRootLine':
4057  $retVal = ‪DebugUtility::viewArray($tsfe->rootLine);
4058  break;
4059  case 'data':
4060  $retVal = ‪DebugUtility::viewArray($this->data);
4061  break;
4062  case 'register':
4063  $retVal = ‪DebugUtility::viewArray($tsfe->register);
4064  break;
4065  case 'page':
4066  $retVal = ‪DebugUtility::viewArray($tsfe->page);
4067  break;
4068  }
4069  break;
4070  case 'flexform':
4071  $keyParts = GeneralUtility::trimExplode(':', $key, true);
4072  if (count($keyParts) === 2 && isset($this->data[$keyParts[0]])) {
4073  $flexFormContent = $this->data[$keyParts[0]];
4074  if (!empty($flexFormContent)) {
4075  $flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
4076  $flexFormKey = str_replace('.', '|', $keyParts[1]);
4077  $settings = $flexFormService->convertFlexFormContentToArray($flexFormContent);
4078  $retVal = $this->‪getGlobal($flexFormKey, $settings);
4079  }
4080  }
4081  break;
4082  case 'session':
4083  $keyParts = GeneralUtility::trimExplode('|', $key, true);
4084  $sessionKey = array_shift($keyParts);
4085  $retVal = $this->‪getTypoScriptFrontendController()->‪fe_user->getSessionData($sessionKey);
4086  foreach ($keyParts as $keyPart) {
4087  if (is_object($retVal)) {
4088  $retVal = $retVal->{$keyPart};
4089  } elseif (is_array($retVal)) {
4090  $retVal = $retVal[$keyPart];
4091  } else {
4092  $retVal = '';
4093  break;
4094  }
4095  }
4096  if (!is_scalar($retVal)) {
4097  $retVal = '';
4098  }
4099  break;
4100  case 'context':
4101  $context = GeneralUtility::makeInstance(Context::class);
4102  [$aspectName, $propertyName] = GeneralUtility::trimExplode(':', $key, true, 2);
4103  $retVal = $context->getPropertyFromAspect($aspectName, $propertyName, '');
4104  if (is_array($retVal)) {
4105  $retVal = implode(',', $retVal);
4106  }
4107  if (!is_scalar($retVal)) {
4108  $retVal = '';
4109  }
4110  break;
4111  case 'site':
4112  $site = $this->‪getTypoScriptFrontendController()->‪getSite();
4113  if ($key === 'identifier') {
4114  $retVal = $site->getIdentifier();
4115  } elseif ($key === 'base') {
4116  $retVal = $site->getBase();
4117  } else {
4118  try {
4119  $retVal = ‪ArrayUtility::getValueByPath($site->getConfiguration(), $key, '.');
4120  } catch (MissingArrayPathException $exception) {
4121  $this->logger->notice('Configuration "{key}" is not defined for site "{site}"', ['key' => $key, 'site' => $site->getIdentifier(), 'exception' => $exception]);
4122  }
4123  }
4124  break;
4125  case 'sitelanguage':
4126  $siteLanguage = $this->‪getTypoScriptFrontendController()->‪getLanguage();
4127  if ($key === 'twoLetterIsoCode') {
4128  $key = 'locale:languageCode';
4129  }
4130  if ($key === 'hreflang') {
4131  $key = 'locale:full';
4132  }
4133  // Harmonizing the namings from the site configuration value with the TypoScript setting
4134  if ($key === 'flag') {
4135  $key = 'flagIdentifier';
4136  }
4137  // Special handling for the locale object
4138  if (str_starts_with($key, 'locale')) {
4139  $localeObject = $siteLanguage->getLocale();
4140  if ($key === 'locale') {
4141  // backwards-compatibility
4142  $retVal = $localeObject->posixFormatted();
4143  } else {
4144  $keyParts = explode(':', $key, 2);
4145  switch ($keyParts[1] ?? '') {
4146  case 'languageCode':
4147  $retVal = $localeObject->getLanguageCode();
4148  break;
4149  case 'countryCode':
4150  $retVal = $localeObject->getCountryCode();
4151  break;
4152  case 'full':
4153  default:
4154  $retVal = $localeObject->getName();
4155  }
4156  }
4157  } else {
4158  $config = $siteLanguage->toArray();
4159  if (isset($config[$key])) {
4160  $retVal = $config[$key] ?? '';
4161  }
4162  }
4163  break;
4164  case 'sitesettings':
4165  $siteSettings = $this->‪getTypoScriptFrontendController()->‪getSite()->getSettings();
4166  $retVal = $siteSettings->get($key, '');
4167  break;
4168  }
4169  }
4170 
4171  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'] ?? [] as $className) {
4172  $hookObject = GeneralUtility::makeInstance($className);
4173  if (!$hookObject instanceof ContentObjectGetDataHookInterface) {
4174  throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetDataHookInterface::class, 1195044480);
4175  }
4176  $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
4177  $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $ref);
4178  }
4179  }
4180  return $retVal;
4181  }
4182 
4192  protected function getFileDataKey($key)
4193  {
4194  [$fileUidOrCurrentKeyword, $requestedFileInformationKey] = GeneralUtility::trimExplode(':', $key, false, 3);
4195  try {
4196  if ($fileUidOrCurrentKeyword === 'current') {
4197  $fileObject = $this->getCurrentFile();
4198  } elseif (‪MathUtility::canBeInterpretedAsInteger($fileUidOrCurrentKeyword)) {
4199  $fileFactory = GeneralUtility::makeInstance(ResourceFactory::class);
4200  $fileObject = $fileFactory->getFileObject($fileUidOrCurrentKeyword);
4201  } else {
4202  $fileObject = null;
4203  }
4204  } catch (Exception $exception) {
4205  $this->logger->warning('The file "{uid}" could not be found and won\'t be included in frontend output', ['uid' => $fileUidOrCurrentKeyword, 'exception' => $exception]);
4206  $fileObject = null;
4207  }
4208 
4209  if ($fileObject instanceof FileInterface) {
4210  // All properties of the \TYPO3\CMS\Core\Resource\FileInterface are available here:
4211  switch ($requestedFileInformationKey) {
4212  case 'name':
4213  return $fileObject->getName();
4214  case 'uid':
4215  if (method_exists($fileObject, 'getUid')) {
4216  return $fileObject->getUid();
4217  }
4218  return 0;
4219  case 'originalUid':
4220  if ($fileObject instanceof FileReference) {
4221  return $fileObject->getOriginalFile()->getUid();
4222  }
4223  return null;
4224  case 'size':
4225  return $fileObject->getSize();
4226  case 'sha1':
4227  return $fileObject->getSha1();
4228  case 'extension':
4229  return $fileObject->getExtension();
4230  case 'mimetype':
4231  return $fileObject->getMimeType();
4232  case 'contents':
4233  return $fileObject->getContents();
4234  case 'publicUrl':
4235  return $fileObject->getPublicUrl();
4236  default:
4237  // Generic alternative here
4238  return $fileObject->getProperty($requestedFileInformationKey);
4239  }
4240  } else {
4241  // @todo fail silently as is common in tslib_content
4242  return 'Error: no file object';
4243  }
4244  }
4245 
4257  public function rootLineValue($key, $field, $slideBack = false, $altRootLine = '')
4258  {
4259  $rootLine = is_array($altRootLine) ? $altRootLine : ($this->getTypoScriptFrontendController()->config['rootLine'] ?? []);
4260  if (!$slideBack) {
4261  return $rootLine[$key][$field] ?? '';
4262  }
4263  for ($a = $key; $a >= 0; $a--) {
4264  $val = $rootLine[$a][$field] ?? '';
4265  if ($val) {
4266  return $val;
4267  }
4268  }
4269 
4270  return '';
4271  }
4272 
4282  public function getGlobal($keyString, $source = null)
4283  {
4284  $keys = GeneralUtility::trimExplode('|', $keyString);
4285  // remove the first key, as this is only used for finding the original value
4286  $rootKey = array_shift($keys);
4287  $value = isset($source) ? ($source[$rootKey] ?? '') : (‪$GLOBALS[$rootKey] ?? '');
4288  return $this->getValueFromRecursiveData($keys, $value);
4289  }
4290 
4297  protected function getValueFromRecursiveData(array $keys, mixed $startValue): int|float|string
4298  {
4299  $value = $startValue;
4300  $numberOfLevels = count($keys);
4301  for ($i = 0; $i < $numberOfLevels && isset($value); $i++) {
4302  $currentKey = $keys[$i];
4303  if (is_object($value)) {
4304  // getter method
4305  if (method_exists($value, 'get' . ucfirst($currentKey))) {
4306  $getterMethod = 'get' . ucfirst($currentKey);
4307  $value = $value->$getterMethod(...)();
4308  // server request attribute, such as "routing"
4309  } elseif ($value instanceof ServerRequestInterface) {
4310  $value = $value->getAttribute($currentKey);
4311  } else {
4312  // Public property
4313  $value = $value->{$currentKey};
4314  }
4315  } elseif (is_array($value)) {
4316  $value = $value[$currentKey] ?? '';
4317  } else {
4318  $value = '';
4319  break;
4320  }
4321  }
4322  if (!is_scalar($value)) {
4323  $value = '';
4324  }
4325  return $value;
4326  }
4327 
4338  public function getKey($key, $arr)
4339  {
4340  $key = (int)$key;
4341  if (is_array($arr)) {
4342  if ($key < 0) {
4343  $key = count($arr) + $key;
4344  }
4345  if ($key < 0) {
4346  $key = 0;
4347  }
4348  }
4349  return $key;
4350  }
4351 
4352  /***********************************************
4353  *
4354  * Link functions (typolink)
4355  *
4356  ***********************************************/
4357 
4376  public function typoLink(string $linkText, array $conf)
4377  {
4378  try {
4379  $linkResult = $this->createLink($linkText, $conf);
4380  } catch (UnableToLinkException $e) {
4381  return $e->getLinkText();
4382  }
4383 
4384  // If flag "returnLast" set, then just return the latest URL / url / target that was built.
4385  // This returns the information without being wrapped in a "LinkResult" object.
4386  switch ($conf['returnLast'] ?? null) {
4387  case 'url':
4388  return $linkResult->getUrl();
4389  case 'target':
4390  return $linkResult->getTarget();
4391  case 'result':
4392  // kept for backwards-compatibility, as this was added in TYPO3 v11
4393  return LinkResult::adapt($linkResult, LinkResult::STRING_CAST_JSON);
4394  }
4395 
4396  $wrap = (string)$this->stdWrapValue('wrap', $conf);
4397  if ($conf['ATagBeforeWrap'] ?? false) {
4398  $linkResult = $linkResult->withLinkText($this->wrap((string)$linkResult->getLinkText(), $wrap));
4399  return LinkResult::adapt($linkResult)->getHtml();
4400  }
4401  $result = LinkResult::adapt($linkResult)->getHtml();
4402  return $this->wrap($result, $wrap);
4403  }
4422  public function createLink(string $linkText, array $conf): ‪LinkResultInterface
4423  {
4424  $this->lastTypoLinkResult = null;
4425  try {
4426  $linkResult = GeneralUtility::makeInstance(LinkFactory::class)->create($linkText, $conf, $this);
4428  // URL could not be generated
4429  throw $e;
4430  }
4431 
4432  $this->lastTypoLinkResult = $linkResult;
4433  return $linkResult;
4434  }
4435 
4445  public function createUrl(array $conf): string
4446  {
4447  try {
4448  return $this->createLink('', $conf)->getUrl();
4449  } catch (UnableToLinkException $e) {
4450  // URL could not be generated
4451  return '';
4452  }
4453  }
4454 
4462  public function typoLink_URL($conf)
4463  {
4464  return $this->createUrl($conf ?? []);
4465  }
4466 
4467  /***********************************************
4468  *
4469  * Miscellaneous functions, stand alone
4470  *
4471  ***********************************************/
4483  public function wrap($content, $wrap, $char = '|')
4484  {
4485  if ($wrap) {
4486  $wrapArr = explode($char, $wrap);
4487  $content = trim($wrapArr[0] ?? '') . $content . trim($wrapArr[1] ?? '');
4488  }
4489  return $content;
4490  }
4491 
4502  public function noTrimWrap($content, $wrap, $char = '|')
4503  {
4504  if ($wrap) {
4505  // expects to be wrapped with (at least) 3 characters (before, middle, after)
4506  // anything else is not taken into account
4507  $wrapArr = explode($char, $wrap, 4);
4508  $content = ($wrapArr[1] ?? '') . $content . ($wrapArr[2] ?? '');
4509  }
4510  return $content;
4511  }
4512 
4522  public function callUserFunction($funcName, $conf, $content)
4523  {
4524  // Split parts
4525  $parts = explode('->', $funcName);
4526  if (count($parts) === 2) {
4527  // Check whether PHP class is available
4528  if (class_exists($parts[0])) {
4529  if ($this->container && $this->container->has($parts[0])) {
4530  $classObj = $this->container->get($parts[0]);
4531  } else {
4532  $classObj = GeneralUtility::makeInstance($parts[0]);
4533  }
4534  $methodName = (string)$parts[1];
4535  $callable = [$classObj, $methodName];
4536 
4537  if (is_object($classObj) && method_exists($classObj, $parts[1]) && is_callable($callable)) {
4538  if (method_exists($classObj, 'setContentObjectRenderer') && is_callable([$classObj, 'setContentObjectRenderer'])) {
4539  $classObj->setContentObjectRenderer($this);
4540  }
4541  $content = $callable($content, $conf, $this->getRequest()->withAttribute('currentContentObject', $this));
4542  } else {
4543  $this->getTimeTracker()->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', LogLevel::ERROR);
4544  }
4545  } else {
4546  $this->getTimeTracker()->setTSlogMessage('Class "' . $parts[0] . '" did not exist', LogLevel::ERROR);
4547  }
4548  } elseif (function_exists($funcName)) {
4549  $content = $funcName($content, $conf, $this->getRequest()->withAttribute('currentContentObject', $this));
4550  } else {
4551  $this->getTimeTracker()->setTSlogMessage('Function "' . $funcName . '" did not exist', LogLevel::ERROR);
4552  }
4553  return $content;
4554  }
4555 
4562  public function keywords($content)
4563  {
4564  $listArr = preg_split('/[,;' . LF . ']/', $content);
4565  if ($listArr === false) {
4566  return '';
4567  }
4568  foreach ($listArr as $k => $v) {
4569  $listArr[$k] = trim($v);
4570  }
4571  return implode(',', $listArr);
4572  }
4573 
4582  public function caseshift($theValue, $case)
4583  {
4584  switch (strtolower($case)) {
4585  case 'upper':
4586  $theValue = mb_strtoupper($theValue, 'utf-8');
4587  break;
4588  case 'lower':
4589  $theValue = mb_strtolower($theValue, 'utf-8');
4590  break;
4591  case 'capitalize':
4592  $theValue = mb_convert_case($theValue, MB_CASE_TITLE, 'utf-8');
4593  break;
4594  case 'ucfirst':
4595  $firstChar = mb_substr($theValue, 0, 1, 'utf-8');
4596  $firstChar = mb_strtoupper($firstChar, 'utf-8');
4597  $remainder = mb_substr($theValue, 1, null, 'utf-8');
4598  $theValue = $firstChar . $remainder;
4599  break;
4600  case 'lcfirst':
4601  $firstChar = mb_substr($theValue, 0, 1, 'utf-8');
4602  $firstChar = mb_strtolower($firstChar, 'utf-8');
4603  $remainder = mb_substr($theValue, 1, null, 'utf-8');
4604  $theValue = $firstChar . $remainder;
4605  break;
4606  case 'uppercamelcase':
4607  $theValue = GeneralUtility::underscoredToUpperCamelCase($theValue);
4608  break;
4609  case 'lowercamelcase':
4610  $theValue = GeneralUtility::underscoredToLowerCamelCase($theValue);
4611  break;
4612  }
4613  return $theValue;
4614  }
4615 
4624  public function HTMLcaseshift($theValue, $case)
4625  {
4626  $inside = 0;
4627  $newVal = '';
4628  $pointer = 0;
4629  $totalLen = strlen($theValue);
4630  do {
4631  if (!$inside) {
4632  $len = strcspn(substr($theValue, $pointer), '<');
4633  $newVal .= $this->caseshift(substr($theValue, $pointer, $len), $case);
4634  $inside = 1;
4635  } else {
4636  $len = strcspn(substr($theValue, $pointer), '>') + 1;
4637  $newVal .= substr($theValue, $pointer, $len);
4638  $inside = 0;
4639  }
4640  $pointer += $len;
4641  } while ($pointer < $totalLen);
4642  return $newVal;
4643  }
4644 
4652  public function calcAge($seconds, $labels)
4653  {
4654  if (MathUtility::canBeInterpretedAsInteger($labels)) {
4655  $labels = ' min| hrs| days| yrs| min| hour| day| year';
4656  } else {
4657  $labels = str_replace('"', '', $labels);
4658  }
4659  $labelArr = explode('|', $labels);
4660  if (count($labelArr) === 4) {
4661  $labelArr = array_merge($labelArr, $labelArr);
4662  }
4663  $absSeconds = abs($seconds);
4664  $sign = $seconds > 0 ? 1 : -1;
4665  if ($absSeconds < 3600) {
4666  $val = round($absSeconds / 60);
4667  $seconds = $sign * $val . ($val == 1 ? $labelArr[4] : $labelArr[0]);
4668  } elseif ($absSeconds < 24 * 3600) {
4669  $val = round($absSeconds / 3600);
4670  $seconds = $sign * $val . ($val == 1 ? $labelArr[5] : $labelArr[1]);
4671  } elseif ($absSeconds < 365 * 24 * 3600) {
4672  $val = round($absSeconds / (24 * 3600));
4673  $seconds = $sign * $val . ($val == 1 ? $labelArr[6] : $labelArr[2]);
4674  } else {
4675  $val = round($absSeconds / (365 * 24 * 3600));
4676  $seconds = $sign * $val . ($val == 1 ? ($labelArr[7] ?? null) : ($labelArr[3] ?? null));
4677  }
4678  return $seconds;
4679  }
4680 
4699  public function mergeTSRef(array $typoScriptArray, string $propertyName): array
4700  {
4701  if (!isset($typoScriptArray[$propertyName]) || !str_starts_with($typoScriptArray[$propertyName], '<')) {
4702  return $typoScriptArray;
4703  }
4704  $frontendTypoScript = $this->getRequest()->getAttribute('frontend.typoscript');
4705  if (!$frontendTypoScript || !$frontendTypoScript->hasSetup()) {
4706  return $typoScriptArray;
4707  }
4708  $fullTypoScriptArray = $frontendTypoScript->getSetupArray();
4709  $dottedSourceIdentifier = trim(substr($typoScriptArray[$propertyName], 1));
4710  $dottedSourceIdentifierArray = StringUtility::explodeEscaped('.', $dottedSourceIdentifier);
4711  $overrideConfig = $typoScriptArray[$propertyName . '.'] ?? [];
4712  $resolvedValue = $dottedSourceIdentifier;
4713  $resolvedConfig = $fullTypoScriptArray;
4714  foreach ($dottedSourceIdentifierArray as $identifierPart) {
4715  if (!isset($resolvedConfig[$identifierPart . '.'])) {
4716  $resolvedValue = $dottedSourceIdentifier;
4717  $resolvedConfig = $overrideConfig;
4718  break;
4719  }
4720  $resolvedValue = $resolvedConfig[$identifierPart] ?? $resolvedValue;
4721  $resolvedConfig = $resolvedConfig[$identifierPart . '.'];
4722  }
4723  $resolvedConfig = array_replace_recursive($resolvedConfig, $overrideConfig);
4724  $typoScriptArray[$propertyName] = $resolvedValue;
4725  $typoScriptArray[$propertyName . '.'] = $resolvedConfig;
4726  if (!isset($typoScriptArray[$propertyName]) || !str_starts_with($typoScriptArray[$propertyName], '<')) {
4727  return $typoScriptArray;
4728  }
4729  // Call recursive to resolve a nested =< operator
4730  return $this->mergeTSRef($typoScriptArray, $propertyName);
4731  }
4732 
4733  /***********************************************
4734  *
4735  * Database functions, making of queries
4736  *
4737  ***********************************************/
4738 
4748  public function searchWhere($searchWords, $searchFieldList, $searchTable)
4749  {
4750  if (!$searchWords) {
4751  return '';
4752  }
4753 
4754  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4755  ->getQueryBuilderForTable($searchTable);
4756 
4757  $prefixTableName = $searchTable ? $searchTable . '.' : '';
4758 
4759  $where = $queryBuilder->expr()->and();
4760  $searchFields = explode(',', $searchFieldList);
4761  $searchWords = preg_split('/[ ,]/', $searchWords);
4762  foreach ($searchWords as $searchWord) {
4763  $searchWord = trim($searchWord);
4764  if (strlen($searchWord) < 3) {
4765  continue;
4766  }
4767  $searchWordConstraint = $queryBuilder->expr()->or();
4768  $searchWord = $queryBuilder->escapeLikeWildcards($searchWord);
4769  foreach ($searchFields as $field) {
4770  $searchWordConstraint = $searchWordConstraint->with(
4771  $queryBuilder->expr()->like($prefixTableName . $field, $queryBuilder->quote('%' . $searchWord . '%'))
4772  );
4773  }
4774 
4775  if ($searchWordConstraint->count()) {
4776  $where = $where->with($searchWordConstraint);
4777  }
4778  }
4779 
4780  if ((string)$where === '') {
4781  return '';
4782  }
4783 
4784  return ' AND (' . (string)$where . ')';
4785  }
4786 
4796  public function exec_getQuery($table, $conf)
4797  {
4798  $statement = $this->getQuery($table, $conf);
4799  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
4800 
4801  return $connection->executeQuery($statement);
4802  }
4803 
4813  public function getRecords($tableName, array $queryConfiguration)
4814  {
4815  $records = [];
4816 
4817  $statement = $this->exec_getQuery($tableName, $queryConfiguration);
4818 
4819  $tsfe = $this->getTypoScriptFrontendController();
4820  while ($row = $statement->fetchAssociative()) {
4821  // Versioning preview:
4822  $tsfe->sys_page->versionOL($tableName, $row, true);
4823 
4824  // Language overlay:
4825  if (is_array($row)) {
4826  $row = $tsfe->sys_page->getLanguageOverlay($tableName, $row);
4827  }
4828 
4829  // Might be unset in the language overlay
4830  if (is_array($row)) {
4831  $records[] = $row;
4832  }
4833  }
4834 
4835  return $records;
4836  }
4837 
4851  public function getQuery($table, $conf, $returnQueryArray = false)
4852  {
4853  // Resolve stdWrap in these properties first
4854  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
4855  $properties = [
4856  'pidInList',
4857  'uidInList',
4858  'languageField',
4859  'selectFields',
4860  'max',
4861  'begin',
4862  'groupBy',
4863  'orderBy',
4864  'join',
4865  'leftjoin',
4866  'rightjoin',
4867  'recursive',
4868  'where',
4869  ];
4870  foreach ($properties as $property) {
4871  $conf[$property] = trim(
4872  isset($conf[$property . '.'])
4873  ? (string)$this->stdWrap($conf[$property] ?? '', $conf[$property . '.'] ?? [])
4874  : (string)($conf[$property] ?? '')
4875  );
4876  if ($conf[$property] === '') {
4877  unset($conf[$property]);
4878  } elseif (in_array($property, ['languageField', 'selectFields', 'join', 'leftjoin', 'rightjoin', 'where'], true)) {
4879  $conf[$property] = QueryHelper::quoteDatabaseIdentifiers($connection, $conf[$property]);
4880  }
4881  if (isset($conf[$property . '.'])) {
4882  // stdWrapping already done, so remove the sub-array
4883  unset($conf[$property . '.']);
4884  }
4885  }
4886  // Handle PDO-style named parameter markers first
4887  $queryMarkers = $this->getQueryMarkers($table, $conf);
4888  // Replace the markers in the non-stdWrap properties
4889  foreach ($queryMarkers as $marker => $markerValue) {
4890  $properties = [
4891  'uidInList',
4892  'selectFields',
4893  'where',
4894  'max',
4895  'begin',
4896  'groupBy',
4897  'orderBy',
4898  'join',
4899  'leftjoin',
4900  'rightjoin',
4901  ];
4902  foreach ($properties as $property) {
4903  if ($conf[$property] ?? false) {
4904  $conf[$property] = str_replace('###' . $marker . '###', $markerValue, $conf[$property]);
4905  }
4906  }
4907  }
4908 
4909  // Construct WHERE clause:
4910  // Handle recursive function for the pidInList
4911  if (isset($conf['recursive'])) {
4912  $conf['recursive'] = (int)$conf['recursive'];
4913  if ($conf['recursive'] > 0) {
4914  $pidList = GeneralUtility::trimExplode(',', $conf['pidInList'], true);
4915  array_walk($pidList, function (&$storagePid) {
4916  if ($storagePid === 'this') {
4917  $storagePid = $this->getTypoScriptFrontendController()->id;
4918  }
4919  });
4920  $expandedPidList = $this->getTypoScriptFrontendController()->sys_page->getPageIdsRecursive($pidList, $conf['recursive']);
4921  $conf['pidInList'] = implode(',', $expandedPidList);
4922  }
4923  }
4924  if ((string)($conf['pidInList'] ?? '') === '') {
4925  $conf['pidInList'] = 'this';
4926  }
4927 
4928  $queryParts = $this->getQueryConstraints($table, $conf);
4929 
4930  $queryBuilder = $connection->createQueryBuilder();
4931  // @todo Check against getQueryConstraints, can probably use FrontendRestrictions
4932  // @todo here and remove enableFields there.
4933  $queryBuilder->getRestrictions()->removeAll();
4934  $queryBuilder->select('*')->from($table);
4935 
4936  if ($queryParts['where'] ?? false) {
4937  $queryBuilder->where($queryParts['where']);
4938  }
4939 
4940  if ($queryParts['groupBy'] ?? false) {
4941  $queryBuilder->groupBy(...$queryParts['groupBy']);
4942  }
4943 
4944  if (is_array($queryParts['orderBy'] ?? false)) {
4945  foreach ($queryParts['orderBy'] as $orderBy) {
4946  $queryBuilder->addOrderBy(...$orderBy);
4947  }
4948  }
4949 
4950  // Fields:
4951  if ($conf['selectFields'] ?? false) {
4952  $queryBuilder->selectLiteral($this->sanitizeSelectPart($conf['selectFields'], $table));
4953  }
4954 
4955  // Setting LIMIT:
4956  $error = false;
4957  if (($conf['max'] ?? false) || ($conf['begin'] ?? false)) {
4958  // Finding the total number of records, if used:
4959  if (str_contains(strtolower(($conf['begin'] ?? '') . ($conf['max'] ?? '')), 'total')) {
4960  $countQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
4961  $countQueryBuilder->getRestrictions()->removeAll();
4962  $countQueryBuilder->count('*')
4963  ->from($table)
4964  ->where($queryParts['where']);
4965 
4966  if ($queryParts['groupBy']) {
4967  $countQueryBuilder->groupBy(...$queryParts['groupBy']);
4968  }
4969 
4970  try {
4971  $count = $countQueryBuilder->executeQuery()->fetchOne();
4972  if (isset($conf['max'])) {
4973  $conf['max'] = str_ireplace('total', $count, (string)$conf['max']);
4974  }
4975  if (isset($conf['begin'])) {
4976  $conf['begin'] = str_ireplace('total', $count, (string)$conf['begin']);
4977  }
4978  } catch (DBALException $e) {
4979  $this->getTimeTracker()->setTSlogMessage($e->getPrevious()->getMessage());
4980  $error = true;
4981  }
4982  }
4983 
4984  if (!$error) {
4985  if (isset($conf['begin']) && $conf['begin'] > 0) {
4986  $conf['begin'] = MathUtility::forceIntegerInRange((int)ceil($this->calc($conf['begin'])), 0);
4987  $queryBuilder->setFirstResult($conf['begin']);
4988  }
4989  if (isset($conf['max'])) {
4990  $conf['max'] = MathUtility::forceIntegerInRange((int)ceil($this->calc($conf['max'])), 0);
4991  $queryBuilder->setMaxResults($conf['max'] ?: 100000);
4992  }
4993  }
4994  }
4995 
4996  if (!$error) {
4997  // Setting up tablejoins:
4998  if ($conf['join'] ?? false) {
4999  $joinParts = QueryHelper::parseJoin($conf['join']);
5000  $queryBuilder->join(
5001  $table,
5002  $joinParts['tableName'],
5003  $joinParts['tableAlias'],
5004  $joinParts['joinCondition']
5005  );
5006  } elseif ($conf['leftjoin'] ?? false) {
5007  $joinParts = QueryHelper::parseJoin($conf['leftjoin']);
5008  $queryBuilder->leftJoin(
5009  $table,
5010  $joinParts['tableName'],
5011  $joinParts['tableAlias'],
5012  $joinParts['joinCondition']
5013  );
5014  } elseif ($conf['rightjoin'] ?? false) {
5015  $joinParts = QueryHelper::parseJoin($conf['rightjoin']);
5016  $queryBuilder->rightJoin(
5017  $table,
5018  $joinParts['tableName'],
5019  $joinParts['tableAlias'],
5020  $joinParts['joinCondition']
5021  );
5022  }
5023 
5024  // Convert the QueryBuilder object into a SQL statement.
5025  $query = $queryBuilder->getSQL();
5026 
5027  // Replace the markers in the queryParts to handle stdWrap enabled properties
5028  foreach ($queryMarkers as $marker => $markerValue) {
5029  // @todo Ugly hack that needs to be cleaned up, with the current architecture
5030  // @todo for exec_Query / getQuery it's the best we can do.
5031  $query = str_replace('###' . $marker . '###', $markerValue, $query);
5032  }
5033 
5034  return $returnQueryArray ? $this->getQueryArray($queryBuilder) : $query;
5035  }
5036 
5037  return '';
5038  }
5039 
5047  protected function getQueryArray(QueryBuilder $queryBuilder)
5048  {
5049  $fromClauses = [];
5050  $knownAliases = [];
5051  $queryParts = [];
5052 
5053  // Loop through all FROM clauses
5054  foreach ($queryBuilder->getQueryPart('from') as $from) {
5055  if ($from['alias'] === null) {
5056  $tableSql = $from['table'];
5057  $tableReference = $from['table'];
5058  } else {
5059  $tableSql = $from['table'] . ' ' . $from['alias'];
5060  $tableReference = $from['alias'];
5061  }
5062 
5063  $knownAliases[$tableReference] = true;
5064 
5065  $fromClauses[$tableReference] = $tableSql . $this->getQueryArrayJoinHelper(
5066  $tableReference,
5067  $queryBuilder->getQueryPart('join'),
5068  $knownAliases
5069  );
5070  }
5071 
5072  $queryParts['SELECT'] = implode(', ', $queryBuilder->getQueryPart('select'));
5073  $queryParts['FROM'] = implode(', ', $fromClauses);
5074  $queryParts['WHERE'] = (string)$queryBuilder->getQueryPart('where') ?: '';
5075  $queryParts['GROUPBY'] = implode(', ', $queryBuilder->getQueryPart('groupBy'));
5076  $queryParts['ORDERBY'] = implode(', ', $queryBuilder->getQueryPart('orderBy'));
5077  if ($queryBuilder->getFirstResult() > 0) {
5078  $queryParts['LIMIT'] = $queryBuilder->getFirstResult() . ',' . $queryBuilder->getMaxResults();
5079  } elseif ($queryBuilder->getMaxResults() > 0) {
5080  $queryParts['LIMIT'] = $queryBuilder->getMaxResults();
5081  }
5082 
5083  return $queryParts;
5084  }
5085 
5091  protected function getQueryArrayJoinHelper(string $fromAlias, array $joinParts, array &$knownAliases): string
5092  {
5093  $sql = '';
5094 
5095  if (isset($joinParts['join'][$fromAlias])) {
5096  foreach ($joinParts['join'][$fromAlias] as $join) {
5097  if (array_key_exists($join['joinAlias'], $knownAliases)) {
5098  throw new \RuntimeException(
5099  'Non unique join alias: "' . $join['joinAlias'] . '" found.',
5100  1472748872
5101  );
5102  }
5103  $sql .= ' ' . strtoupper($join['joinType'])
5104  . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias']
5105  . ' ON ' . ((string)$join['joinCondition']);
5106  $knownAliases[$join['joinAlias']] = true;
5107  }
5108 
5109  foreach ($joinParts['join'][$fromAlias] as $join) {
5110  $sql .= $this->getQueryArrayJoinHelper($join['joinAlias'], $joinParts, $knownAliases);
5111  }
5112  }
5113 
5114  return $sql;
5115  }
5125  protected function getQueryConstraints(string $table, array $conf): array
5126  {
5127  // Init:
5128  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
5129  $expressionBuilder = $queryBuilder->expr();
5130  $tsfe = $this->getTypoScriptFrontendController();
5131  $constraints = [];
5132  $pid_uid_flag = 0;
5133  $enableFieldsIgnore = [];
5134  $queryParts = [
5135  'where' => null,
5136  'groupBy' => null,
5137  'orderBy' => null,
5138  ];
5139 
5140  $isInWorkspace = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'isOffline');
5141  $considerMovePointers = (
5142  $isInWorkspace && $table !== 'pages'
5143  && !empty(‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
5144  );
5145 
5146  if (trim($conf['uidInList'] ?? '')) {
5147  $listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['uidInList']));
5148 
5149  // If moved records shall be considered, select via t3ver_oid
5150  if ($considerMovePointers) {
5151  $constraints[] = (string)$expressionBuilder->or(
5152  $expressionBuilder->in($table . '.uid', $listArr),
5153  $expressionBuilder->and(
5154  $expressionBuilder->eq(
5155  $table . '.t3ver_state',
5156  VersionState::MOVE_POINTER->value
5157  ),
5158  $expressionBuilder->in($table . '.t3ver_oid', $listArr)
5159  )
5160  );
5161  } else {
5162  $constraints[] = (string)$expressionBuilder->in($table . '.uid', $listArr);
5163  }
5164  $pid_uid_flag++;
5165  }
5166 
5167  // Static_* tables are allowed to be fetched from root page
5168  if (str_starts_with($table, 'static_')) {
5169  $pid_uid_flag++;
5170  }
5171 
5172  if (trim($conf['pidInList'])) {
5173  $listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['pidInList']));
5174  // Removes all pages which are not visible for the user!
5175  $listArr = $this->checkPidArray($listArr);
5176  if (GeneralUtility::inList($conf['pidInList'], 'root')) {
5177  $listArr[] = 0;
5178  }
5179  if (GeneralUtility::inList($conf['pidInList'], '-1')) {
5180  $listArr[] = -1;
5181  $enableFieldsIgnore['pid'] = true;
5182  }
5183  if (!empty($listArr)) {
5184  $constraints[] = $expressionBuilder->in($table . '.pid', array_map('intval', $listArr));
5185  $pid_uid_flag++;
5186  } else {
5187  // If not uid and not pid then uid is set to 0 - which results in nothing!!
5188  $pid_uid_flag = 0;
5189  }
5190  }
5191 
5192  // If not uid and not pid then uid is set to 0 - which results in nothing!!
5193  if (!$pid_uid_flag) {
5194  $constraints[] = $expressionBuilder->eq($table . '.uid', 0);
5195  }
5196 
5197  $where = trim((string)$this->stdWrapValue('where', $conf));
5198  if ($where) {
5199  $constraints[] = QueryHelper::stripLogicalOperatorPrefix($where);
5200  }
5201 
5202  // Check if the default language should be fetched (= doing overlays), or if only the records of a language should be fetched
5203  // but only do this for TCA tables that have languages enabled
5204  $languageConstraint = $this->getLanguageRestriction($expressionBuilder, $table, $conf, GeneralUtility::makeInstance(Context::class));
5205  if ($languageConstraint !== null) {
5206  $constraints[] = $languageConstraint;
5207  }
5208 
5209  // Enablefields
5210  $constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->enableFields($table, -1, $enableFieldsIgnore));
5211 
5212  // MAKE WHERE:
5213  if ($constraints !== []) {
5214  $queryParts['where'] = $expressionBuilder->and(...$constraints);
5215  }
5216  // GROUP BY
5217  $groupBy = trim((string)$this->stdWrapValue('groupBy', $conf));
5218  if ($groupBy) {
5219  $queryParts['groupBy'] = QueryHelper::parseGroupBy($groupBy);
5220  }
5221 
5222  // ORDER BY
5223  $orderByString = trim((string)$this->stdWrapValue('orderBy', $conf));
5224  if ($orderByString) {
5225  $queryParts['orderBy'] = QueryHelper::parseOrderBy($orderByString);
5226  }
5227 
5228  // Return result:
5229  return $queryParts;
5230  }
5231 
5258  protected function getLanguageRestriction(ExpressionBuilder $expressionBuilder, string $table, array $conf, Context $context)
5259  {
5260  $languageField = '';
5261  $localizationParentField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? null;
5262  // Check if the table is translatable, and set the language field by default from the TCA information
5263  if (!empty($conf['languageField']) || !isset($conf['languageField'])) {
5264  if (isset($conf['languageField']) && !empty(‪$GLOBALS['TCA'][$table]['columns'][$conf['languageField']])) {
5265  $languageField = $conf['languageField'];
5266  } elseif (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['languageField']) && !empty($localizationParentField)) {
5267  $languageField = $table . '.' . ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'];
5268  }
5269  }
5270 
5271  // No language restriction enabled explicitly or available via TCA
5272  if (empty($languageField)) {
5273  return null;
5274  }
5275 
5277  $languageAspect = $context->getAspect('language');
5278  if ($languageAspect->doOverlays() && !empty($localizationParentField)) {
5279  // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will
5280  // OVERLAY the records with localized versions!
5281  $languageQuery = $expressionBuilder->in($languageField, [0, -1]);
5282  // Use this option to include records that don't have a default language counterpart ("free mode")
5283  // (originalpointerfield is 0 and the language field contains the requested language)
5284  if (isset($conf['includeRecordsWithoutDefaultTranslation']) || !empty($conf['includeRecordsWithoutDefaultTranslation.'])) {
5285  $includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.'])
5286  ? $this->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.'])
5287  : $conf['includeRecordsWithoutDefaultTranslation'];
5288  $includeRecordsWithoutDefaultTranslation = trim($includeRecordsWithoutDefaultTranslation) !== '';
5289  } else {
5290  // Option was not explicitly set, check what's in for the language overlay type.
5291  $includeRecordsWithoutDefaultTranslation = $languageAspect->getOverlayType() === $languageAspect::OVERLAYS_ON_WITH_FLOATING;
5292  }
5293  if ($includeRecordsWithoutDefaultTranslation) {
5294  $languageQuery = $expressionBuilder->or(
5295  $languageQuery,
5296  $expressionBuilder->and(
5297  $expressionBuilder->eq($table . '.' . $localizationParentField, 0),
5298  $expressionBuilder->eq($languageField, $languageAspect->getContentId())
5299  )
5300  );
5301  }
5302  return $languageQuery;
5303  }
5304  // No overlays = only fetch records given for the requested language and "all languages"
5305  return $expressionBuilder->in($languageField, [$languageAspect->getContentId(), -1]);
5306  }
5307 
5320  protected function sanitizeSelectPart($selectPart, $table)
5321  {
5322  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
5323 
5324  // Pattern matching parts
5325  $matchStart = '/(^\\s*|,\\s*|' . $table . '\\.)';
5326  $matchEnd = '(\\s*,|\\s*$)/';
5327  $necessaryFields = ['uid', 'pid'];
5328  $wsFields = ['t3ver_state'];
5329  $languageField = ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? false;
5330  if (isset(‪$GLOBALS['TCA'][$table]) && !preg_match($matchStart . '\\*' . $matchEnd, $selectPart) && !preg_match('/(count|max|min|avg|sum)\\([^\\)]+\\)|distinct/i', $selectPart)) {
5331  foreach ($necessaryFields as $field) {
5332  $match = $matchStart . $field . $matchEnd;
5333  if (!preg_match($match, $selectPart)) {
5334  $selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
5335  }
5336  }
5337  if (is_string($languageField)) {
5338  $match = $matchStart . $languageField . $matchEnd;
5339  if (!preg_match($match, $selectPart)) {
5340  $selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $languageField) . ' AS ' . $connection->quoteIdentifier($languageField);
5341  }
5342  }
5343  if (‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] ?? false) {
5344  foreach ($wsFields as $field) {
5345  $match = $matchStart . $field . $matchEnd;
5346  if (!preg_match($match, $selectPart)) {
5347  $selectPart .= ', ' . $connection->quoteIdentifier($table . '.' . $field) . ' AS ' . $connection->quoteIdentifier($field);
5348  }
5349  }
5350  }
5351  }
5352  return $selectPart;
5353  }
5354 
5362  public function checkPidArray($pageIds)
5363  {
5364  if (!is_array($pageIds) || empty($pageIds)) {
5365  return [];
5366  }
5367 
5368  $tsfe = $this->getTypoScriptFrontendController();
5369  if ($pageIds === [$tsfe->id]) {
5370  // The TypoScriptFrontendController already granted access to the current page (see getPageAndRootline())
5371  // and made sure the current doktype is a doktype whose content should be rendered, so there is no need
5372  // to check that again.
5373  return $pageIds;
5374  }
5375 
5376  $restrictionContainer = GeneralUtility::makeInstance(FrontendRestrictionContainer::class);
5377  if ($this->checkPid_badDoktypeList) {
5378  $restrictionContainer->add(GeneralUtility::makeInstance(
5379  DocumentTypeExclusionRestriction::class,
5380  // @todo this functionality should be streamlined with a default FrontendRestriction or a "LinkRestrictionContainer"
5381  GeneralUtility::intExplode(',', (string)$this->checkPid_badDoktypeList, true)
5382  ));
5383  }
5384  return $tsfe->sys_page->filterAccessiblePageIds($pageIds, $restrictionContainer);
5385  }
5386 
5397  public function getQueryMarkers($table, $conf)
5398  {
5399  if (!isset($conf['markers.']) || !is_array($conf['markers.'])) {
5400  return [];
5401  }
5402  // Parse markers and prepare their values
5403  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
5404  $markerValues = [];
5405  foreach ($conf['markers.'] as $dottedMarker => $dummy) {
5406  $marker = rtrim($dottedMarker, '.');
5407  if ($dottedMarker != $marker . '.') {
5408  continue;
5409  }
5410  // Parse definition
5411  // todo else value is always null
5412  $tempValue = isset($conf['markers.'][$dottedMarker])
5413  ? $this->stdWrap($conf['markers.'][$dottedMarker]['value'] ?? '', $conf['markers.'][$dottedMarker])
5414  : $conf['markers.'][$dottedMarker]['value'];
5415  // Quote/escape if needed
5416  if (is_numeric($tempValue)) {
5417  if ((int)$tempValue == $tempValue) {
5418  // Handle integer
5419  $markerValues[$marker] = (int)$tempValue;
5420  } else {
5421  // Handle float
5422  $markerValues[$marker] = (float)$tempValue;
5423  }
5424  } elseif ($tempValue === null) {
5425  // It represents NULL
5426  $markerValues[$marker] = 'NULL';
5427  } elseif (!empty($conf['markers.'][$dottedMarker]['commaSeparatedList'])) {
5428  // See if it is really a comma separated list of values
5429  $explodeValues = GeneralUtility::trimExplode(',', $tempValue);
5430  if (count($explodeValues) > 1) {
5431  // Handle each element of list separately
5432  $tempArray = [];
5433  foreach ($explodeValues as $listValue) {
5434  if (is_numeric($listValue)) {
5435  if ((int)$listValue == $listValue) {
5436  $tempArray[] = (int)$listValue;
5437  } else {
5438  $tempArray[] = (float)$listValue;
5439  }
5440  } else {
5441  // If quoted, remove quotes before
5442  // escaping.
5443  if (preg_match('/^\'([^\']*)\'$/', $listValue, $matches)) {
5444  $listValue = $matches[1];
5445  } elseif (preg_match('/^\\"([^\\"]*)\\"$/', $listValue, $matches)) {
5446  $listValue = $matches[1];
5447  }
5448  $tempArray[] = $connection->quote($listValue);
5449  }
5450  }
5451  $markerValues[$marker] = implode(',', $tempArray);
5452  } else {
5453  // Handle remaining values as string
5454  $markerValues[$marker] = $connection->quote($tempValue);
5455  }
5456  } else {
5457  // Handle remaining values as string
5458  $markerValues[$marker] = $connection->quote($tempValue);
5459  }
5460  }
5461  return $markerValues;
5462  }
5469  protected function getResourceFactory()
5470  {
5471  return GeneralUtility::makeInstance(ResourceFactory::class);
5472  }
5473 
5481  protected function getEnvironmentVariable($key)
5482  {
5483  if ($key === 'REQUEST_URI') {
5484  return $this->getRequest()->getAttribute('normalizedParams')->getRequestUri();
5485  }
5486  return GeneralUtility::getIndpEnv($key);
5487  }
5488 
5496  protected function getFromCache(array $configuration)
5497  {
5498  if ($this->getTypoScriptFrontendController()->no_cache) {
5499  return false;
5500  }
5501  $cacheKey = $this->calculateCacheKey($configuration);
5502  if (empty($cacheKey)) {
5503  return false;
5504  }
5505 
5506  $cacheFrontend = GeneralUtility::makeInstance(CacheManager::class)->getCache('hash');
5507  $cachedData = $cacheFrontend->get($cacheKey);
5508  if ($cachedData === false) {
5509  return false;
5510  }
5511  $this->getTypoScriptFrontendController()->addCacheTags($cachedData['cacheTags'] ?? []);
5512  return $cachedData['content'] ?? false;
5513  }
5514 
5520  protected function calculateCacheLifetime(array $configuration)
5521  {
5522  $configuration['lifetime'] = $configuration['lifetime'] ?? '';
5523  $lifetimeConfiguration = (string)$this->stdWrapValue('lifetime', $configuration);
5524 
5525  $lifetime = null; // default lifetime
5526  if (strtolower($lifetimeConfiguration) === 'unlimited') {
5527  $lifetime = 0; // unlimited
5528  } elseif ($lifetimeConfiguration > 0) {
5529  $lifetime = (int)$lifetimeConfiguration; // lifetime in seconds
5530  }
5531  return $lifetime;
5532  }
5539  protected function calculateCacheTags(array $configuration)
5540  {
5541  $configuration['tags'] = $configuration['tags'] ?? '';
5542  $tags = (string)$this->stdWrapValue('tags', $configuration);
5543  return empty($tags) ? [] : GeneralUtility::trimExplode(',', $tags);
5544  }
5545 
5551  protected function calculateCacheKey(array $configuration)
5552  {
5553  $configuration['key'] = $configuration['key'] ?? '';
5554  return $this->stdWrapValue('key', $configuration);
5555  }
5556 
5560  protected function getTimeTracker()
5561  {
5562  return GeneralUtility::makeInstance(TimeTracker::class);
5563  }
5564 
5569  public function getTypoScriptFrontendController()
5570  {
5571  return $this->typoScriptFrontendController ?: ‪$GLOBALS['TSFE'] ?? null;
5572  }
5573 
5581  protected function getContentLengthOfCurrentTag(string $theValue, int $pointer, string $currentTag): int
5582  {
5583  $tempContent = strtolower(substr($theValue, $pointer));
5584  $startTag = '<' . $currentTag;
5585  $endTag = '</' . $currentTag . '>';
5586  $offsetCount = 0;
5587 
5588  // Take care for nested tags
5589  do {
5590  $nextMatchingEndTagPosition = strpos($tempContent, $endTag);
5591  // only match tag `a` in `<a href"...">` but not in `<abbr>`
5592  $nextSameTypeTagPosition = preg_match(
5593  '#' . $startTag . '[\s/>]#',
5594  $tempContent,
5595  $nextSameStartTagMatches,
5596  PREG_OFFSET_CAPTURE
5597  ) ? $nextSameStartTagMatches[0][1] : false;
5598 
5599  // filter out nested tag contents to help getting the correct closing tag
5600  if ($nextMatchingEndTagPosition !== false && $nextSameTypeTagPosition !== false && $nextSameTypeTagPosition < $nextMatchingEndTagPosition) {
5601  $lastOpeningTagStartPosition = (int)strrpos(substr($tempContent, 0, $nextMatchingEndTagPosition), $startTag);
5602  $closingTagEndPosition = $nextMatchingEndTagPosition + strlen($endTag);
5603  $offsetCount += $closingTagEndPosition - $lastOpeningTagStartPosition;
5605  // replace content from latest tag start to latest tag end
5606  $tempContent = substr($tempContent, 0, $lastOpeningTagStartPosition) . substr($tempContent, $closingTagEndPosition);
5607  }
5608  } while (
5609  ($nextMatchingEndTagPosition !== false && $nextSameTypeTagPosition !== false) &&
5610  $nextSameTypeTagPosition < $nextMatchingEndTagPosition
5611  );
5612 
5613  // if no closing tag is found we use length of the whole content
5614  $endingOffset = strlen($tempContent);
5615  if ($nextMatchingEndTagPosition !== false) {
5616  $endingOffset = $nextMatchingEndTagPosition + $offsetCount;
5617  }
5618 
5619  return $endingOffset;
5620  }
5621 
5622  protected function shallDebug(): bool
5623  {
5624  $tsfe = $this->getTypoScriptFrontendController();
5625  if ($tsfe !== null && isset($tsfe->config['config']['debug'])) {
5626  return (bool)($tsfe->config['config']['debug']);
5627  }
5628  return !empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['debug']);
5629  }
5648  public function getRequest(): ServerRequestInterface
5649  {
5650  if ($this->request instanceof ServerRequestInterface) {
5651  return $this->request;
5652  }
5653  if ((‪$GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface) {
5654  // @todo: We may want to deprecate this fallback and force consumers
5655  // to setRequest() after object instantiation / unserialization instead.
5656  return ‪$GLOBALS['TYPO3_REQUEST'];
5657  }
5658  throw new ‪ContentRenderingException(
5659  'PSR-7 request is missing in ContentObjectRenderer. Inject with start(), setRequest() or provide via $GLOBALS[\'TYPO3_REQUEST\'].',
5660  1607172972
5661  );
5662  }
5663 }
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_noTrimWrap
‪string stdWrap_noTrimWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2201
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$parentRecordNumber
‪int $parentRecordNumber
Definition: ContentObjectRenderer.php:299
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\http_makelinks
‪string http_makelinks(string $data, array $conf)
Definition: ContentObjectRenderer.php:3536
‪TYPO3\CMS\Core\Resource\FileReference\getProperty
‪getProperty(string $key)
Definition: FileReference.php:107
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\mergeTSRef
‪array mergeTSRef(array $typoScriptArray, string $propertyName)
Definition: ContentObjectRenderer.php:4681
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_case
‪string stdWrap_case($content='', $conf=[])
Definition: ContentObjectRenderer.php:1906
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_htmlSpecialChars
‪string stdWrap_htmlSpecialChars($content='', $conf=[])
Definition: ContentObjectRenderer.php:1996
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectStdWrapHookInterface
Definition: ContentObjectStdWrapHookInterface.php:22
‪TYPO3\CMS\Core\Database\Query\Restriction\DocumentTypeExclusionRestriction
Definition: DocumentTypeExclusionRestriction.php:27
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\shallDebug
‪shallDebug()
Definition: ContentObjectRenderer.php:5604
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setCurrentFile
‪setCurrentFile($fileObject)
Definition: ContentObjectRenderer.php:1057
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_expandList
‪string stdWrap_expandList($content='')
Definition: ContentObjectRenderer.php:1797
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFileDataKey
‪string int getFileDataKey($key)
Definition: ContentObjectRenderer.php:4174
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\OBJECTTYPE_USER
‪const OBJECTTYPE_USER
Definition: ContentObjectRenderer.php:370
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cacheRead
‪string stdWrap_cacheRead($content='', $conf=[])
Definition: ContentObjectRenderer.php:1222
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCurrentTable
‪string getCurrentTable()
Definition: ContentObjectRenderer.php:471
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\listNum
‪string listNum($content, $listNum, $delimeter=',')
Definition: ContentObjectRenderer.php:2526
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\in
‪in(string $fieldName, $value)
Definition: ExpressionBuilder.php:233
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\fe_user
‪$this fe_user
Definition: TypoScriptFrontendController.php:426
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_ifNull
‪string stdWrap_ifNull($content='', $conf=[])
Definition: ContentObjectRenderer.php:1442
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_insertData
‪string stdWrap_insertData($content='')
Definition: ContentObjectRenderer.php:2330
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cObjGetSeparated
‪list< string > cObjGetSeparated(?array $setup, string $addKey='')
Definition: ContentObjectRenderer.php:565
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getUserObjectType
‪mixed getUserObjectType()
Definition: ContentObjectRenderer.php:773
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection\create
‪static create(string $jsonString, array $tcaConfig=[])
Definition: CropVariantCollection.php:37
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_orderedStdWrap
‪string stdWrap_orderedStdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2301
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:26
‪TYPO3\CMS\Core\Utility\DebugUtility\debugTrail
‪static string debugTrail(bool $prependFileNames=false)
Definition: DebugUtility.php:64
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_csConv
‪string stdWrap_csConv($content='', $conf=[])
Definition: ContentObjectRenderer.php:1633
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\round
‪string round($content, array $conf=[])
Definition: ContentObjectRenderer.php:3016
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getResourceFactory
‪ResourceFactory getResourceFactory()
Definition: ContentObjectRenderer.php:5451
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\encaps_lineSplit
‪string encaps_lineSplit($theValue, $conf)
Definition: ContentObjectRenderer.php:3415
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\start
‪start($data, $table='')
Definition: ContentObjectRenderer.php:441
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\imageLinkWrap
‪string imageLinkWrap($string, $imageFile, $conf)
Definition: ContentObjectRenderer.php:894
‪debug
‪debug(mixed $variable='', ?string $title=null)
Definition: GlobalDebugFunctions.php:21
‪TYPO3\CMS\Core\Context\Context\getAspect
‪getAspect(string $name)
Definition: Context.php:97
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\substring
‪string substring($content, $options)
Definition: ContentObjectRenderer.php:2751
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_listNum
‪string stdWrap_listNum($content='', $conf=[])
Definition: ContentObjectRenderer.php:1491
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentFile
‪File FileReference Folder string null $currentFile
Definition: ContentObjectRenderer.php:328
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_prefixComment
‪string stdWrap_prefixComment($content='', $conf=[])
Definition: ContentObjectRenderer.php:2379
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setUserObjectType
‪setUserObjectType($userObjectType)
Definition: ContentObjectRenderer.php:783
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrap
‪string stdWrap_wrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2183
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\determineExceptionHandlerClassName
‪string null determineExceptionHandlerClassName($configuration)
Definition: ContentObjectRenderer.php:721
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_replacement
‪string stdWrap_replacement($content='', $conf=[])
Definition: ContentObjectRenderer.php:1695
‪TYPO3\CMS\Core\Versioning\VersionState
‪VersionState
Definition: VersionState.php:22
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area
Definition: Area.php:23
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGECROPSCALEMASK
‪const CONTEXT_IMAGECROPSCALEMASK
Definition: ProcessedFile.php:61
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getSite
‪getSite()
Definition: TypoScriptFrontendController.php:2511
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:27
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentRecord
‪string $currentRecord
Definition: ContentObjectRenderer.php:287
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$doConvertToUserIntObject
‪bool $doConvertToUserIntObject
Definition: ContentObjectRenderer.php:333
‪TYPO3\CMS\Frontend\ContentObject
Definition: AbstractContentObject.php:18
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cropHTML
‪string cropHTML(string $content, string $options)
Definition: ContentObjectRenderer.php:2797
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCurrentFile
‪File FileReference Folder string null getCurrentFile()
Definition: ContentObjectRenderer.php:1067
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\uniqueHash
‪string uniqueHash($str='')
Definition: TypoScriptFrontendController.php:2324
‪TYPO3\CMS\Core\Utility\MathUtility\calculateWithParentheses
‪static string calculateWithParentheses(string $string)
Definition: MathUtility.php:167
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\parseFuncInternal
‪string parseFuncInternal($theValue, $conf)
Definition: ContentObjectRenderer.php:3202
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setParent
‪setParent($data, $currentRecord)
Definition: ContentObjectRenderer.php:505
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer
Definition: FilePathSanitizer.php:39
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_prepend
‪string stdWrap_prepend($content='', $conf=[])
Definition: ContentObjectRenderer.php:2257
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrap
‪string stdWrap_stdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:1547
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stdWrapHookObjects
‪array $stdWrapHookObjects
Definition: ContentObjectRenderer.php:318
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:100
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setCurrentVal
‪setCurrentVal($value)
Definition: ContentObjectRenderer.php:537
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\parseFunc
‪string parseFunc($theValue, ?array $conf, ?string $ref=null)
Definition: ContentObjectRenderer.php:3070
‪TYPO3\CMS\Core\Resource\FileReference
Definition: FileReference.php:36
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\or
‪or(CompositeExpression|string|null ... $expressions)
Definition: ExpressionBuilder.php:77
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\HTMLcaseshift
‪string HTMLcaseshift($theValue, $case)
Definition: ContentObjectRenderer.php:4606
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface
Definition: ContentObjectGetImageResourceHookInterface.php:22
‪TYPO3\CMS\Core\Utility\DebugUtility\viewArray
‪static string viewArray(mixed $array_in)
Definition: DebugUtility.php:113
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getContext
‪getContext()
Definition: TypoScriptFrontendController.php:2516
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getContentLengthOfCurrentTag
‪getContentLengthOfCurrentTag(string $theValue, int $pointer, string $currentTag)
Definition: ContentObjectRenderer.php:5563
‪TYPO3\CMS\Frontend\ContentObject\Exception\ExceptionHandlerInterface
Definition: ExceptionHandlerInterface.php:24
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:33
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_round
‪string stdWrap_round($content='', $conf=[])
Definition: ContentObjectRenderer.php:1772
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentRecordNumber
‪int $currentRecordNumber
Definition: ContentObjectRenderer.php:293
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stripHtml
‪string stdWrap_stripHtml($content='')
Definition: ContentObjectRenderer.php:1957
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_field
‪string null stdWrap_field($content='', $conf=[])
Definition: ContentObjectRenderer.php:1326
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_HTMLparser
‪string stdWrap_HTMLparser($content='', $conf=[])
Definition: ContentObjectRenderer.php:1665
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_lang
‪string stdWrap_lang($content='', $conf=[])
Definition: ContentObjectRenderer.php:1283
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getValueFromRecursiveData
‪getValueFromRecursiveData(array $keys, mixed $startValue)
Definition: ContentObjectRenderer.php:4279
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_br
‪string stdWrap_br($content='')
Definition: ContentObjectRenderer.php:2039
‪TYPO3\CMS\Frontend\ContentObject\Exception\ContentRenderingException
Definition: ContentRenderingException.php:24
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrapAlign
‪string stdWrap_wrapAlign($content='', $conf=[])
Definition: ContentObjectRenderer.php:2147
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getEnvironmentVariable
‪string getEnvironmentVariable($key)
Definition: ContentObjectRenderer.php:5463
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCropAreaFromFileReference
‪Area null getCropAreaFromFileReference(FileReference $fileReference, array $fileArray)
Definition: ContentObjectRenderer.php:3796
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\and
‪and(CompositeExpression|string|null ... $expressions)
Definition: ExpressionBuilder.php:69
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_split
‪string stdWrap_split($content='', $conf=[])
Definition: ContentObjectRenderer.php:1682
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:55
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_numRows
‪string stdWrap_numRows($content='', $conf=[])
Definition: ContentObjectRenderer.php:1368
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cObjGetSingle
‪string cObjGetSingle(string $name, $conf, $TSkey='__')
Definition: ContentObjectRenderer.php:591
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cacheStore
‪string stdWrap_cacheStore($content='', $conf=[])
Definition: ContentObjectRenderer.php:2413
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$getImgResourceHookObjects
‪array $getImgResourceHookObjects
Definition: ContentObjectRenderer.php:324
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapProcess
‪string stdWrap_stdWrapProcess($content='', $conf=[])
Definition: ContentObjectRenderer.php:1561
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_if
‪string stdWrap_if($content='', $conf=[])
Definition: ContentObjectRenderer.php:1596
‪TYPO3\CMS\Core\Text\TextCropper
Definition: TextCropper.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\checkIf
‪checkIf($conf)
Definition: ContentObjectRenderer.php:2551
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrapValue
‪string int bool null stdWrapValue($key, array $config, $defaultValue='')
Definition: ContentObjectRenderer.php:1181
‪TYPO3\CMS\Core\Service\FlexFormService
Definition: FlexFormService.php:25
‪TYPO3\CMS\Core\Localization\DateFormatter
Definition: DateFormatter.php:27
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapPreProcess
‪string stdWrap_stdWrapPreProcess($content='', $conf=[])
Definition: ContentObjectRenderer.php:1206
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\wrap
‪string wrap($content, $wrap, $char='|')
Definition: ContentObjectRenderer.php:4465
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static getValueByPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:176
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\exec_getQuery
‪Result exec_getQuery($table, $conf)
Definition: ContentObjectRenderer.php:4778
‪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:5240
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$userObjectType
‪int bool $userObjectType
Definition: ContentObjectRenderer.php:340
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_brTag
‪string stdWrap_brTag($content='', $conf=[])
Definition: ContentObjectRenderer.php:2053
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_rawUrlEncode
‪string stdWrap_rawUrlEncode($content='')
Definition: ContentObjectRenderer.php:1982
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Core\Type\BitSet
Definition: BitSet.php:66
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getGetImgResourceHookObjects
‪array getGetImgResourceHookObjects()
Definition: ContentObjectRenderer.php:482
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrap3
‪string stdWrap_wrap3($content='', $conf=[])
Definition: ContentObjectRenderer.php:2284
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_formattedDate
‪string stdWrap_formattedDate(string $content, array $conf)
Definition: ContentObjectRenderer.php:1867
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getLanguage
‪getLanguage()
Definition: TypoScriptFrontendController.php:2506
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:27
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:46
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_preIfEmptyListNum
‪string stdWrap_preIfEmptyListNum($content='', $conf=[])
Definition: ContentObjectRenderer.php:1429
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\caseshift
‪string caseshift($theValue, $case)
Definition: ContentObjectRenderer.php:4564
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$parentRecord
‪array $parentRecord
Definition: ContentObjectRenderer.php:305
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_date
‪string stdWrap_date($content='', $conf=[])
Definition: ContentObjectRenderer.php:1811
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\createExceptionHandler
‪ExceptionHandlerInterface null createExceptionHandler($configuration=[])
Definition: ContentObjectRenderer.php:700
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_htmlSanitize
‪stdWrap_htmlSanitize(string $content='', array $conf=[])
Definition: ContentObjectRenderer.php:2390
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_keywords
‪string stdWrap_keywords($content='')
Definition: ContentObjectRenderer.php:2079
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_preCObject
‪string stdWrap_preCObject($content='', $conf=[])
Definition: ContentObjectRenderer.php:2120
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_required
‪string stdWrap_required($content='')
Definition: ContentObjectRenderer.php:1578
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_current
‪string stdWrap_current($content='', $conf=[])
Definition: ContentObjectRenderer.php:1340
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\__sleep
‪array __sleep()
Definition: ContentObjectRenderer.php:390
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_setContentToCurrent
‪string stdWrap_setContentToCurrent($content='')
Definition: ContentObjectRenderer.php:1255
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap
‪string null stdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:1086
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\cObjGet
‪string cObjGet($setup, $addKey='')
Definition: ContentObjectRenderer.php:551
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_numberFormat
‪string stdWrap_numberFormat($content='', $conf=[])
Definition: ContentObjectRenderer.php:1785
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_setCurrent
‪string stdWrap_setCurrent($content='', $conf=[])
Definition: ContentObjectRenderer.php:1269
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\convertToUserIntObject
‪convertToUserIntObject()
Definition: ContentObjectRenderer.php:791
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_intval
‪string stdWrap_intval($content='')
Definition: ContentObjectRenderer.php:1741
‪TYPO3\CMS\Core\Utility\GeneralUtility\expandList
‪static string expandList($list)
Definition: GeneralUtility.php:433
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\insertData
‪string insertData($str)
Definition: ContentObjectRenderer.php:2689
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\__construct
‪__construct(TypoScriptFrontendController $typoScriptFrontendController=null, ContainerInterface $container=null)
Definition: ContentObjectRenderer.php:372
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_ifEmpty
‪string stdWrap_ifEmpty($content='', $conf=[])
Definition: ContentObjectRenderer.php:1456
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\createUrl
‪string createUrl(array $conf)
Definition: ContentObjectRenderer.php:4427
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_parseFunc
‪string stdWrap_parseFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:1651
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_hash
‪string stdWrap_hash($content='', array $conf=[])
Definition: ContentObjectRenderer.php:1754
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$data
‪array $data
Definition: ContentObjectRenderer.php:266
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:38
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\__wakeup
‪__wakeup()
Definition: ContentObjectRenderer.php:409
‪TYPO3\CMS\Frontend\Page\PageLayoutResolver
Definition: PageLayoutResolver.php:32
‪TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
Definition: ResourceDoesNotExistException.php:23
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_outerWrap
‪string stdWrap_outerWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2318
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\numberFormat
‪string numberFormat($content, $conf)
Definition: ContentObjectRenderer.php:3044
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\keywords
‪string keywords($content)
Definition: ContentObjectRenderer.php:4544
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectGetDataHookInterface
Definition: ContentObjectGetDataHookInterface.php:22
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\typoLink
‪string LinkResult typoLink(string $linkText, array $conf)
Definition: ContentObjectRenderer.php:4358
‪TYPO3\CMS\Core\Html\SanitizerInitiator
Definition: SanitizerInitiator.php:28
‪TYPO3\CMS\Core\Utility\GeneralUtility\hmac
‪static string hmac($input, $additionalSecret='')
Definition: GeneralUtility.php:473
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\noTrimWrap
‪string noTrimWrap($content, $wrap, $char='|')
Definition: ContentObjectRenderer.php:4484
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFieldVal
‪string null getFieldVal($field)
Definition: ContentObjectRenderer.php:3869
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileReferenceObject
‪FileReference getFileReferenceObject($uid, array $fileReferenceData=[], $raw=false)
Definition: ResourceFactory.php:417
‪TYPO3\CMS\Core\Page\DefaultJavaScriptAssetTrait
Definition: DefaultJavaScriptAssetTrait.php:30
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\HTMLparser_TSbridge
‪string HTMLparser_TSbridge($theValue, $conf)
Definition: ContentObjectRenderer.php:2653
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$currentValKey
‪string $currentValKey
Definition: ContentObjectRenderer.php:280
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\createCropAreaFromJsonString
‪createCropAreaFromJsonString(string $cropSettings, string $cropVariant)
Definition: ContentObjectRenderer.php:3853
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_postCObject
‪string stdWrap_postCObject($content='', $conf=[])
Definition: ContentObjectRenderer.php:2133
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\dataWrap
‪string dataWrap($content, $wrap)
Definition: ContentObjectRenderer.php:2669
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getRecords
‪array getRecords($tableName, array $queryConfiguration)
Definition: ContentObjectRenderer.php:4795
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_strftime
‪string stdWrap_strftime($content='', $conf=[])
Definition: ContentObjectRenderer.php:1828
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calculateCacheTags
‪array calculateCacheTags(array $configuration)
Definition: ContentObjectRenderer.php:5521
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject
Definition: AbstractContentObject.php:31
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_substring
‪string stdWrap_substring($content='', $conf=[])
Definition: ContentObjectRenderer.php:1932
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:57
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\mailto_makelinks
‪string mailto_makelinks(string $data, array $conf)
Definition: ContentObjectRenderer.php:3597
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_innerWrap2
‪string stdWrap_innerWrap2($content='', $conf=[])
Definition: ContentObjectRenderer.php:2107
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_ifBlank
‪string stdWrap_ifBlank($content='', $conf=[])
Definition: ContentObjectRenderer.php:1473
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapOverride
‪string stdWrap_stdWrapOverride($content='', $conf=[])
Definition: ContentObjectRenderer.php:1395
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getContentObject
‪getContentObject($name)
Definition: ContentObjectRenderer.php:621
‪TYPO3\CMS\Core\Utility\DebugUtility
Definition: DebugUtility.php:27
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$lastTypoLinkResult
‪LinkResultInterface $lastTypoLinkResult
Definition: ContentObjectRenderer.php:312
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryArray
‪array getQueryArray(QueryBuilder $queryBuilder)
Definition: ContentObjectRenderer.php:5029
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\setRequest
‪setRequest(?ServerRequestInterface $request)
Definition: ContentObjectRenderer.php:378
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$parameters
‪array $parameters
Definition: ContentObjectRenderer.php:276
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_debug
‪string stdWrap_debug($content='')
Definition: ContentObjectRenderer.php:2469
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getRequest
‪getRequest()
Definition: ContentObjectRenderer.php:5630
‪TYPO3\CMS\Frontend\Imaging\GifBuilder
Definition: GifBuilder.php:57
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTypoScriptFrontendController
‪TypoScriptFrontendController null getTypoScriptFrontendController()
Definition: ContentObjectRenderer.php:5551
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$request
‪ServerRequestInterface $request
Definition: ContentObjectRenderer.php:357
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_typolink
‪string stdWrap_typolink($content='', $conf=[])
Definition: ContentObjectRenderer.php:2166
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_dataWrap
‪string stdWrap_dataWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2244
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stdWrapRecursionLevel
‪int $stdWrapRecursionLevel
Definition: ContentObjectRenderer.php:348
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stopRendering
‪array $stopRendering
Definition: ContentObjectRenderer.php:344
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\createLink
‪createLink(string $linkText, array $conf)
Definition: ContentObjectRenderer.php:4404
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:47
‪TYPO3\CMS\Core\TypoScript\TypoScriptService
Definition: TypoScriptService.php:27
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calculateCacheLifetime
‪int null calculateCacheLifetime(array $configuration)
Definition: ContentObjectRenderer.php:5502
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$container
‪ContainerInterface null $container
Definition: ContentObjectRenderer.php:95
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryArrayJoinHelper
‪getQueryArrayJoinHelper(string $fromAlias, array $joinParts, array &$knownAliases)
Definition: ContentObjectRenderer.php:5073
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_encapsLines
‪string stdWrap_encapsLines($content='', $conf=[])
Definition: ContentObjectRenderer.php:2067
‪TYPO3\CMS\Core\Resource\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calc
‪int calc($val)
Definition: ContentObjectRenderer.php:2819
‪TYPO3\CMS\Webhooks\Message\$url
‪identifier readonly UriInterface $url
Definition: LoginErrorOccurredMessage.php:36
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_append
‪string stdWrap_append($content='', $conf=[])
Definition: ContentObjectRenderer.php:2270
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\render
‪render(AbstractContentObject $contentObject, $configuration=[])
Definition: ContentObjectRenderer.php:644
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_bytes
‪string stdWrap_bytes($content='', $conf=[])
Definition: ContentObjectRenderer.php:1919
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_crop
‪string stdWrap_crop($content='', $conf=[])
Definition: ContentObjectRenderer.php:1970
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getData
‪string getData($string, $fieldArray=null)
Definition: ContentObjectRenderer.php:3892
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$stdWrapOrder
‪array $stdWrapOrder
Definition: ContentObjectRenderer.php:103
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\addCacheTags
‪addCacheTags(array $tags)
Definition: TypoScriptFrontendController.php:1801
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:103
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\TimeTracker\TimeTracker\setTSlogMessage
‪setTSlogMessage(string $content, string $logLevel=LogLevel::INFO)
Definition: TimeTracker.php:173
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryConstraints
‪array getQueryConstraints(string $table, array $conf)
Definition: ContentObjectRenderer.php:5107
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_debugData
‪string stdWrap_debugData($content='')
Definition: ContentObjectRenderer.php:2495
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_wrap2
‪string stdWrap_wrap2($content='', $conf=[])
Definition: ContentObjectRenderer.php:2226
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCropAreaFromFromTypoScriptSettings
‪Area null getCropAreaFromFromTypoScriptSettings(FileInterface $file, array $fileArray)
Definition: ContentObjectRenderer.php:3815
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:33
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\crop
‪string crop($content, $options)
Definition: ContentObjectRenderer.php:2769
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cObject
‪string stdWrap_cObject($content='', $conf=[])
Definition: ContentObjectRenderer.php:1354
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_prioriCalc
‪string stdWrap_prioriCalc($content='', $conf=[])
Definition: ContentObjectRenderer.php:1709
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\replacementSingle
‪string replacementSingle($content, array $configuration)
Definition: ContentObjectRenderer.php:2947
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\lastChanged
‪lastChanged($tstamp)
Definition: ContentObjectRenderer.php:1037
‪TYPO3\CMS\Core\Html\HtmlCropper
Definition: HtmlCropper.php:24
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection
Definition: CropVariantCollection.php:23
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_char
‪string stdWrap_char($content='', $conf=[])
Definition: ContentObjectRenderer.php:1729
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_stdWrapPostProcess
‪string stdWrap_stdWrapPostProcess($content='', $conf=[])
Definition: ContentObjectRenderer.php:2453
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:89
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\numRows
‪int numRows($conf)
Definition: ContentObjectRenderer.php:2510
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$typoScriptFrontendController
‪TypoScriptFrontendController null $typoScriptFrontendController
Definition: ContentObjectRenderer.php:352
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileObject
‪File getFileObject($uid, array $fileData=[])
Definition: ResourceFactory.php:191
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:421
‪TYPO3\CMS\Core\Utility\StringUtility\multibyteStringPad
‪static multibyteStringPad(string $string, int $length, string $pad_string=' ', int $pad_type=STR_PAD_RIGHT, string $encoding='UTF-8')
Definition: StringUtility.php:131
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_debugFunc
‪string stdWrap_debugFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:2482
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getImgResource
‪array null getImgResource($file, $fileArray)
Definition: ContentObjectRenderer.php:3650
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getTimeTracker
‪TimeTracker getTimeTracker()
Definition: ContentObjectRenderer.php:5542
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\rootLineValue
‪string rootLineValue($key, $field, $slideBack=false, $altRootLine='')
Definition: ContentObjectRenderer.php:4239
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:48
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\prefixComment
‪string prefixComment($str, $conf, $content)
Definition: ContentObjectRenderer.php:2726
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\mergeExceptionHandlerConfiguration
‪array mergeExceptionHandlerConfiguration($configuration)
Definition: ContentObjectRenderer.php:751
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\searchWhere
‪string searchWhere($searchWords, $searchFieldList, $searchTable)
Definition: ContentObjectRenderer.php:4730
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\callUserFunction
‪mixed callUserFunction($funcName, $conf, $content)
Definition: ContentObjectRenderer.php:4504
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_data
‪string stdWrap_data($_='', $conf=[])
Definition: ContentObjectRenderer.php:1313
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_override
‪string stdWrap_override($content='', $conf=[])
Definition: ContentObjectRenderer.php:1412
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\readFlexformIntoConf
‪readFlexformIntoConf($flexData, &$conf, $recursive=false)
Definition: ContentObjectRenderer.php:812
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_innerWrap
‪string stdWrap_innerWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:2093
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getSlidePids
‪string getSlidePids($pidList, $pidConf)
Definition: ContentObjectRenderer.php:858
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_age
‪string stdWrap_age($content='', $conf=[])
Definition: ContentObjectRenderer.php:1892
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calcAge
‪string calcAge($seconds, $labels)
Definition: ContentObjectRenderer.php:4634
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$table
‪string $table
Definition: ContentObjectRenderer.php:270
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_cropHTML
‪string stdWrap_cropHTML($content='', $conf=[])
Definition: ContentObjectRenderer.php:1945
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getCurrentVal
‪mixed getCurrentVal()
Definition: ContentObjectRenderer.php:526
‪TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer
Definition: FrontendRestrictionContainer.php:30
‪TYPO3\CMS\Core\TimeTracker\TimeTracker
Definition: TimeTracker.php:32
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\checkPidArray
‪array checkPidArray($pageIds)
Definition: ContentObjectRenderer.php:5344
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getFromCache
‪string bool getFromCache(array $configuration)
Definition: ContentObjectRenderer.php:5478
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_addPageCacheTags
‪string stdWrap_addPageCacheTags($content='', $conf=[])
Definition: ContentObjectRenderer.php:1238
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\sanitizeSelectPart
‪string sanitizeSelectPart($selectPart, $table)
Definition: ContentObjectRenderer.php:5302
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQuery
‪mixed getQuery($table, $conf, $returnQueryArray=false)
Definition: ContentObjectRenderer.php:4833
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_strtotime
‪string stdWrap_strtotime($content='', $conf=[])
Definition: ContentObjectRenderer.php:1850
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\OBJECTTYPE_USER_INT
‪const OBJECTTYPE_USER_INT
Definition: ContentObjectRenderer.php:364
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_trim
‪string stdWrap_trim($content='')
Definition: ContentObjectRenderer.php:1503
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static getContext()
Definition: Environment.php:128
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:16
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_preUserFunc
‪string stdWrap_preUserFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:1381
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\calculateCacheKey
‪string calculateCacheKey(array $configuration)
Definition: ContentObjectRenderer.php:5533
‪TYPO3\CMS\Core\Utility\GeneralUtility\xml2array
‪static array string xml2array(string $string, string $NSprefix='', bool $reportDocTag=false)
Definition: GeneralUtility.php:1242
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getKey
‪int getKey($key, $arr)
Definition: ContentObjectRenderer.php:4320
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_postUserFuncInt
‪string stdWrap_postUserFuncInt($content='', $conf=[])
Definition: ContentObjectRenderer.php:2357
‪TYPO3\CMS\Core\Html\SanitizerBuilderFactory
Definition: SanitizerBuilderFactory.php:37
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_doubleBrTag
‪string stdWrap_doubleBrTag($content='', $conf=[])
Definition: ContentObjectRenderer.php:2026
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\typoLink_URL
‪string typoLink_URL($conf)
Definition: ContentObjectRenderer.php:4444
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\splitObj
‪string splitObj($value, $conf)
Definition: ContentObjectRenderer.php:2861
‪TYPO3\CMS\Frontend\ContentObject\Exception\ProductionExceptionHandler
Definition: ProductionExceptionHandler.php:32
‪TYPO3\CMS\Core\Resource\ResourceFactory\retrieveFileOrFolderObject
‪File Folder null retrieveFileOrFolderObject($input)
Definition: ResourceFactory.php:273
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_strPad
‪string stdWrap_strPad($content='', $conf=[])
Definition: ContentObjectRenderer.php:1516
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject\render
‪string render($conf=[])
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface
Definition: ContentObjectPostInitHookInterface.php:23
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_encodeForJavaScriptValue
‪string stdWrap_encodeForJavaScriptValue($content='')
Definition: ContentObjectRenderer.php:2013
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\$checkPid_badDoktypeList
‪string int null $checkPid_badDoktypeList
Definition: ContentObjectRenderer.php:310
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\replacement
‪string replacement($content, array $configuration)
Definition: ContentObjectRenderer.php:2927
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_fieldRequired
‪string stdWrap_fieldRequired($content='', $conf=[])
Definition: ContentObjectRenderer.php:1614
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap_postUserFunc
‪string stdWrap_postUserFunc($content='', $conf=[])
Definition: ContentObjectRenderer.php:2343
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getQueryMarkers
‪array getQueryMarkers($table, $conf)
Definition: ContentObjectRenderer.php:5379
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getGlobal
‪mixed getGlobal($keyString, $source=null)
Definition: ContentObjectRenderer.php:4264