TYPO3 CMS  TYPO3_6-2
TemplateService.php
Go to the documentation of this file.
1 <?php
3 
19 
28 
29  // Debugging, analysis:
30  // If set, the global tt-timeobject is used to log the performance.
34  public $tt_track = 1;
35 
36  // If set, the template is always rendered. Used from Admin Panel.
41 
42  // Backend Analysis modules settings:
43  // This array is passed on to matchObj by generateConfig(). If it holds elements, they are used for matching instead. See commment at the match-class. Used for backend modules only. Never frontend!
47  public $matchAlternative = array();
48 
49  // If set, the match-class matches everything! Used for backend modules only. Never frontend!
53  public $matchAll = 0;
54 
58  public $backend_info = 0;
59 
60  // Set from the backend - used to set an absolute path (PATH_site) so that relative resources are properly found with getFileName()
64  public $getFileName_backPath = '';
65 
66  // Externally set breakpoints (used by Backend Modules)
70  public $ext_constants_BRP = 0;
71 
75  public $ext_config_BRP = 0;
76 
80  public $ext_regLinenumbers = FALSE;
81 
85  public $ext_regComments = FALSE;
86 
87  // Constants:
91  public $tempPath = 'typo3temp/';
92 
93  // Set Internally:
94  // This MUST be initialized by the init() function
98  public $whereClause = '';
99 
103  public $debug = 0;
104 
105  // This is the only paths (relative!!) that are allowed for resources in TypoScript. Should all be appended with '/'. You can extend these by the global array TYPO3_CONF_VARS. See init() function.
109  public $allowedPaths = array();
110 
111  // See init(); Set if preview of some kind is enabled.
116 
117  // Set, if the TypoScript template structure is loaded and OK, see ->start()
121  public $loaded = 0;
122 
123  // Default TypoScript Setup code
127  public $setup = array(
128  'styles.' => array(
129  'insertContent' => 'CONTENT',
130  'insertContent.' => array(
131  'table' => 'tt_content',
132  'select.' => array(
133  'orderBy' => 'sorting',
134  'where' => 'colPos=0',
135  'languageField' => 'sys_language_uid'
136  )
137  )
138  ),
139  'config.' => array(
140  'extTarget' => '_top',
141  'uniqueLinkVars' => 1
142  )
143  );
144 
148  public $flatSetup = array();
149 
150  // Default TypoScript Constants code:
154  public $const = array(
155  '_clear' => '<img src="clear.gif" width="1" height="1" alt="" />',
156  '_blackBorderWrap' => '<table border="0" bgcolor="black" cellspacing="0" cellpadding="1"><tr><td> | </td></tr></table>',
157  '_tableWrap' => '<table border="0" cellspacing="0" cellpadding="0"> | </table>',
158  '_tableWrap_DEBUG' => '<table border="1" cellspacing="0" cellpadding="0"> | </table>',
159  '_stdFrameParams' => 'frameborder="no" marginheight="0" marginwidth="0" noresize="noresize"',
160  '_stdFramesetParams' => 'border="0" framespacing="0" frameborder="no"'
161  );
162 
163  // For fetching TypoScript code from template hierarchy before parsing it. Each array contains code field values from template records/files:
164  // Setup field
168  public $config = array();
169 
170  // Constant field
174  public $constants = array();
175 
180  protected $templateIncludePaths = array();
181 
182  // For Template Analyser in backend
186  public $hierarchyInfo = array();
187 
188  // For Template Analyser in backend (setup content only)
192  public $hierarchyInfoToRoot = array();
193 
194  // Next-level flag (see runThroughTemplates())
198  public $nextLevel = 0;
199 
200  // The Page UID of the root page
204  public $rootId;
205 
206  // The rootline from current page to the root page
210  public $rootLine;
211 
212  // Rootline all the way to the root. Set but runThroughTemplates
217 
218  // A pointer to the last entry in the rootline where a template was found.
223 
224  // Array of arrays with title/uid of templates in hierarchy
228  public $rowSum;
229 
230  // The current site title field.
234  public $sitetitle = '';
235 
236  // Tracking all conditions found during parsing of TypoScript. Used for the "all" key in currentPageData
240  public $sections;
241 
242  // Tracking all matching conditions found
247 
253  public $clearList_const = array();
254 
260  public $clearList_setup = array();
261 
265  public $parserErrors = array();
266 
270  public $setup_constants = array();
271 
272  // Other:
273  // Used by getFileName for caching of references to file resources
277  public $fileCache = array();
278 
279  // Keys are frame names and values are type-values, which must be used to refer correctly to the content of the frames.
283  public $frames = array();
284 
285  // Contains mapping of Page id numbers to MP variables.
289  public $MPmap = '';
290 
300  protected $extensionStaticsProcessed = FALSE;
301 
307  protected $processExtensionStatics = FALSE;
308 
316  protected $isDefaultTypoScriptAdded = FALSE;
317 
326  protected $processIncludesHasBeenRun = FALSE;
327 
331  public function getProcessExtensionStatics() {
333  }
334 
339  $this->processExtensionStatics = (bool) $processExtensionStatics;
340  }
341 
350  public function init() {
351  // $this->whereClause is used only to select templates from sys_template.
352  // $GLOBALS['SIM_ACCESS_TIME'] is used so that we're able to simulate a later time as a test...
353  $this->whereClause = 'AND deleted=0 ';
354  if (!$GLOBALS['TSFE']->showHiddenRecords) {
355  $this->whereClause .= 'AND hidden=0 ';
356  }
357  if ($GLOBALS['TSFE']->showHiddenRecords || $GLOBALS['SIM_ACCESS_TIME'] != $GLOBALS['ACCESS_TIME']) {
358  // Set the simulation flag, if simulation is detected!
359  $this->simulationHiddenOrTime = 1;
360  }
361  $this->whereClause .= 'AND (starttime<=' . $GLOBALS['SIM_ACCESS_TIME'] . ') AND (endtime=0 OR endtime>' . $GLOBALS['SIM_ACCESS_TIME'] . ')';
362  // Sets the paths from where TypoScript resources are allowed to be used:
363  $this->allowedPaths = array(
364  'media/',
365  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'],
366  // fileadmin/ path
367  'uploads/',
368  'typo3temp/',
369  TYPO3_mainDir . 'ext/',
370  TYPO3_mainDir . 'sysext/',
371  TYPO3_mainDir . 'contrib/',
372  'typo3conf/ext/'
373  );
374  if ($GLOBALS['TYPO3_CONF_VARS']['FE']['addAllowedPaths']) {
375  $pathArr = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['addAllowedPaths'], TRUE);
376  foreach ($pathArr as $p) {
377  // Once checked for path, but as this may run from typo3/mod/web/ts/ dir, that'll not work!! So the paths ar uncritically included here.
378  $this->allowedPaths[] = $p;
379  }
380  }
381  }
382 
399  public function getCurrentPageData() {
400  return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_pagesection')->get((int)$GLOBALS['TSFE']->id . '_' . GeneralUtility::md5int($GLOBALS['TSFE']->MP));
401  }
402 
410  public function matching($cc) {
411  if (is_array($cc['all'])) {
413  $matchObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Configuration\\TypoScript\\ConditionMatching\\ConditionMatcher');
414  $matchObj->setRootline((array) $cc['rootLine']);
415  foreach ($cc['all'] as $key => $pre) {
416  if ($matchObj->match($pre)) {
417  $sectionsMatch[$key] = $pre;
418  }
419  }
420  $cc['match'] = $sectionsMatch;
421  }
422  return $cc;
423  }
424 
435  public function start($theRootLine) {
436  if (is_array($theRootLine)) {
437  $setupData = '';
438  $hash = '';
439  // Flag that indicates that the existing data in cache_pagesection
440  // could be used (this is the case if $TSFE->all is set, and the
441  // rowSum still matches). Based on this we decide if cache_pagesection
442  // needs to be updated...
443  $isCached = FALSE;
444  $this->runThroughTemplates($theRootLine);
445  if ($GLOBALS['TSFE']->all) {
446  $cc = $GLOBALS['TSFE']->all;
447  // The two rowSums must NOT be different from each other - which they will be if start/endtime or hidden has changed!
448  if (serialize($this->rowSum) !== serialize($cc['rowSum'])) {
449  unset($cc);
450  } else {
451  // If $TSFE->all contains valid data, we don't need to update cache_pagesection (because this data was fetched from there already)
452  if (serialize($this->rootLine) === serialize($cc['rootLine'])) {
453  $isCached = TRUE;
454  }
455  // When the data is serialized below (ROWSUM hash), it must not contain the rootline by concept. So this must be removed (and added again later)...
456  unset($cc['rootLine']);
457  }
458  }
459  // This is about getting the hash string which is used to fetch the cached TypoScript template.
460  // If there was some cached currentPageData ($cc) then that's good (it gives us the hash).
461  if (is_array($cc)) {
462  // If currentPageData was actually there, we match the result (if this wasn't done already in $TSFE->getFromCache()...)
463  if (!$cc['match']) {
464  // TODO: check if this can ever be the case - otherwise remove
465  $cc = $this->matching($cc);
466  ksort($cc);
467  }
468  $hash = md5(serialize($cc));
469  } else {
470  // If currentPageData was not there, we first find $rowSum (freshly generated). After that we try to see, if it is stored with a list of all conditions. If so we match the result.
471  $rowSumHash = md5('ROWSUM:' . serialize($this->rowSum));
473  if (is_array($result)) {
474  $cc = array();
475  $cc['all'] = $result;
476  $cc['rowSum'] = $this->rowSum;
477  $cc = $this->matching($cc);
478  ksort($cc);
479  $hash = md5(serialize($cc));
480  }
481  }
482  if ($hash) {
483  // Get TypoScript setup array
485  }
486  if (is_array($setupData) && !$this->forceTemplateParsing) {
487  // If TypoScript setup structure was cached we unserialize it here:
488  $this->setup = $setupData;
489  if ($this->tt_track) {
490  $GLOBALS['TT']->setTSLogMessage('Using cached TS template data');
491  }
492  } else {
493  if ($this->tt_track) {
494  $GLOBALS['TT']->setTSLogMessage('Not using any cached TS data');
495  }
496 
497  // Make configuration
498  $this->generateConfig();
499  // This stores the template hash thing
500  $cc = array();
501  // All sections in the template at this point is found
502  $cc['all'] = $this->sections;
503  // The line of templates is collected
504  $cc['rowSum'] = $this->rowSum;
505  $cc = $this->matching($cc);
506  ksort($cc);
507  $hash = md5(serialize($cc));
508  // This stores the data.
509  \TYPO3\CMS\Frontend\Page\PageRepository::storeHash($hash, $this->setup, 'TS_TEMPLATE');
510  if ($this->tt_track) {
511  $GLOBALS['TT']->setTSlogMessage('TS template size, serialized: ' . strlen(serialize($this->setup)) . ' bytes');
512  }
513  $rowSumHash = md5('ROWSUM:' . serialize($this->rowSum));
514  \TYPO3\CMS\Frontend\Page\PageRepository::storeHash($rowSumHash, $cc['all'], 'TMPL_CONDITIONS_ALL');
515  }
516  // Add rootLine
517  $cc['rootLine'] = $this->rootLine;
518  ksort($cc);
519  // Make global and save
520  $GLOBALS['TSFE']->all = $cc;
521  // Matching must be executed for every request, so this must never be part of the pagesection cache!
522  unset($cc['match']);
523  if (!$isCached && !$this->simulationHiddenOrTime && !$GLOBALS['TSFE']->no_cache) {
524  // Only save the data if we're not simulating by hidden/starttime/endtime
525  $mpvarHash = GeneralUtility::md5int($GLOBALS['TSFE']->MP);
527  $pageSectionCache = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_pagesection');
528  $pageSectionCache->set((int)$GLOBALS['TSFE']->id . '_' . $mpvarHash, $cc, array(
529  'pageId_' . (int)$GLOBALS['TSFE']->id,
530  'mpvarHash_' . $mpvarHash
531  ));
532  }
533  // If everything OK.
534  if ($this->rootId && $this->rootLine && $this->setup) {
535  $this->loaded = 1;
536  }
537  }
538  }
539 
540  /*******************************************************************
541  *
542  * Fetching TypoScript code text for the Template Hierarchy
543  *
544  *******************************************************************/
556  public function runThroughTemplates($theRootLine, $start_template_uid = 0) {
557  $this->constants = array();
558  $this->config = array();
559  $this->rowSum = array();
560  $this->hierarchyInfoToRoot = array();
561  $this->absoluteRootLine = $theRootLine;
562  $this->isDefaultTyposcriptAdded = FALSE;
563 
564  reset($this->absoluteRootLine);
565  $c = count($this->absoluteRootLine);
566  for ($a = 0; $a < $c; $a++) {
567  // If some template loaded before has set a template-id for the next level, then load this template first!
568  if ($this->nextLevel) {
569  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid=' . (int)$this->nextLevel . ' ' . $this->whereClause);
570  $this->nextLevel = 0;
571  if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
572  $this->versionOL($row);
573  if (is_array($row)) {
574  $this->processTemplate($row, 'sys_' . $row['uid'], $this->absoluteRootLine[$a]['uid'], 'sys_' . $row['uid']);
575  $this->outermostRootlineIndexWithTemplate = $a;
576  }
577  }
578  $GLOBALS['TYPO3_DB']->sql_free_result($res);
579  }
580  $addC = '';
581  // If first loop AND there is set an alternative template uid, use that
582  if ($a == $c - 1 && $start_template_uid) {
583  $addC = ' AND uid=' . (int)$start_template_uid;
584  }
585  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'pid=' . (int)$this->absoluteRootLine[$a]['uid'] . $addC . ' ' . $this->whereClause, '', 'sorting', 1);
586  if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
587  $this->versionOL($row);
588  if (is_array($row)) {
589  $this->processTemplate($row, 'sys_' . $row['uid'], $this->absoluteRootLine[$a]['uid'], 'sys_' . $row['uid']);
590  $this->outermostRootlineIndexWithTemplate = $a;
591  }
592  }
593  $GLOBALS['TYPO3_DB']->sql_free_result($res);
594  $this->rootLine[] = $this->absoluteRootLine[$a];
595  }
596 
597  // Process extension static files if not done yet, but explicitly requested
598  if (!$this->extensionStaticsProcessed && $this->processExtensionStatics) {
599  $this->addExtensionStatics('sys_0', 'sys_0', 0, array());
600  }
601 
602  // Add the global default TypoScript from the TYPO3_CONF_VARS
603  $this->addDefaultTypoScript();
604 
605  $this->processIncludes();
606  }
607 
622  public function processTemplate($row, $idList, $pid, $templateID = '', $templateParent = '', $includePath = '') {
623  // Adding basic template record information to rowSum array
624  $this->rowSum[] = array($row['uid'], $row['title'], $row['tstamp']);
625  // Processing "Clear"-flags
626  if ($row['clear']) {
627  $clConst = $row['clear'] & 1;
628  $clConf = $row['clear'] & 2;
629  if ($clConst) {
630  // Keep amount of items to stay in sync with $this->templateIncludePaths so processIncludes() does not break
631  foreach ($this->constants as &$constantConfiguration) {
632  $constantConfiguration = '';
633  }
634  unset($constantConfiguration);
635  $this->clearList_const = array();
636  }
637  if ($clConf) {
638  // Keep amount of items to stay in sync with $this->templateIncludePaths so processIncludes() does not break
639  foreach ($this->config as &$configConfiguration) {
640  $configConfiguration = '';
641  }
642  unset($configConfiguration);
643  $this->hierarchyInfoToRoot = array();
644  $this->clearList_setup = array();
645  }
646  }
647  // Include static records (static_template) or files (from extensions) (#1/2)
648  // NORMAL inclusion, The EXACT same code is found below the basedOn inclusion!!!
649  if (!$row['includeStaticAfterBasedOn']) {
650  $this->includeStaticTypoScriptSources($idList, $templateID, $pid, $row);
651  }
652  // Include "Based On" sys_templates:
653  // 'basedOn' is a list of templates to include
654  if (trim($row['basedOn'])) {
655  // Manually you can put this value in the field and then the based_on ID will be taken from the $_GET var defined by '=....'.
656  // Example: If $row['basedOn'] is 'EXTERNAL_BASED_ON_TEMPLATE_ID=based_on_uid', then the global var, based_on_uid - given by the URL like '&based_on_uid=999' - is included instead!
657  // This feature allows us a hack to test/demonstrate various included templates on the same set of content bearing pages. Used by the "freesite" extension.
658  $basedOn_hackFeature = explode('=', $row['basedOn']);
659  if ($basedOn_hackFeature[0] == 'EXTERNAL_BASED_ON_TEMPLATE_ID' && $basedOn_hackFeature[1]) {
660  $id = (int)GeneralUtility::_GET($basedOn_hackFeature[1]);
661  // If $id is not allready included ...
662  if ($id && !GeneralUtility::inList($idList, ('sys_' . $id))) {
663  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid=' . $id . ' ' . $this->whereClause);
664  // there was a template, then we fetch that
665  if ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
666  $this->versionOL($subrow);
667  if (is_array($subrow)) {
668  $this->processTemplate($subrow, $idList . ',sys_' . $id, $pid, 'sys_' . $id, $templateID);
669  }
670  }
671  $GLOBALS['TYPO3_DB']->sql_free_result($res);
672  }
673  } else {
674  // Normal Operation, which is to include the "based-on" sys_templates,
675  // if they are not already included, and maintaining the sorting of the templates
676  $basedOnIds = GeneralUtility::intExplode(',', $row['basedOn'], TRUE);
677  // skip template if it's already included
678  foreach ($basedOnIds as $key => $basedOnId) {
679  if (GeneralUtility::inList($idList, 'sys_' . $basedOnId)) {
680  unset($basedOnIds[$key]);
681  }
682  }
683  if (!empty($basedOnIds)) {
684  $subTemplates = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_template', 'uid IN (' . implode(',', $basedOnIds) . ') ' . $this->whereClause, '', '', '', 'uid');
685  // Traversing list again to ensure the sorting of the templates
686  foreach ($basedOnIds as $id) {
687  if (is_array($subTemplates[$id])) {
688  $this->versionOL($subTemplates[$id]);
689  $this->processTemplate($subTemplates[$id], $idList . ',sys_' . $id, $pid, 'sys_' . $id, $templateID);
690  }
691  }
692  }
693  }
694  }
695  // Include static records (static_template) or files (from extensions) (#2/2)
696  if ($row['includeStaticAfterBasedOn']) {
697  $this->includeStaticTypoScriptSources($idList, $templateID, $pid, $row);
698  }
699  // Creating hierarchy information; Used by backend analysis tools
700  $this->hierarchyInfo[] = ($this->hierarchyInfoToRoot[] = array(
701  'root' => trim($row['root']),
702  'next' => $row['nextLevel'],
703  'clConst' => $clConst,
704  'clConf' => $clConf,
705  'templateID' => $templateID,
706  'templateParent' => $templateParent,
707  'title' => $row['title'],
708  'uid' => $row['uid'],
709  'pid' => $row['pid'],
710  'configLines' => substr_count($row['config'], LF) + 1
711  ));
712  // Adding the content of the fields constants (Constants) and config (Setup)
713  $this->constants[] = $row['constants'];
714  $this->config[] = $row['config'];
715  $this->templateIncludePaths[] = $includePath;
716  // For backend analysis (Template Analyser) provide the order of added constants/config template IDs
717  $this->clearList_const[] = $templateID;
718  $this->clearList_setup[] = $templateID;
719  if (trim($row['sitetitle'])) {
720  $this->sitetitle = $row['sitetitle'];
721  }
722  // If the template record is a Rootlevel record, set the flag and clear the template rootLine (so it starts over from this point)
723  if (trim($row['root'])) {
724  $this->rootId = $pid;
725  $this->rootLine = array();
726  }
727  // If a template is set to be active on the next level set this internal value to point to this UID. (See runThroughTemplates())
728  if ($row['nextLevel']) {
729  $this->nextLevel = $row['nextLevel'];
730  } else {
731  $this->nextLevel = 0;
732  }
733  }
734 
746  public function updateRootlineData($fullRootLine) {
747  if (!is_array($this->rootLine) || count($this->rootLine) === 0) {
748  return;
749  }
750 
751  $fullRootLineByUid = array();
752  foreach ($fullRootLine as $rootLineData) {
753  $fullRootLineByUid[$rootLineData['uid']] = $rootLineData;
754  }
755 
756  foreach ($this->rootLine as $level => $dataArray) {
757  $currentUid = $dataArray['uid'];
758 
759  if (!array_key_exists($currentUid, $fullRootLineByUid)) {
760  throw new \RuntimeException(sprintf('The full rootLine does not contain data for the page with the uid %d that is contained in the template rootline.', $currentUid), 1370419654);
761  }
762 
763  $this->rootLine[$level] = $fullRootLineByUid[$currentUid];
764  }
765  }
766 
778  public function includeStaticTypoScriptSources($idList, $templateID, $pid, $row) {
779  // Static Template Records (static_template): include_static is a list of static templates to include
780  // Call function for link rendering:
781  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['includeStaticTypoScriptSources'])) {
782  $_params = array(
783  'idList' => &$idList,
784  'templateId' => &$templateID,
785  'pid' => &$pid,
786  'row' => &$row
787  );
788  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['includeStaticTypoScriptSources'] as $_funcRef) {
789  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
790  }
791  }
792  // If "Include before all static templates if root-flag is set" is set:
793  if ($row['static_file_mode'] == 3 && substr($templateID, 0, 4) == 'sys_' && $row['root']) {
794  $this->addExtensionStatics($idList, $templateID, $pid, $row);
795  }
796  // Static Template Files (Text files from extensions): include_static_file is a list of static files to include (from extensions)
797  if (trim($row['include_static_file'])) {
798  $include_static_fileArr = GeneralUtility::trimExplode(',', $row['include_static_file'], TRUE);
799  // Traversing list
800  foreach ($include_static_fileArr as $ISF_file) {
801  if (substr($ISF_file, 0, 4) == 'EXT:') {
802  list($ISF_extKey, $ISF_localPath) = explode('/', substr($ISF_file, 4), 2);
803  if ((string)$ISF_extKey !== '' && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($ISF_extKey) && (string)$ISF_localPath !== '') {
804  $ISF_localPath = rtrim($ISF_localPath, '/') . '/';
805  $ISF_filePath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($ISF_extKey) . $ISF_localPath;
806  if (@is_dir($ISF_filePath)) {
807  $mExtKey = str_replace('_', '', $ISF_extKey . '/' . $ISF_localPath);
808  $subrow = array(
809  'constants' => @file_exists(($ISF_filePath . 'constants.txt')) ? GeneralUtility::getUrl($ISF_filePath . 'constants.txt') : '',
810  'config' => @file_exists(($ISF_filePath . 'setup.txt')) ? GeneralUtility::getUrl($ISF_filePath . 'setup.txt') : '',
811  'include_static' => @file_exists(($ISF_filePath . 'include_static.txt')) ? implode(',', array_unique(GeneralUtility::intExplode(',', GeneralUtility::getUrl($ISF_filePath . 'include_static.txt')))) : '',
812  'include_static_file' => @file_exists(($ISF_filePath . 'include_static_file.txt')) ? implode(',', array_unique(explode(',', GeneralUtility::getUrl($ISF_filePath . 'include_static_file.txt')))) : '',
813  'title' => $ISF_file,
814  'uid' => $mExtKey
815  );
816  $subrow = $this->prependStaticExtra($subrow);
817  $this->processTemplate($subrow, $idList . ',ext_' . $mExtKey, $pid, 'ext_' . $mExtKey, $templateID, $ISF_filePath);
818  }
819  }
820  }
821  }
822  }
823  // If "Default (include before if root flag is set)" is set OR
824  // "Always include before this template record" AND root-flag are set
825  if ($row['static_file_mode'] == 1 || $row['static_file_mode'] == 0 && substr($templateID, 0, 4) == 'sys_' && $row['root']) {
826  $this->addExtensionStatics($idList, $templateID, $pid, $row);
827  }
828  // Include Static Template Records after all other TypoScript has been included.
829  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['includeStaticTypoScriptSourcesAtEnd'])) {
830  $_params = array(
831  'idList' => &$idList,
832  'templateId' => &$templateID,
833  'pid' => &$pid,
834  'row' => &$row
835  );
836  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['includeStaticTypoScriptSourcesAtEnd'] as $_funcRef) {
837  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
838  }
839  }
840  }
841 
854  public function addExtensionStatics($idList, $templateID, $pid, $row) {
855  $this->extensionStaticsProcessed = TRUE;
856 
857  // @TODO: Change to use new API
858  foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $extKey => $files) {
859  if ((is_array($files) || $files instanceof \ArrayAccess) && ($files['ext_typoscript_constants.txt'] || $files['ext_typoscript_setup.txt'])) {
860  $mExtKey = str_replace('_', '', $extKey);
861  $subrow = array(
862  'constants' => $files['ext_typoscript_constants.txt'] ? GeneralUtility::getUrl($files['ext_typoscript_constants.txt']) : '',
863  'config' => $files['ext_typoscript_setup.txt'] ? GeneralUtility::getUrl($files['ext_typoscript_setup.txt']) : '',
864  'title' => $extKey,
865  'uid' => $mExtKey
866  );
867  $subrow = $this->prependStaticExtra($subrow);
868  $extPath = ExtensionManagementUtility::extPath($extKey);
869  $this->processTemplate($subrow, $idList . ',ext_' . $mExtKey, $pid, 'ext_' . $mExtKey, $templateID, $extPath);
870  }
871  }
872  }
873 
885  public function prependStaticExtra($subrow) {
886  // the identifier can be "43" if coming from "static template" extension or a path like "cssstyledcontent/static/"
887  $identifier = $subrow['uid'];
888  $subrow['config'] .= $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup.'][$identifier];
889  $subrow['constants'] .= $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants.'][$identifier];
890  // if this is a template of type "default content rendering", also see if other extensions have added their TypoScript that should be included after the content definitions
891  if (in_array($identifier, $GLOBALS['TYPO3_CONF_VARS']['FE']['contentRenderingTemplates'], TRUE)) {
892  $subrow['config'] .= $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup.']['defaultContentRendering'];
893  $subrow['constants'] .= $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants.']['defaultContentRendering'];
894  }
895  return $subrow;
896  }
897 
906  public function versionOL(&$row) {
907  // Distinguish frontend and backend call:
908  // To do the fronted call a full frontend is required, just checking for
909  // TYPO3_MODE === 'FE' is not enough. This could otherwise lead to fatals in
910  // eId scripts that run in frontend scope, but do not have a full blown frontend.
911  if (is_object($GLOBALS['TSFE']) === TRUE && property_exists($GLOBALS['TSFE'], 'sys_page') === TRUE && method_exists($GLOBALS['TSFE']->sys_page, 'versionOL') === TRUE) {
912  // Frontend
913  $GLOBALS['TSFE']->sys_page->versionOL('sys_template', $row);
914  } else {
915  // Backend
917  }
918  }
919 
920  /*******************************************************************
921  *
922  * Parsing TypoScript code text from Template Records into PHP array
923  *
924  *******************************************************************/
933  public function generateConfig() {
934  // Add default TS for all code types
935  $this->addDefaultTypoScript();
936 
937  // Parse the TypoScript code text for include-instructions!
938  $this->processIncludes();
939  // These vars are also set lateron...
940  $this->setup['sitetitle'] = $this->sitetitle;
941  // ****************************
942  // Parse TypoScript Constants
943  // ****************************
944  // Initialize parser and match-condition classes:
946  $constants = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
947  $constants->breakPointLN = (int)$this->ext_constants_BRP;
948  $constants->setup = $this->const;
949  $constants->setup = $this->mergeConstantsFromPageTSconfig($constants->setup);
951  $matchObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Configuration\\TypoScript\\ConditionMatching\\ConditionMatcher');
952  $matchObj->setSimulateMatchConditions($this->matchAlternative);
953  $matchObj->setSimulateMatchResult((bool) $this->matchAll);
954  // Traverse constants text fields and parse them
955  foreach ($this->constants as $str) {
956  $constants->parse($str, $matchObj);
957  }
958  // Read out parse errors if any
959  $this->parserErrors['constants'] = $constants->errors;
960  // Then flatten the structure from a multi-dim array to a single dim array with all constants listed as key/value pairs (ready for substitution)
961  $this->flatSetup = array();
962  $this->flattenSetup($constants->setup, '', '');
963  // ***********************************************
964  // Parse TypoScript Setup (here called "config")
965  // ***********************************************
966  // Initialize parser and match-condition classes:
968  $config = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
969  $config->breakPointLN = (int)$this->ext_config_BRP;
970  $config->regLinenumbers = $this->ext_regLinenumbers;
971  $config->regComments = $this->ext_regComments;
972  $config->setup = $this->setup;
973  // Transfer information about conditions found in "Constants" and which of them returned TRUE.
974  $config->sections = $constants->sections;
975  $config->sectionsMatch = $constants->sectionsMatch;
976  // Traverse setup text fields and concatenate them into one, single string separated by a [GLOBAL] condition
977  $all = '';
978  foreach ($this->config as $str) {
979  $all .= '
980 [GLOBAL]
981 ' . $str;
982  }
983  // Substitute constants in the Setup code:
984  if ($this->tt_track) {
985  $GLOBALS['TT']->push('Substitute Constants (' . count($this->flatSetup) . ')');
986  }
987  $all = $this->substituteConstants($all);
988  if ($this->tt_track) {
989  $GLOBALS['TT']->pull();
990  }
991  // Searching for possible unsubstituted constants left (only for information)
992  if (strstr($all, '{$')) {
993  $theConstList = array();
994  $findConst = explode('{$', $all);
995  array_shift($findConst);
996  foreach ($findConst as $constVal) {
997  $constLen = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(strcspn($constVal, '}'), 0, 50);
998  $theConstList[] = '{$' . substr($constVal, 0, ($constLen + 1));
999  }
1000  if ($this->tt_track) {
1001  $GLOBALS['TT']->setTSlogMessage(implode(', ', $theConstList) . ': Constants may remain un-substituted!!', 2);
1002  }
1003  }
1004  // Logging the textual size of the TypoScript Setup field text with all constants substituted:
1005  if ($this->tt_track) {
1006  $GLOBALS['TT']->setTSlogMessage('TypoScript template size as textfile: ' . strlen($all) . ' bytes');
1007  }
1008  // Finally parse the Setup field TypoScript code (where constants are now substituted)
1009  $config->parse($all, $matchObj);
1010  // Read out parse errors if any
1011  $this->parserErrors['config'] = $config->errors;
1012  // Transfer the TypoScript array from the parser object to the internal $this->setup array:
1013  $this->setup = $config->setup;
1014  if ($this->backend_info) {
1015  // Used for backend purposes only
1016  $this->setup_constants = $constants->setup;
1017  }
1018  // ****************************************************************
1019  // Final processing of the $this->setup TypoScript Template array
1020  // Basically: This is unsetting/setting of certain reserved keys.
1021  // ****************************************************************
1022  // These vars are allready set after 'processTemplate', but because $config->setup overrides them (in the line above!), we set them again. They are not changed compared to the value they had in the top of the page!
1023  unset($this->setup['sitetitle']);
1024  unset($this->setup['sitetitle.']);
1025  $this->setup['sitetitle'] = $this->sitetitle;
1026  // Unsetting some vars...
1027  unset($this->setup['types.']);
1028  unset($this->setup['types']);
1029  if (is_array($this->setup)) {
1030  foreach ($this->setup as $key => $value) {
1031  if ($value == 'PAGE') {
1032  // Set the typeNum of the current page object:
1033  if (isset($this->setup[$key . '.']['typeNum'])) {
1034  $typeNum = $this->setup[$key . '.']['typeNum'];
1035  $this->setup['types.'][$typeNum] = $key;
1036  } elseif (!isset($this->setup['types.'][0]) || !$this->setup['types.'][0]) {
1037  $this->setup['types.'][0] = $key;
1038  }
1039  }
1040  }
1041  }
1042  unset($this->setup['styles.']);
1043  unset($this->setup['temp.']);
1044  unset($constants);
1045  // Storing the conditions found/matched information:
1046  $this->sections = $config->sections;
1047  $this->sectionsMatch = $config->sectionsMatch;
1048  }
1049 
1058  public function processIncludes() {
1059  if ($this->processIncludesHasBeenRun) {
1060  return;
1061  }
1062 
1063  $paths = $this->templateIncludePaths;
1064  $files = array();
1065  foreach ($this->constants as &$value) {
1066  $includeData = \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::checkIncludeLines($value, 1, TRUE, array_shift($paths));
1067  $files = array_merge($files, $includeData['files']);
1068  $value = $includeData['typoscript'];
1069  }
1070  unset($value);
1071  $paths = $this->templateIncludePaths;
1072  foreach ($this->config as &$value) {
1073  $includeData = \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::checkIncludeLines($value, 1, TRUE, array_shift($paths));
1074  $files = array_merge($files, $includeData['files']);
1075  $value = $includeData['typoscript'];
1076  }
1077  unset($value);
1078 
1079  if (!empty($files)) {
1080  $files = array_unique($files);
1081  foreach ($files as $file) {
1082  $this->rowSum[] = array($file, filemtime($file));
1083  }
1084  }
1085 
1086  $this->processIncludesHasBeenRun = TRUE;
1087  }
1088 
1097  public function mergeConstantsFromPageTSconfig($constArray) {
1098  $TSdataArray = array();
1099  // Setting default configuration:
1100  $TSdataArray[] = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'];
1101  for ($a = 0; $a <= $this->outermostRootlineIndexWithTemplate; $a++) {
1102  $TSdataArray[] = $this->absoluteRootLine[$a]['TSconfig'];
1103  }
1104  // Parsing the user TS (or getting from cache)
1106  $userTS = implode(LF . '[GLOBAL]' . LF, $TSdataArray);
1108  $parseObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
1109  $parseObj->parse($userTS);
1110  if (is_array($parseObj->setup['TSFE.']['constants.'])) {
1111  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($constArray, $parseObj->setup['TSFE.']['constants.']);
1112  }
1113  return $constArray;
1114  }
1115 
1126  public function flattenSetup($setupArray, $prefix, $resourceFlag) {
1127  if (is_array($setupArray)) {
1128  foreach ($setupArray as $key => $val) {
1129  if ($prefix || substr($key, 0, 16) != 'TSConstantEditor') {
1130  // We don't want 'TSConstantEditor' in the flattend setup on the first level (190201)
1131  if (is_array($val)) {
1132  $this->flattenSetup($val, $prefix . $key, $key == 'file.');
1133  } elseif ($resourceFlag) {
1134  $this->flatSetup[$prefix . $key] = $this->getFileName($val);
1135  } else {
1136  $this->flatSetup[$prefix . $key] = $val;
1137  }
1138  }
1139  }
1140  }
1141  }
1142 
1151  public function substituteConstants($all) {
1152  if ($this->tt_track) {
1153  $GLOBALS['TT']->setTSlogMessage('Constants to substitute: ' . count($this->flatSetup));
1154  }
1155  $noChange = FALSE;
1156  // Recursive substitution of constants (up to 10 nested levels)
1157  for ($i = 0; $i < 10 && !$noChange; $i++) {
1158  $old_all = $all;
1159  $all = preg_replace_callback('/\\{\\$(.[^}]*)\\}/', array($this, 'substituteConstantsCallBack'), $all);
1160  if ($old_all == $all) {
1161  $noChange = TRUE;
1162  }
1163  }
1164  return $all;
1165  }
1166 
1175  public function substituteConstantsCallBack($matches) {
1176  // Replace {$CONST} if found in $this->flatSetup, else leave unchanged
1177  return isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? $this->flatSetup[$matches[1]] : $matches[0];
1178  }
1179 
1180  /*******************************************************************
1181  *
1182  * Various API functions, used from elsewhere in the frontend classes
1183  *
1184  *******************************************************************/
1196  public function splitConfArray($conf, $splitCount) {
1197  // Initialize variables:
1198  $splitCount = (int)$splitCount;
1199  $conf2 = array();
1200  if ($splitCount && is_array($conf)) {
1201  // Initialize output to carry at least the keys:
1202  for ($aKey = 0; $aKey < $splitCount; $aKey++) {
1203  $conf2[$aKey] = array();
1204  }
1205  // Recursive processing of array keys:
1206  foreach ($conf as $cKey => $val) {
1207  if (is_array($val)) {
1208  $tempConf = $this->splitConfArray($val, $splitCount);
1209  foreach ($tempConf as $aKey => $val) {
1210  $conf2[$aKey][$cKey] = $val;
1211  }
1212  } else {
1213  // Splitting of all values on this level of the TypoScript object tree:
1214  if ($cKey === 'noTrimWrap' || (!strstr($val, '|*|') && !strstr($val, '||'))) {
1215  for ($aKey = 0; $aKey < $splitCount; $aKey++) {
1216  $conf2[$aKey][$cKey] = $val;
1217  }
1218  } else {
1219  $main = explode('|*|', $val);
1220  $mainCount = count($main);
1221  $lastC = 0;
1222  $middleC = 0;
1223  $firstC = 0;
1224  if ($main[0]) {
1225  $first = explode('||', $main[0]);
1226  $firstC = count($first);
1227  }
1228  if ($main[1]) {
1229  $middle = explode('||', $main[1]);
1230  $middleC = count($middle);
1231  }
1232  if ($main[2]) {
1233  $last = explode('||', $main[2]);
1234  $lastC = count($last);
1235  $value = $last[0];
1236  }
1237  for ($aKey = 0; $aKey < $splitCount; $aKey++) {
1238  if ($firstC && isset($first[$aKey])) {
1239  $value = $first[$aKey];
1240  } elseif ($middleC) {
1241  $value = $middle[($aKey - $firstC) % $middleC];
1242  }
1243  if ($lastC && $lastC >= $splitCount - $aKey) {
1244  $value = $last[$lastC - ($splitCount - $aKey)];
1245  }
1246  $conf2[$aKey][$cKey] = trim($value);
1247  }
1248  }
1249  }
1250  }
1251  }
1252  return $conf2;
1253  }
1254 
1263  public function getFileName($fileFromSetup) {
1264  $file = trim($fileFromSetup);
1265  if (!$file) {
1266  return;
1267  } elseif (strstr($file, '../')) {
1268  if ($this->tt_track) {
1269  $GLOBALS['TT']->setTSlogMessage('File path "' . $file . '" contained illegal string "../"!', 3);
1270  }
1271  return;
1272  }
1273  // Cache
1274  $hash = md5($file);
1275  if (isset($this->fileCache[$hash])) {
1276  return $this->fileCache[$hash];
1277  }
1278  if (substr($file, 0, 4) === 'EXT:') {
1279  $newFile = '';
1280  list($extKey, $script) = explode('/', substr($file, 4), 2);
1281  if ($extKey && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extKey)) {
1283  $newFile = \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($extPath) . $script;
1284  }
1285  if (!@file_exists((PATH_site . $newFile))) {
1286  if ($this->tt_track) {
1287  $GLOBALS['TT']->setTSlogMessage('Extension media file "' . $newFile . '" was not found!', 3);
1288  }
1289  return;
1290  } else {
1291  $file = $newFile;
1292  }
1293  }
1294  // if this is an URL, it can be returned directly
1295  $urlScheme = parse_url($file, PHP_URL_SCHEME);
1296  if ($urlScheme === 'https' || $urlScheme === 'http' || is_file(PATH_site . $file)) {
1297  return $file;
1298  }
1299  // Find
1300  if (strpos($file, '/') !== FALSE) {
1301  // If the file is in the media/ folder but it doesn't exist,
1302  // it is assumed that it's in the tslib folder
1303  if (GeneralUtility::isFirstPartOfStr($file, 'media/') && !file_exists(($this->getFileName_backPath . $file))) {
1304  $file = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('cms') . 'tslib/' . $file;
1305  }
1306  if (file_exists($this->getFileName_backPath . $file)) {
1307  $outFile = $file;
1308  $fileInfo = GeneralUtility::split_fileref($outFile);
1309  $OK = 0;
1310  foreach ($this->allowedPaths as $val) {
1311  if (substr($fileInfo['path'], 0, strlen($val)) == $val) {
1312  $OK = 1;
1313  break;
1314  }
1315  }
1316  if ($OK) {
1317  $this->fileCache[$hash] = $outFile;
1318  return $outFile;
1319  } elseif ($this->tt_track) {
1320  $GLOBALS['TT']->setTSlogMessage('"' . $file . '" was not located in the allowed paths: (' . implode(',', $this->allowedPaths) . ')', 3);
1321  }
1322  } elseif ($this->tt_track) {
1323  $GLOBALS['TT']->setTSlogMessage('"' . $this->getFileName_backPath . $file . '" is not a file (non-uploads/.. resource, did not exist).', 3);
1324  }
1325  }
1326  }
1327 
1338  public function printTitle($pageTitle, $noTitle = FALSE, $showTitleFirst = FALSE) {
1339  $siteTitle = trim($this->setup['sitetitle']);
1340  $pageTitle = $noTitle ? '' : $pageTitle;
1341  $pageTitleSeparator = '';
1342  if ($showTitleFirst) {
1343  $temp = $siteTitle;
1344  $siteTitle = $pageTitle;
1345  $pageTitle = $temp;
1346  }
1347  if ($pageTitle != '' && $siteTitle != '') {
1348  $pageTitleSeparator = ': ';
1349  if (isset($this->setup['config.']['pageTitleSeparator']) && $this->setup['config.']['pageTitleSeparator']) {
1350  $pageTitleSeparator = $this->setup['config.']['pageTitleSeparator'];
1351 
1352  if (is_object($GLOBALS['TSFE']->cObj) && isset($this->setup['config.']['pageTitleSeparator.']) && is_array($this->setup['config.']['pageTitleSeparator.'])) {
1353  $pageTitleSeparator = $GLOBALS['TSFE']->cObj->stdWrap($pageTitleSeparator, $this->setup['config.']['pageTitleSeparator.']);
1354  } else {
1355  $pageTitleSeparator .= ' ';
1356  }
1357  }
1358  }
1359  return $siteTitle . $pageTitleSeparator . $pageTitle;
1360  }
1361 
1371  public function fileContent($fName) {
1372  $incFile = $this->getFileName($fName);
1373  if ($incFile) {
1374  return @file_get_contents($incFile);
1375  }
1376  }
1377 
1387  public function wrap($content, $wrap) {
1388  if ($wrap) {
1389  $wrapArr = explode('|', $wrap);
1390  return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
1391  } else {
1392  return $content;
1393  }
1394  }
1395 
1404  public function removeQueryString($url) {
1405  if (substr($url, -1) == '?') {
1406  return substr($url, 0, -1);
1407  } else {
1408  return $url;
1409  }
1410  }
1411 
1421  static public function sortedKeyList($setupArr, $acceptOnlyProperties = FALSE) {
1422  $keyArr = array();
1423  $setupArrKeys = array_keys($setupArr);
1424  foreach ($setupArrKeys as $key) {
1425  if ($acceptOnlyProperties || \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($key)) {
1426  $keyArr[] = (int)$key;
1427  }
1428  }
1429  $keyArr = array_unique($keyArr);
1430  sort($keyArr);
1431  return $keyArr;
1432  }
1433 
1441  public function getRootlineLevel($list) {
1442  $idx = 0;
1443  foreach ($this->rootLine as $page) {
1444  if (GeneralUtility::inList($list, $page['uid'])) {
1445  return $idx;
1446  }
1447  $idx++;
1448  }
1449  return FALSE;
1450  }
1451 
1452  /*******************************************************************
1453  *
1454  * Functions for creating links
1455  *
1456  *******************************************************************/
1475  public function linkData($page, $oTarget, $no_cache, $script, $overrideArray = NULL, $addParams = '', $typeOverride = '', $targetDomain = '') {
1476  $LD = array();
1477  // Overriding some fields in the page record and still preserves the values by adding them as parameters. Little strange function.
1478  if (is_array($overrideArray)) {
1479  foreach ($overrideArray as $theKey => $theNewVal) {
1480  $addParams .= '&real_' . $theKey . '=' . rawurlencode($page[$theKey]);
1481  $page[$theKey] = $theNewVal;
1482  }
1483  }
1484  // Adding Mount Points, "&MP=", parameter for the current page if any is set:
1485  if (!strstr($addParams, '&MP=')) {
1486  // Looking for hardcoded defaults:
1487  if (trim($GLOBALS['TSFE']->MP_defaults[$page['uid']])) {
1488  $addParams .= '&MP=' . rawurlencode(trim($GLOBALS['TSFE']->MP_defaults[$page['uid']]));
1489  } elseif ($GLOBALS['TSFE']->config['config']['MP_mapRootPoints']) {
1490  // Else look in automatically created map:
1491  $m = $this->getFromMPmap($page['uid']);
1492  if ($m) {
1493  $addParams .= '&MP=' . rawurlencode($m);
1494  }
1495  }
1496  }
1497  // Setting ID/alias:
1498  if (!$script) {
1499  $script = $GLOBALS['TSFE']->config['mainScript'];
1500  }
1501  if ($page['alias']) {
1502  $LD['url'] = $script . '?id=' . rawurlencode($page['alias']);
1503  } else {
1504  $LD['url'] = $script . '?id=' . $page['uid'];
1505  }
1506  // Setting target
1507  $LD['target'] = trim($page['target']) ?: $oTarget;
1508  // typeNum
1509  $typeNum = $this->setup[$LD['target'] . '.']['typeNum'];
1510  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($typeOverride) && (int)$GLOBALS['TSFE']->config['config']['forceTypeValue']) {
1511  $typeOverride = (int)$GLOBALS['TSFE']->config['config']['forceTypeValue'];
1512  }
1513  if ((string)$typeOverride !== '') {
1514  $typeNum = $typeOverride;
1515  }
1516  // Override...
1517  if ($typeNum) {
1518  $LD['type'] = '&type=' . (int)$typeNum;
1519  } else {
1520  $LD['type'] = '';
1521  }
1522  // Preserving the type number.
1523  $LD['orig_type'] = $LD['type'];
1524  // noCache
1525  $LD['no_cache'] = trim($page['no_cache']) || $no_cache ? '&no_cache=1' : '';
1526  // linkVars
1527  if ($GLOBALS['TSFE']->config['config']['uniqueLinkVars']) {
1528  if ($addParams) {
1529  $LD['linkVars'] = GeneralUtility::implodeArrayForUrl('', GeneralUtility::explodeUrl2Array($GLOBALS['TSFE']->linkVars . $addParams), '', FALSE, TRUE);
1530  } else {
1531  $LD['linkVars'] = $GLOBALS['TSFE']->linkVars;
1532  }
1533  } else {
1534  $LD['linkVars'] = $GLOBALS['TSFE']->linkVars . $addParams;
1535  }
1536  // Add absRefPrefix if exists.
1537  $LD['url'] = $GLOBALS['TSFE']->absRefPrefix . $LD['url'];
1538  // If the special key 'sectionIndex_uid' (added 'manually' in tslib/menu.php to the page-record) is set, then the link jumps directly to a section on the page.
1539  $LD['sectionIndex'] = $page['sectionIndex_uid'] ? '#c' . $page['sectionIndex_uid'] : '';
1540  // Compile the normal total url
1541  $LD['totalURL'] = $this->removeQueryString(($LD['url'] . $LD['type'] . $LD['no_cache'] . $LD['linkVars'] . $GLOBALS['TSFE']->getMethodUrlIdToken)) . $LD['sectionIndex'];
1542  // Call post processing function for link rendering:
1543  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc'])) {
1544  $_params = array(
1545  'LD' => &$LD,
1546  'args' => array('page' => $page, 'oTarget' => $oTarget, 'no_cache' => $no_cache, 'script' => $script, 'overrideArray' => $overrideArray, 'addParams' => $addParams, 'typeOverride' => $typeOverride, 'targetDomain' => $targetDomain),
1547  'typeNum' => $typeNum
1548  );
1549  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc'] as $_funcRef) {
1550  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1551  }
1552  }
1553  // Return the LD-array
1554  return $LD;
1555  }
1556 
1567  public function getFromMPmap($pageId = 0) {
1568  // Create map if not found already:
1569  if (!is_array($this->MPmap)) {
1570  $this->MPmap = array();
1571  $rootPoints = GeneralUtility::trimExplode(',', strtolower($GLOBALS['TSFE']->config['config']['MP_mapRootPoints']), TRUE);
1572  // Traverse rootpoints:
1573  foreach ($rootPoints as $p) {
1574  if ($p == 'root') {
1575  $p = $this->rootLine[0]['uid'];
1576  $initMParray = array();
1577  if ($this->rootLine[0]['_MOUNT_OL'] && $this->rootLine[0]['_MP_PARAM']) {
1578  $initMParray[] = $this->rootLine[0]['_MP_PARAM'];
1579  }
1580  }
1581  $this->initMPmap_create($p, $initMParray);
1582  }
1583  }
1584  // Finding MP var for Page ID:
1585  if ($pageId) {
1586  if (is_array($this->MPmap[$pageId]) && count($this->MPmap[$pageId])) {
1587  return implode(',', $this->MPmap[$pageId]);
1588  }
1589  }
1590  }
1591 
1602  public function initMPmap_create($id, $MP_array = array(), $level = 0) {
1603  $id = (int)$id;
1604  if ($id <= 0) {
1605  return;
1606  }
1607  // First level, check id
1608  if (!$level) {
1609  // Find mount point if any:
1610  $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($id);
1611  // Overlay mode:
1612  if (is_array($mount_info) && $mount_info['overlay']) {
1613  $MP_array[] = $mount_info['MPvar'];
1614  $id = $mount_info['mount_pid'];
1615  }
1616  // Set mapping information for this level:
1617  $this->MPmap[$id] = $MP_array;
1618  // Normal mode:
1619  if (is_array($mount_info) && !$mount_info['overlay']) {
1620  $MP_array[] = $mount_info['MPvar'];
1621  $id = $mount_info['mount_pid'];
1622  }
1623  }
1624  if ($id && $level < 20) {
1625  $nextLevelAcc = array();
1626  // Select and traverse current level pages:
1627  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,pid,doktype,mount_pid,mount_pid_ol', 'pages', 'pid=' . (int)$id . ' AND deleted=0 AND doktype<>' . \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_RECYCLER . ' AND doktype<>' . \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_BE_USER_SECTION);
1628  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1629  // Find mount point if any:
1630  $next_id = $row['uid'];
1631  $next_MP_array = $MP_array;
1632  $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($next_id, $row);
1633  // Overlay mode:
1634  if (is_array($mount_info) && $mount_info['overlay']) {
1635  $next_MP_array[] = $mount_info['MPvar'];
1636  $next_id = $mount_info['mount_pid'];
1637  }
1638  if (!isset($this->MPmap[$next_id])) {
1639  // Set mapping information for this level:
1640  $this->MPmap[$next_id] = $next_MP_array;
1641  // Normal mode:
1642  if (is_array($mount_info) && !$mount_info['overlay']) {
1643  $next_MP_array[] = $mount_info['MPvar'];
1644  $next_id = $mount_info['mount_pid'];
1645  }
1646  // Register recursive call
1647  // (have to do it this way since ALL of the current level should be registered BEFORE the sublevel at any time)
1648  $nextLevelAcc[] = array($next_id, $next_MP_array);
1649  }
1650  }
1651  $GLOBALS['TYPO3_DB']->sql_free_result($res);
1652  // Call recursively, if any:
1653  foreach ($nextLevelAcc as $pSet) {
1654  $this->initMPmap_create($pSet[0], $pSet[1], $level + 1);
1655  }
1656  }
1657  }
1658 
1667  protected function addDefaultTypoScript() {
1668  // Add default TS for all code types, if not done already
1669  if (!$this->isDefaultTypoScriptAdded) {
1670  // adding default setup and constants
1671  // defaultTypoScript_setup is *very* unlikely to be empty
1672  // the count of elements in ->constants, ->config and ->templateIncludePaths have to be in sync
1673  array_unshift($this->constants, (string)$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants']);
1674  array_unshift($this->config, (string)$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup']);
1675  array_unshift($this->templateIncludePaths, '');
1676  // prepare a proper entry to hierachyInfo (used by TemplateAnalyzer in BE)
1677  $rootTemplateId = $this->hierarchyInfo[count($this->hierarchyInfo)-1]['templateID'];
1678  $defaultTemplateInfo = array(
1679  'root' => '',
1680  'next' => '',
1681  'clConst' => '',
1682  'clConf' => '',
1683  'templateID' => '_defaultTypoScript_',
1684  'templateParent' => $rootTemplateId,
1685  'title' => 'SYS:TYPO3_CONF_VARS:FE:defaultTypoScript',
1686  'uid' => '_defaultTypoScript_',
1687  'pid' => '',
1688  'configLines' => substr_count((string)$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'], LF) + 1
1689  );
1690  // push info to information arrays used in BE by TemplateTools (Analyzer)
1691  array_unshift($this->clearList_const, $defaultTemplateInfo['uid']);
1692  array_unshift($this->clearList_setup, $defaultTemplateInfo['uid']);
1693  array_unshift($this->hierarchyInfo, $defaultTemplateInfo);
1694  $this->isDefaultTypoScriptAdded = TRUE;
1695  }
1696  }
1697 
1698 }
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
printTitle($pageTitle, $noTitle=FALSE, $showTitleFirst=FALSE)
linkData($page, $oTarget, $no_cache, $script, $overrideArray=NULL, $addParams='', $typeOverride='', $targetDomain='')
static explodeUrl2Array($string, $multidim=FALSE)
static isFirstPartOfStr($str, $partStr)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:32
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=FALSE)
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
runThroughTemplates($theRootLine, $start_template_uid=0)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
includeStaticTypoScriptSources($idList, $templateID, $pid, $row)
static checkIncludeLines($string, $cycle_counter=1, $returnFiles=FALSE, $parentFilenameOrPath='')
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
processTemplate($row, $idList, $pid, $templateID='', $templateParent='', $includePath='')
static split_fileref($fileNameWithPath)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static getUrl($url, $includeHeader=0, $requestHeaders=FALSE, &$report=NULL)
static storeHash($hash, $data, $ident, $lifetime=0)
setProcessExtensionStatics($processExtensionStatics)
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
addExtensionStatics($idList, $templateID, $pid, $row)
initMPmap_create($id, $MP_array=array(), $level=0)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
flattenSetup($setupArray, $prefix, $resourceFlag)
static sortedKeyList($setupArr, $acceptOnlyProperties=FALSE)