2 namespace TYPO3\CMS\Core\TypoScript
;
5 * This file is part of the TYPO3 CMS project.
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Backend\Template\DocumentTemplate
;
18 use TYPO3\CMS\Backend\Utility\BackendUtility
;
19 use TYPO3\CMS\Core\Database\ConnectionPool
;
20 use TYPO3\CMS\Core\Database\Query\QueryBuilder
;
21 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
;
22 use TYPO3\CMS\Core\Exception
;
23 use TYPO3\CMS\Core\Imaging\Icon
;
24 use TYPO3\CMS\Core\Imaging\IconFactory
;
25 use TYPO3\CMS\Core\Utility\GeneralUtility
;
26 use TYPO3\CMS\Core\Utility\MathUtility
;
27 use TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher
;
28 use TYPO3\CMS\Lang\LanguageService
;
31 * TSParser extension class to TemplateService
32 * Contains functions for the TS module in TYPO3 backend
34 class ExtendedTemplateService
extends TemplateService
37 * This string is used to indicate the point in a template from where the editable constants are listed.
38 * Any vars before this point (if it exists though) is regarded as default values.
42 public $edit_divider = '###MOD_TS:EDITABLE_CONSTANTS###';
45 * Disabled in backend context
49 public $tt_track = false
;
54 public $categories = [
56 // Constants of superior importance for the template-layout. This is dimensions, imagefiles and enabling of various features. The most basic constants, which you would almost always want to configure.
58 // Menu setup. This includes fontfiles, sizes, background images. Depending on the menutype.
60 // All constants related to the display of pagecontent elements
62 // General configuration like metatags, link targets
64 // Advanced functions, which are used very seldom.
69 * Translated categories
73 protected $categoryLabels = [];
76 * This will be filled with the available categories of the current template.
80 public $subCategories = [
81 // Standard categories:
82 'enable' => ['Enable features', 'a'],
83 'dims' => ['Dimensions, widths, heights, pixels', 'b'],
84 'file' => ['Files', 'c'],
85 'typo' => ['Typography', 'd'],
86 'color' => ['Colors', 'e'],
87 'links' => ['Links and targets', 'f'],
88 'language' => ['Language specific constants', 'g'],
89 // subcategories based on the default content elements
90 'cheader' => ['Content: \'Header\'', 'ma'],
91 'cheader_g' => ['Content: \'Header\', Graphical', 'ma'],
92 'ctext' => ['Content: \'Text\'', 'mb'],
93 'cimage' => ['Content: \'Image\'', 'md'],
94 'ctextmedia' => ['Content: \'Textmedia\'', 'ml'],
95 'cbullets' => ['Content: \'Bullet list\'', 'me'],
96 'ctable' => ['Content: \'Table\'', 'mf'],
97 'cuploads' => ['Content: \'Filelinks\'', 'mg'],
98 'cmultimedia' => ['Content: \'Multimedia\'', 'mh'],
99 'cmedia' => ['Content: \'Media\'', 'mr'],
100 'cmailform' => ['Content: \'Form\'', 'mi'],
101 'csearch' => ['Content: \'Search\'', 'mj'],
102 'clogin' => ['Content: \'Login\'', 'mk'],
103 'cmenu' => ['Content: \'Menu/Sitemap\'', 'mm'],
104 'cshortcut' => ['Content: \'Insert records\'', 'mn'],
105 'clist' => ['Content: \'List of records\'', 'mo'],
106 'chtml' => ['Content: \'HTML\'', 'mq']
114 public $ext_inBrace = 0;
121 public $tsbrowser_searchKeys = [];
126 public $tsbrowser_depthKeys = [];
131 public $constantMode = '';
136 public $regexMode = '';
141 public $fixedLgd = '';
146 public $ext_lineNumberOffset = 0;
151 public $ext_expandAllNotes = 0;
156 public $ext_noPMicons = 0;
161 public $ext_listOfTemplatesArr = [];
166 public $ext_lineNumberOffset_mode = '';
173 public $ext_dontCheckIssetValues = 0;
178 public $ext_printAll = 0;
183 public $ext_CEformName = 'forms[0]';
188 public $doNotSortCategoriesBeforeMakingForm = false
;
195 public $templateTitles = [];
200 protected $lnToScript = null
;
205 public $clearList_const_temp;
210 public $clearList_setup_temp;
220 public $linkObjects = false
;
225 public $helpConfig = [];
230 public $changed = false
;
235 protected $objReg = [];
250 public $lastComment = '';
255 protected $inlineJavaScript = [];
258 * Gets the inline JavaScript.
262 public function getInlineJavaScript()
264 return $this->inlineJavaScript
;
268 * Substitute constant
273 public function substituteConstants($all)
275 return preg_replace_callback('/\\{\\$(.[^}]+)\\}/', [$this, 'substituteConstantsCallBack'], $all);
279 * Call back method for preg_replace_callback in substituteConstants
281 * @param array $matches Regular expression matches
282 * @return string Replacement
283 * @see substituteConstants()
285 public function substituteConstantsCallBack($matches)
287 $marker = substr(md5($matches[0]), 0, 6);
288 switch ($this->constantMode
) {
290 $ret_val = isset($this->flatSetup
[$matches[1]]) && !is_array($this->flatSetup
[$matches[1]]) ?
'##' . $marker . '_B##' . $matches[0] . '##' . $marker . '_E##' : $matches[0];
293 $ret_val = isset($this->flatSetup
[$matches[1]]) && !is_array($this->flatSetup
[$matches[1]]) ?
'##' . $marker . '_B##' . $this->flatSetup
[$matches[1]] . '##' . $marker . '_E##' : $matches[0];
296 $ret_val = $matches[0];
299 $ret_val = isset($this->flatSetup
[$matches[1]]) && !is_array($this->flatSetup
[$matches[1]]) ?
$this->flatSetup
[$matches[1]] : $matches[0];
310 public function substituteCMarkers($all)
312 switch ($this->constantMode
) {
316 '/##[a-z0-9]{6}_B##((?:(?!##[a-z0-9]{6}_E##).)+)?##[a-z0-9]{6}_E##/',
317 '<strong style="color: green;">$1</strong>',
327 * Parse constants with respect to the constant-editor in this module.
328 * In particular comments in the code are registered and the edit_divider is taken into account.
332 public function generateConfig_constants()
334 // These vars are also set lateron...
335 $this->setup
['sitetitle'] = $this->sitetitle
;
337 $constants = GeneralUtility
::makeInstance(Parser\TypoScriptParser
::class);
338 // Register comments!
339 $constants->regComments
= 1;
340 $constants->setup
= $this->mergeConstantsFromPageTSconfig([]);
341 /** @var ConditionMatcher $matchObj */
342 $matchObj = GeneralUtility
::makeInstance(ConditionMatcher
::class);
343 // Matches ALL conditions in TypoScript
344 $matchObj->setSimulateMatchResult(true
);
346 $cc = count($this->constants
);
347 $defaultConstants = [];
348 foreach ($this->constants
as $str) {
351 if (strstr($str, $this->edit_divider
)) {
352 $parts = explode($this->edit_divider
, $str, 2);
354 $constants->parse($parts[0], $matchObj);
356 $this->flatSetup
= [];
357 $this->flattenSetup($constants->setup
, '');
358 $defaultConstants = $this->flatSetup
;
360 $constants->parse($str, $matchObj);
362 $this->flatSetup
= [];
363 $this->flattenSetup($constants->setup
, '');
364 $this->setup
['constants'] = $constants->setup
;
365 return $this->ext_compareFlatSetups($defaultConstants);
369 * @param array $theSetup
370 * @param string $theKey
373 public function ext_getSetup($theSetup, $theKey)
375 $parts = explode('.', $theKey, 2);
376 if ((string)$parts[0] !== '' && is_array($theSetup[$parts[0] . '.'])) {
377 if (trim($parts[1]) !== '') {
378 return $this->ext_getSetup($theSetup[$parts[0] . '.'], trim($parts[1]));
380 return [$theSetup[$parts[0] . '.'], $theSetup[$parts[0]]];
382 if (trim($theKey) !== '') {
383 return [[], $theSetup[$theKey]];
385 return [$theSetup, ''];
392 * @param string $depth_in
393 * @param string $depthData
394 * @param string $parentType (unused)
395 * @param string $parentValue (unused)
396 * @param string $alphaSort sorts the array keys / tree by alphabet when set to 1
399 public function ext_getObjTree($arr, $depth_in, $depthData, $parentType = '', $parentValue = '', $alphaSort = '0')
402 if ($alphaSort == '1') {
407 foreach ($arr as $key => $value) {
408 // Don't do anything with comments / linenumber registrations...
409 if (substr($key, -2) !== '..') {
410 $key = preg_replace('/\\.$/', '', $key);
411 if (substr($key, -1) !== '.') {
412 if (MathUtility
::canBeInterpretedAsInteger($key)) {
413 $keyArr_num[$key] = $arr[$key];
415 $keyArr_alpha[$key] = $arr[$key];
421 $keyArr = $keyArr_num +
$keyArr_alpha;
423 $depth_in = $depth_in . '.';
425 foreach ($keyArr as $key => $value) {
426 $depth = $depth_in . $key;
427 // This excludes all constants starting with '_' from being shown.
428 if ($this->bType
!== 'const' ||
$depth[0] !== '_') {
429 $goto = substr(md5($depth), 0, 6);
430 $deeper = is_array($arr[$key . '.']) && ($this->tsbrowser_depthKeys
[$depth] ||
$this->ext_expandAllNotes
) ?
1 : 0;
431 $PM = is_array($arr[$key . '.']) && !$this->ext_noPMicons ?
($deeper ?
'minus' : 'plus') : 'join';
432 $HTML .= $depthData . '<li>';
433 if ($PM !== 'join') {
435 'id' => $GLOBALS['SOBE']->id
,
436 'tsbr[' . $depth . ']' => $deeper ?
0 : 1
438 if (GeneralUtility
::_GP('breakPointLN')) {
439 $urlParameters['breakPointLN'] = GeneralUtility
::_GP('breakPointLN');
441 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters) . '#' . $goto;
442 $HTML .= '<a class="list-tree-control' . ($PM === 'minus' ?
' list-tree-control-open' : ' list-tree-control-closed') . '" name="' . $goto . '" href="' . htmlspecialchars($aHref) . '"><i class="fa"></i></a>';
446 if (($depth === 'types' ||
$depth === 'resources' ||
$depth === 'sitetitle') && $this->bType
=== 'setup') {
447 $label = '<span style="color: #666666;">' . $label . '</span>';
449 if ($this->linkObjects
) {
451 'id' => $GLOBALS['SOBE']->id
,
454 if (GeneralUtility
::_GP('breakPointLN')) {
455 $urlParameters['breakPointLN'] = GeneralUtility
::_GP('breakPointLN');
457 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
458 if ($this->bType
!== 'const') {
459 $ln = is_array($arr[$key . '.ln..']) ?
'Defined in: ' . $this->lineNumberToScript($arr[$key . '.ln..']) : 'N/A';
463 if ($this->tsbrowser_searchKeys
[$depth] & 4) {
464 $label = '<strong class="text-danger">' . $label . '</strong>';
466 // The key has matched the search string
467 $label = '<a href="' . htmlspecialchars($aHref) . '" title="' . htmlspecialchars($ln) . '">' . $label . '</a>';
471 <span class="list-tree-group">
472 <span class="list-tree-label">[' . $label . ']</span>';
473 if (isset($arr[$key])) {
474 $theValue = $arr[$key];
475 if ($this->fixedLgd
) {
476 $imgBlocks = ceil(1 +
strlen($depthData) / 77);
477 $lgdChars = 68 - ceil(strlen(('[' . $key . ']')) * 0.8) - $imgBlocks * 3;
478 $theValue = $this->ext_fixed_lgd($theValue, $lgdChars);
480 // The value has matched the search string
481 if ($this->tsbrowser_searchKeys
[$depth] & 2) {
482 $HTML .= ' = <span class="list-tree-value text-danger">' . htmlspecialchars($theValue) . '</span>';
484 $HTML .= ' = <span class="list-tree-value">' . htmlspecialchars($theValue) . '</span>';
486 if ($this->ext_regComments
&& isset($arr[$key . '..'])) {
487 $comment = $arr[$key . '..'];
488 // Skip INCLUDE_TYPOSCRIPT comments, they are almost useless
489 if (!preg_match('/### <INCLUDE_TYPOSCRIPT:.*/', $comment)) {
490 // Remove linebreaks, replace with ' '
491 $comment = preg_replace('/[\\r\\n]/', ' ', $comment);
492 // Remove # and * if more than twice in a row
493 $comment = preg_replace('/[#\\*]{2,}/', '', $comment);
494 // Replace leading # (just if it exists) and add it again. Result: Every comment should be prefixed by a '#'.
495 $comment = preg_replace('/^[#\\*\\s]+/', '# ', $comment);
496 // Masking HTML Tags: Replace < with < and > with >
497 $comment = htmlspecialchars($comment);
498 $HTML .= ' <i class="text-muted">' . trim($comment) . '</i>';
504 $HTML .= $this->ext_getObjTree($arr[$key . '.'], $depth, $depthData, '', $arr[$key], $alphaSort);
509 $HTML = '<ul class="list-tree text-monospace">' . $HTML . '</ul>';
516 * Find the originating template name for an array of line numbers (TypoScript setup only!)
517 * Given an array of linenumbers the method will try to find the corresponding template where this line originated
518 * The linenumber indicates the *last* lineNumber that is part of the template
520 * lineNumbers are in sync with the calculated lineNumbers '.ln..' in TypoScriptParser
522 * @param array $lnArr Array with linenumbers (might have some extra symbols, for example for unsetting) to be processed
523 * @return array The same array where each entry has been prepended by the template title if available
525 public function lineNumberToScript(array $lnArr)
527 // On the first call, construct the lnToScript array.
528 if (!is_array($this->lnToScript
)) {
529 $this->lnToScript
= [];
531 // aggregatedTotalLineCount
533 foreach ($this->hierarchyInfo
as $templateNumber => $info) {
534 // hierarchyInfo has the number of lines in configLines, but unfortunately this value
535 // was calculated *before* processing of any INCLUDE instructions
536 // for some yet unknown reason we have to add an extra +2 offset
537 $linecountAfterIncludeProcessing = substr_count($this->config
[$templateNumber], LF
) +
2;
538 $c +
= $linecountAfterIncludeProcessing;
539 $this->lnToScript
[$c] = $info['title'];
543 foreach ($lnArr as $k => $ln) {
544 foreach ($this->lnToScript
as $endLn => $title) {
545 if ($endLn >= (int)$ln) {
546 $lnArr[$k] = '"' . $title . '", ' . $ln;
552 return implode('; ', $lnArr);
557 * @param string $depth_in
558 * @param string $searchString
559 * @param array $keyArray
563 public function ext_getSearchKeys($arr, $depth_in, $searchString, $keyArray)
566 foreach ($arr as $key => $value) {
567 $key = preg_replace('/\\.$/', '', $key);
568 if (substr($key, -1) !== '.') {
573 $depth_in = $depth_in . '.';
576 if ($this->regexMode
) {
577 $searchPattern = '/' . addcslashes($searchString, '/') . '/';
578 $matchResult = @preg_match
($searchPattern, '');
579 if ($matchResult === false
) {
580 throw new Exception(sprintf('Error evaluating regular expression "%s".', $searchPattern), 1446559458);
583 foreach ($keyArr as $key => $value) {
584 $depth = $depth_in . $key;
585 $deeper = is_array($arr[$key . '.']);
586 if ($this->regexMode
) {
587 // The value has matched
588 if (preg_match($searchPattern, $arr[$key])) {
589 $this->tsbrowser_searchKeys
[$depth] +
= 2;
591 // The key has matched
592 if (preg_match($searchPattern, $key)) {
593 $this->tsbrowser_searchKeys
[$depth] +
= 4;
595 // Just open this subtree if the parent key has matched the search
596 if (preg_match($searchPattern, $depth_in)) {
597 $this->tsbrowser_searchKeys
[$depth] = 1;
600 // The value has matched
601 if (stristr($arr[$key], $searchString)) {
602 $this->tsbrowser_searchKeys
[$depth] +
= 2;
604 // The key has matches
605 if (stristr($key, $searchString)) {
606 $this->tsbrowser_searchKeys
[$depth] +
= 4;
608 // Just open this subtree if the parent key has matched the search
609 if (stristr($depth_in, $searchString)) {
610 $this->tsbrowser_searchKeys
[$depth] = 1;
614 $cS = count($this->tsbrowser_searchKeys
);
615 $keyArray = $this->ext_getSearchKeys($arr[$key . '.'], $depth, $searchString, $keyArray);
616 if ($cS != count($this->tsbrowser_searchKeys
)) {
617 $keyArray[$depth] = 1;
628 public function ext_getRootlineNumber($pid)
631 foreach ($this->getRootLine() as $key => $val) {
632 if ((int)$val['uid'] === (int)$pid) {
642 * @param string $depthData
643 * @param array $keyArray
647 public function ext_getTemplateHierarchyArr($arr, $depthData, $keyArray, $first = 0)
650 foreach ($arr as $key => $value) {
651 $key = preg_replace('/\\.$/', '', $key);
652 if (substr($key, -1) !== '.') {
658 /** @var IconFactory $iconFactory */
659 $iconFactory = GeneralUtility
::makeInstance(IconFactory
::class);
660 foreach ($keyArr as $key => $value) {
663 $deeper = is_array($arr[$key . '.']);
665 $LN = $a == $c ?
'blank' : 'line';
666 $BTM = $a == $c ?
'top' : '';
668 $alttext = '[' . $row['templateID'] . ']';
669 $alttext .= $row['pid'] ?
' - ' . BackendUtility
::getRecordPath($row['pid'], $GLOBALS['SOBE']->perms_clause
, 20) : '';
670 $icon = substr($row['templateID'], 0, 3) === 'sys'
671 ?
'<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIconForRecord('sys_template', $row, Icon
::SIZE_SMALL
)->render() . '</span>'
672 : '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIcon('mimetypes-x-content-template-static', Icon
::SIZE_SMALL
)->render() . '</span>';
673 if (in_array($row['templateID'], $this->clearList_const
) ||
in_array($row['templateID'], $this->clearList_setup
)) {
675 'id' => $GLOBALS['SOBE']->id
,
676 'template' => $row['templateID']
678 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
679 $A_B = '<a href="' . htmlspecialchars($aHref) . '">';
681 if (GeneralUtility
::_GP('template') == $row['templateID']) {
682 $A_B = '<strong>' . $A_B;
689 $HTML .= ($first ?
'' : '<span class="treeline-icon treeline-icon-join' . $BTM . '"></span>') . $icon . ' ' . $A_B
690 . htmlspecialchars(GeneralUtility
::fixed_lgd_cs($row['title'], $GLOBALS['BE_USER']->uc
['titleLen']))
691 . $A_E . ' ';
692 $RL = $this->ext_getRootlineNumber($row['pid']);
693 $statusCheckedIcon = $iconFactory->getIcon('status-status-checked', Icon
::SIZE_SMALL
)->render();
695 <td class="nowrap">' . $HTML . '</td>
696 <td align="center">' . ($row['root'] ?
$statusCheckedIcon : '') . '</td>
697 <td align="center">' . ($row['clConf'] ?
$statusCheckedIcon : '') . '</td>
698 <td align="center">' . ($row['clConst'] ?
$statusCheckedIcon : '') . '</td>
699 <td align="center">' . ($row['pid'] ?
: '') . '</td>
700 <td align="center">' . ($RL >= 0 ?
$RL : '') . '</td>
701 <td>' . ($row['next'] ?
$row['next'] : '') . '</td>
704 $keyArray = $this->ext_getTemplateHierarchyArr($arr[$key . '.'], $depthData . ($first ?
'' : '<span class="treeline-icon treeline-icon-' . $LN . '"></span>'), $keyArray);
711 * Processes the flat array from TemplateService->hierarchyInfo
712 * and turns it into a hierarchical array to show dependencies (used by TemplateAnalyzer)
714 * @param array $depthDataArr (empty array on external call)
715 * @param int &$pointer Element number (1! to count()) of $this->hierarchyInfo that should be processed.
716 * @return array Processed hierachyInfo.
718 public function ext_process_hierarchyInfo(array $depthDataArr, &$pointer)
720 $parent = $this->hierarchyInfo
[$pointer - 1]['templateParent'];
721 while ($pointer > 0 && $this->hierarchyInfo
[$pointer - 1]['templateParent'] == $parent) {
723 $row = $this->hierarchyInfo
[$pointer];
724 $depthDataArr[$row['templateID']] = $row;
725 unset($this->clearList_setup_temp
[$row['templateID']]);
726 unset($this->clearList_const_temp
[$row['templateID']]);
727 $this->templateTitles
[$row['templateID']] = $row['title'];
728 if ($row['templateID'] == $this->hierarchyInfo
[$pointer - 1]['templateParent']) {
729 $depthDataArr[$row['templateID'] . '.'] = $this->ext_process_hierarchyInfo([], $pointer);
732 return $depthDataArr;
736 * Get formatted HTML output for TypoScript either with Syntaxhiglighting or in plain mode
738 * @param array $config Array with simple strings of typoscript code.
739 * @param bool $lineNumbers Prepend linNumbers to each line.
740 * @param bool $comments Enable including comments in output.
741 * @param bool $crop Enable cropping of long lines.
742 * @param bool $syntaxHL Enrich output with syntaxhighlighting.
743 * @param int $syntaxHLBlockmode
746 public function ext_outputTS(
748 $lineNumbers = false
,
752 $syntaxHLBlockmode = 0
755 foreach ($config as $str) {
756 $all .= '[GLOBAL]' . LF
. $str;
759 $tsparser = GeneralUtility
::makeInstance(Parser\TypoScriptParser
::class);
760 $tsparser->lineNumberOffset
= $this->ext_lineNumberOffset +
1;
761 $tsparser->parentObject
= $this;
762 return $tsparser->doSyntaxHighlight($all, $lineNumbers ?
[$this->ext_lineNumberOffset +
1] : '', $syntaxHLBlockmode);
764 return $this->ext_formatTS($all, $lineNumbers, $comments, $crop);
768 * Returns a new string of max. $chars length
769 * If the string is longer, it will be truncated and prepended with '...'
770 * $chars must be an integer of at least 4
772 * @param string $string
776 public function ext_fixed_lgd($string, $chars)
779 if (strlen($string) > $chars) {
780 if (strlen($string) > 24 && preg_match('/^##[a-z0-9]{6}_B##$/', substr($string, 0, 12))) {
781 $string = GeneralUtility
::fixed_lgd_cs(substr($string, 12, -12), ($chars - 3));
782 $marker = substr(md5($string), 0, 6);
783 return '##' . $marker . '_B##' . $string . '##' . $marker . '_E##';
785 return GeneralUtility
::fixed_lgd_cs($string, $chars - 3);
792 * @param int $lineNumber Line Number
796 public function ext_lnBreakPointWrap($lineNumber, $str)
798 return '<a href="#" id="line-' . $lineNumber . '" onClick="return brPoint(' . $lineNumber . ','
799 . ($this->ext_lineNumberOffset_mode
=== 'setup' ?
1 : 0) . ');">' . $str . '</a>';
803 * @param string $input
805 * @param bool $comments
809 public function ext_formatTS($input, $ln, $comments = true
, $crop = false
)
811 $cArr = explode(LF
, $input);
812 $n = ceil(log10(count($cArr) +
$this->ext_lineNumberOffset
));
814 foreach ($cArr as $k => $v) {
815 $lln = $k +
$this->ext_lineNumberOffset +
1;
817 $lineNum = $this->ext_lnBreakPointWrap($lln, str_replace(' ', ' ', sprintf(('% ' . $n . 'd'), $lln))) . ': ';
819 $v = htmlspecialchars($v);
821 $v = $this->ext_fixed_lgd($v, $ln ?
71 : 77);
823 $cArr[$k] = $lineNum . str_replace(' ', ' ', $v);
824 $firstChar = substr(trim($v), 0, 1);
825 if ($firstChar === '[') {
826 $cArr[$k] = '<strong class="text-success">' . $cArr[$k] . '</strong>';
827 } elseif ($firstChar === '/' ||
$firstChar === '#') {
829 $cArr[$k] = '<span class="text-muted">' . $cArr[$k] . '</span>';
835 $output = implode($cArr, '<br />') . '<br />';
840 * Get a single sys_template record attached to a single page.
841 * If multiple template records are on this page, the first (order by sorting)
842 * record will be returned, unless a specific template uid is specified via $templateUid
844 * @param int $pid The pid to select sys_template records from
845 * @param int $templateUid Optional template uid
846 * @return array|null Returns the template record or null if none was found
848 public function ext_getFirstTemplate($pid, $templateUid = 0)
854 // Query is taken from the runThroughTemplates($theRootLine) function in the parent class.
855 $queryBuilder = $this->getTemplateQueryBuilder($pid)
858 $queryBuilder->andWhere(
859 $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($templateUid, \PDO
::PARAM_INT
))
862 $row = $queryBuilder->execute()->fetch();
863 BackendUtility
::workspaceOL('sys_template', $row);
869 * Get an array of all template records on a page.
871 * @param int $pid Pid to fetch sys_template records for
872 * @return array[] Array of template records
874 public function ext_getAllTemplates($pid): array
879 $result = $this->getTemplateQueryBuilder($pid)->execute();
881 while ($row = $result->fetch()) {
882 BackendUtility
::workspaceOL('sys_template', $row);
883 if (is_array($row)) {
891 * Internal helper method to prepare the query builder for
892 * getting sys_template records from a given pid
894 * @param int $pid The pid to select sys_template records from
895 * @return QueryBuilder Returns a QueryBuilder
897 protected function getTemplateQueryBuilder(int $pid): QueryBuilder
899 $queryBuilder = GeneralUtility
::makeInstance(ConnectionPool
::class)
900 ->getQueryBuilderForTable('sys_template');
901 $queryBuilder->getRestrictions()
903 ->add(GeneralUtility
::makeInstance(DeletedRestriction
::class));
904 $queryBuilder->select('*')
905 ->from('sys_template')
907 $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO
::PARAM_INT
))
909 if (!empty($GLOBALS['TCA']['sys_template']['ctrl']['sortby'])) {
910 $queryBuilder->orderBy($GLOBALS['TCA']['sys_template']['ctrl']['sortby']);
913 return $queryBuilder;
917 * This function compares the flattened constants (default and all).
918 * Returns an array with the constants from the whole template which may be edited by the module.
920 * @param array $default
923 public function ext_compareFlatSetups($default)
925 $editableComments = [];
927 foreach ($this->flatSetup
as $const => $value) {
928 if (substr($const, -2) === '..' ||
!isset($this->flatSetup
[$const . '..'])) {
932 $comment = trim($this->flatSetup
[$const . '..']);
933 $c_arr = explode(LF
, $comment);
934 foreach ($c_arr as $k => $v) {
935 $line = trim(preg_replace('/^[#\\/]*/', '', $v));
939 $parts = explode(';', $line);
940 foreach ($parts as $par) {
941 if (strstr($par, '=')) {
942 $keyValPair = explode('=', $par, 2);
943 switch (trim(strtolower($keyValPair[0]))) {
946 $editableComments[$const]['type'] = trim($keyValPair[1]);
949 // List of categories.
950 $catSplit = explode('/', strtolower($keyValPair[1]));
951 $catSplit[0] = trim($catSplit[0]);
952 if (isset($this->categoryLabels
[$catSplit[0]])) {
953 $catSplit[0] = $this->categoryLabels
[$catSplit[0]];
955 $editableComments[$const]['cat'] = $catSplit[0];
956 // This is the subcategory. Must be a key in $this->subCategories[].
957 // catSplit[2] represents the search-order within the subcat.
958 $catSplit[1] = trim($catSplit[1]);
959 if ($catSplit[1] && isset($this->subCategories
[$catSplit[1]])) {
960 $editableComments[$const]['subcat_name'] = $catSplit[1];
961 $orderIdentifier = isset($catSplit[2]) ?
trim($catSplit[2]) : $counter;
962 $editableComments[$const]['subcat'] = $this->subCategories
[$catSplit[1]][1]
963 . '/' . $catSplit[1] . '/' . $orderIdentifier . 'z';
964 } elseif (isset($catSplit[2])) {
965 $editableComments[$const]['subcat'] = 'x' . '/' . trim($catSplit[2]) . 'z';
967 $editableComments[$const]['subcat'] = 'x' . '/' . $counter . 'z';
972 $editableComments[$const]['label'] = trim($keyValPair[1]);
974 case 'customcategory':
975 // Custom category label
976 $customCategory = explode('=', $keyValPair[1], 2);
977 if (trim($customCategory[0])) {
978 $categoryKey = strtolower($customCategory[0]);
979 $this->categoryLabels
[$categoryKey] = $this->getLanguageService()->sL($customCategory[1]);
982 case 'customsubcategory':
983 // Custom subCategory label
984 $customSubcategory = explode('=', $keyValPair[1], 2);
985 if (trim($customSubcategory[0])) {
986 $subCategoryKey = strtolower($customSubcategory[0]);
987 $this->subCategories
[$subCategoryKey][0] = $this->getLanguageService()->sL($customSubcategory[1]);
994 if (isset($editableComments[$const])) {
995 $editableComments[$const]['name'] = $const;
996 $editableComments[$const]['value'] = trim($value);
997 if (isset($default[$const])) {
998 $editableComments[$const]['default_value'] = trim($default[$const]);
1002 return $editableComments;
1006 * @param array $editConstArray
1008 public function ext_categorizeEditableConstants($editConstArray)
1010 // Runs through the available constants and fills the $this->categories array with pointers and priority-info
1011 foreach ($editConstArray as $constName => $constData) {
1012 if (!$constData['type']) {
1013 $constData['type'] = 'string';
1015 $cats = explode(',', $constData['cat']);
1016 // if = only one category, while allows for many. We have agreed on only one category is the most basic way...
1017 foreach ($cats as $theCat) {
1018 $theCat = trim($theCat);
1020 $this->categories
[$theCat][$constName] = $constData['subcat'];
1029 public function ext_getCategoryLabelArray()
1031 // Returns array used for labels in the menu.
1033 foreach ($this->categories
as $k => $v) {
1035 $retArr[$k] = strtoupper($k) . ' (' . count($v) . ')';
1042 * @param string $type
1045 public function ext_getTypeData($type)
1048 $type = trim($type);
1050 $retArr['type'] = 'string';
1052 $m = strcspn($type, ' [');
1053 $retArr['type'] = strtolower(substr($type, 0, $m));
1054 $types = ['int' => 1, 'options' => 1, 'file' => 1, 'boolean' => 1, 'offset' => 1, 'user' => 1];
1055 if (isset($types[$retArr['type']])) {
1056 $p = trim(substr($type, $m));
1058 preg_match('/\\[(.*)\\]/', $p, $reg);
1061 $retArr['paramstr'] = $p;
1062 switch ($retArr['type']) {
1064 if ($retArr['paramstr'][0] === '-') {
1065 $retArr['params'] = GeneralUtility
::intExplode('-', substr($retArr['paramstr'], 1));
1066 $retArr['params'][0] = (int)('-' . $retArr['params'][0]);
1068 $retArr['params'] = GeneralUtility
::intExplode('-', $retArr['paramstr']);
1070 $retArr['min'] = $retArr['params'][0];
1071 $retArr['max'] = $retArr['params'][1];
1072 $retArr['paramstr'] = $retArr['params'][0] . ' - ' . $retArr['params'][1];
1075 $retArr['params'] = explode(',', $retArr['paramstr']);
1085 * @param string $category
1087 public function ext_getTSCE_config($category)
1089 $catConf = $this->setup
['constants']['TSConstantEditor.'][$category . '.'];
1091 if (is_array($catConf)) {
1092 foreach ($catConf as $key => $val) {
1100 if (MathUtility
::canBeInterpretedAsInteger($key)) {
1101 $constRefs = explode(',', $val);
1102 foreach ($constRefs as $const) {
1103 $const = trim($const);
1105 $out['constants'][$const] .= '<span class="label label-danger">' . $key . '</span>';
1112 $this->helpConfig
= $out;
1116 * @param array $params
1119 public function ext_fNandV($params)
1121 $fN = 'data[' . $params['name'] . ']';
1122 $idName = str_replace('.', '-', $params['name']);
1123 $fV = $params['value'];
1124 // Values entered from the constantsedit cannot be constants! 230502; removed \{ and set {
1125 if (preg_match('/^{[\\$][a-zA-Z0-9\\.]*}$/', trim($fV), $reg)) {
1128 $fV = htmlspecialchars($fV);
1129 return [$fN, $fV, $params, $idName];
1133 * This functions returns the HTML-code that creates the editor-layout of the module.
1135 * @param array $theConstants
1136 * @param string $category
1139 public function ext_printFields($theConstants, $category)
1141 reset($theConstants);
1144 if (is_array($this->categories
[$category])) {
1145 $help = $this->helpConfig
;
1146 if (!$this->doNotSortCategoriesBeforeMakingForm
) {
1147 asort($this->categories
[$category]);
1149 /** @var IconFactory $iconFactory */
1150 $iconFactory = GeneralUtility
::makeInstance(IconFactory
::class);
1151 foreach ($this->categories
[$category] as $name => $type) {
1152 $params = $theConstants[$name];
1153 if (is_array($params)) {
1154 if ($subcat != $params['subcat_name']) {
1155 $subcat = $params['subcat_name'];
1156 $subcat_name = $params['subcat_name'] ?
$this->subCategories
[$params['subcat_name']][0] : 'Others';
1157 $output .= '<h3>' . $subcat_name . '</h3>';
1159 $label = $this->getLanguageService()->sL($params['label']);
1160 $label_parts = explode(':', $label, 2);
1161 if (count($label_parts) === 2) {
1162 $head = trim($label_parts[0]);
1163 $body = trim($label_parts[1]);
1165 $head = trim($label_parts[0]);
1168 $typeDat = $this->ext_getTypeData($params['type']);
1170 $raname = substr(md5($params['name']), 0, 10);
1171 $aname = '\'' . $raname . '\'';
1172 list($fN, $fV, $params, $idName) = $this->ext_fNandV($params);
1173 $idName = htmlspecialchars($idName);
1175 switch ($typeDat['type']) {
1178 $additionalAttributes = '';
1179 if ($typeDat['paramstr']) {
1180 $hint = ' Range: ' . $typeDat['paramstr'];
1181 } elseif ($typeDat['type'] === 'int+') {
1182 $hint = ' Range: 0 - ';
1183 $typeDat['min'] = 0;
1185 $hint = ' (Integer)';
1188 if (isset($typeDat['min'])) {
1189 $additionalAttributes .= ' min="' . (int)$typeDat['min'] . '" ';
1191 if (isset($typeDat['max'])) {
1192 $additionalAttributes .= ' max="' . (int)$typeDat['max'] . '" ';
1196 '<input class="form-control" id="' . $idName . '" type="number"'
1197 . ' name="' . $fN . '" value="' . $fV . '"' . ' onChange="uFormUrl(' . $aname . ')"' . $additionalAttributes . ' />';
1201 <input class="form-control formengine-colorpickerelement t3js-color-picker" type="text" id="input-' . $idName . '" rel="' . $idName .
1202 '" name="' . $fN . '" value="' . $fV . '"' . $this->getDocumentTemplate()->formWidth(7) . ' onChange="uFormUrl(' . $aname . ')" />';
1204 if (empty($this->inlineJavaScript
[$typeDat['type']])) {
1205 $this->inlineJavaScript
[$typeDat['type']] = 'require([\'TYPO3/CMS/Backend/ColorPicker\'], function(ColorPicker){ColorPicker.initialize()});';
1209 $wArr = explode('|', $fV);
1210 $p_field = '<input class="form-control" type="text" id="' . $idName . '" name="' . $fN . '" value="' . $wArr[0] . '"' . $this->getDocumentTemplate()->formWidth(29) . ' onChange="uFormUrl(' . $aname . ')" />';
1212 $p_field .= '<input class="form-control" type="text" name="W' . $fN . '" value="' . $wArr[1] . '"' . $this->getDocumentTemplate()->formWidth(15) . ' onChange="uFormUrl(' . $aname . ')" />';
1215 $wArr = explode(',', $fV);
1216 $labels = GeneralUtility
::trimExplode(',', $typeDat['paramstr']);
1217 $p_field = ($labels[0] ?
$labels[0] : 'x') . ':<input type="text" name="' . $fN . '" value="' . $wArr[0] . '"' . $this->getDocumentTemplate()->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1219 $p_field .= ($labels[1] ?
$labels[1] : 'y') . ':<input type="text" name="W' . $fN . '" value="' . $wArr[1] . '"' . $this->getDocumentTemplate()->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1220 $labelsCount = count($labels);
1221 for ($aa = 2; $aa < $labelsCount; $aa++
) {
1223 $p_field .= ' , ' . $labels[$aa] . ':<input type="text" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '"' . $this->getDocumentTemplate()->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1225 $p_field .= '<input type="hidden" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '" />';
1230 if (is_array($typeDat['params'])) {
1232 foreach ($typeDat['params'] as $val) {
1233 $vParts = explode('=', $val, 2);
1234 $label = $vParts[0];
1235 $val = isset($vParts[1]) ?
$vParts[1] : $vParts[0];
1238 if ($val === $params['value']) {
1241 $p_field .= '<option value="' . htmlspecialchars($val) . '"' . $sel . '>' . $this->getLanguageService()->sL($label) . '</option>';
1243 $p_field = '<select class="form-control" id="' . $idName . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1247 $sel = $fV ?
'checked' : '';
1249 '<input type="hidden" name="' . $fN . '" value="0" />'
1250 . '<label class="btn btn-default btn-checkbox">'
1251 . '<input id="' . $idName . '" type="checkbox" name="' . $fN . '" value="' . ($typeDat['paramstr'] ?
$typeDat['paramstr'] : 1) . '" ' . $sel . ' onClick="uFormUrl(' . $aname . ')" />'
1252 . '<span class="t3-icon fa"></span>'
1256 $sel = $fV ?
'checked' : '';
1258 '<input type="hidden" name="' . $fN . '" value="#" />'
1259 . '<label class="btn btn-default btn-checkbox">'
1260 . '<input id="' . $idName . '" type="checkbox" name="' . $fN . '" value="" ' . $sel . ' onClick="uFormUrl(' . $aname . ')" />'
1261 . '<span class="t3-icon fa"></span>'
1266 $extList = $typeDat['paramstr'];
1267 if ($extList === 'IMAGE_EXT') {
1268 $extList = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
1270 $p_field = '<option value="">(' . $extList . ')</option>';
1271 if (trim($params['value'])) {
1272 $val = $params['value'];
1273 $p_field .= '<option value=""></option>';
1274 $p_field .= '<option value="' . htmlspecialchars($val) . '" selected>' . $val . '</option>';
1276 $p_field = '<select class="form-select" id="' . $idName . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1279 $userFunction = $typeDat['paramstr'];
1280 $userFunctionParams = ['fieldName' => $fN, 'fieldValue' => $fV];
1281 $p_field = GeneralUtility
::callUserFunction($userFunction, $userFunctionParams, $this);
1284 $p_field = '<input class="form-control" id="' . $idName . '" type="text" name="' . $fN . '" value="' . $fV . '"'
1285 . ' onChange="uFormUrl(' . $aname . ')" />';
1287 // Define default names and IDs
1288 $userTyposcriptID = 'userTS-' . $idName;
1289 $defaultTyposcriptID = 'defaultTS-' . $idName;
1290 $checkboxName = 'check[' . $params['name'] . ']';
1291 $checkboxID = 'check-' . $idName;
1292 $userTyposcriptStyle = '';
1293 $deleteIconHTML = '';
1294 $constantCheckbox = '';
1295 $constantDefaultRow = '';
1296 if (!$this->ext_dontCheckIssetValues
) {
1297 // Set the default styling options
1298 if (isset($this->objReg
[$params['name']])) {
1299 $checkboxValue = 'checked';
1300 $defaultTyposcriptStyle = 'style="display:none;"';
1302 $checkboxValue = '';
1303 $userTyposcriptStyle = 'style="display:none;"';
1304 $defaultTyposcriptStyle = '';
1306 $deleteTitle = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.deleteTitle'));
1307 $deleteIcon = $iconFactory->getIcon('actions-edit-undo', Icon
::SIZE_SMALL
)->render();
1309 '<button type="button" class="btn btn-default t3js-toggle" data-toggle="undo" rel="' . $idName . '">'
1310 . '<span title="' . $deleteTitle . '" alt="' . $deleteTitle . '">'
1314 $editTitle = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.editTitle'));
1315 $editIcon = $iconFactory->getIcon('actions-open', Icon
::SIZE_SMALL
)->render();
1317 '<button type="button" class="btn btn-default t3js-toggle" data-toggle="edit" rel="' . $idName . '">'
1318 . '<span title="' . $editTitle . '" alt="' . $editTitle . '">'
1322 $constantCheckbox = '<input type="hidden" name="' . $checkboxName . '" id="' . $checkboxID . '" value="' . $checkboxValue . '"/>';
1323 // If there's no default value for the field, use a static label.
1324 if (!$params['default_value']) {
1325 $params['default_value'] = '[Empty]';
1327 $constantDefaultRow =
1328 '<div class="input-group defaultTS" id="' . $defaultTyposcriptID . '" ' . $defaultTyposcriptStyle . '>'
1329 . '<span class="input-group-btn">' . $editIconHTML . '</span>'
1330 . '<input class="form-control" type="text" placeholder="' . htmlspecialchars($params['default_value']) . '" readonly>'
1334 '<div class="input-group userTS" id="' . $userTyposcriptID . '" ' . $userTyposcriptStyle . '>'
1335 . '<span class="input-group-btn">' . $deleteIconHTML . '</span>'
1338 $constantLabel = '<label class="t3js-formengine-label"><span>' . htmlspecialchars($head) . '</span></label>';
1339 $constantName = '<span class="help-block">[' . $params['name'] . ']</span>';
1340 $constantDescription = $body ?
'<p class="help-block">' . htmlspecialchars($body) . '</p>' : '';
1343 $constantData .= '<span class="help-block">' . $hint . '</span>';
1348 . $constantDefaultRow;
1351 '<fieldset class="form-section">'
1352 . '<a name="' . $raname . '"></a>' . $help['constants'][$params['name']]
1353 . '<div class="form-group">'
1354 . $constantLabel . $constantName . $constantDescription . $constantData
1358 debug('Error. Constant did not exist. Should not happen.');
1362 return '<div class="tstemplate-constanteditor">' . $output . '</div>';
1365 /***************************
1367 * Processing input values
1369 ***************************/
1371 * @param string $constants
1373 public function ext_regObjectPositions($constants)
1375 // This runs through the lines of the constants-field of the active template and registers the constants-names
1376 // and line positions in an array, $this->objReg
1377 $this->raw
= explode(LF
, $constants);
1379 // Resetting the objReg if the divider is found!!
1381 $this->ext_regObjects('');
1385 * @param string $pre
1387 public function ext_regObjects($pre)
1389 // Works with regObjectPositions. "expands" the names of the TypoScript objects
1390 while (isset($this->raw
[$this->rawP
])) {
1391 $line = ltrim($this->raw
[$this->rawP
]);
1392 if (strstr($line, $this->edit_divider
)) {
1393 // Resetting the objReg if the divider is found!!
1398 if ($line[0] === '[') {
1399 } elseif (strcspn($line, '}#/') != 0) {
1400 $varL = strcspn($line, ' {=<');
1401 $var = substr($line, 0, $varL);
1402 $line = ltrim(substr($line, $varL));
1405 $this->objReg
[$pre . $var] = $this->rawP
- 1;
1408 $this->ext_inBrace++
;
1409 $this->ext_regObjects($pre . $var . '.');
1412 $this->lastComment
= '';
1413 } elseif ($line[0] === '}') {
1414 $this->lastComment
= '';
1415 $this->ext_inBrace
--;
1416 if ($this->ext_inBrace
< 0) {
1417 $this->ext_inBrace
= 0;
1427 * @param string $key
1428 * @param string $var
1430 public function ext_putValueInConf($key, $var)
1432 // Puts the value $var to the TypoScript value $key in the current lines of the templates.
1433 // If the $key is not found in the template constants field, a new line is inserted in the bottom.
1434 $theValue = ' ' . trim($var);
1435 if (isset($this->objReg
[$key])) {
1436 $lineNum = $this->objReg
[$key];
1437 $parts = explode('=', $this->raw
[$lineNum], 2);
1438 if (count($parts) === 2) {
1439 $parts[1] = $theValue;
1441 $this->raw
[$lineNum] = implode($parts, '=');
1443 $this->raw
[] = $key . ' =' . $theValue;
1445 $this->changed
= true
;
1449 * @param string $key
1451 public function ext_removeValueInConf($key)
1453 // Removes the value in the configuration
1454 if (isset($this->objReg
[$key])) {
1455 $lineNum = $this->objReg
[$key];
1456 unset($this->raw
[$lineNum]);
1458 $this->changed
= true
;
1463 * @param array $settings
1466 public function ext_depthKeys($arr, $settings)
1469 foreach ($arr as $theK => $theV) {
1470 $theKeyParts = explode('.', $theK);
1472 $c = count($theKeyParts);
1474 foreach ($theKeyParts as $p) {
1476 $depth .= ($depth ?
'.' : '') . $p;
1477 $tsbrArray[$depth] = $c == $a ?
$theV : 1;
1481 foreach ($tsbrArray as $theK => $theV) {
1483 $settings[$theK] = 1;
1485 unset($settings[$theK]);
1494 * @param array $http_post_vars
1495 * @param array $http_post_files (not used anymore)
1496 * @param array $theConstants
1497 * @param array $tplRow Not used
1499 public function ext_procesInput($http_post_vars, $http_post_files, $theConstants, $tplRow)
1501 $data = $http_post_vars['data'];
1502 $check = $http_post_vars['check'];
1503 $Wdata = $http_post_vars['Wdata'];
1504 $W2data = $http_post_vars['W2data'];
1505 $W3data = $http_post_vars['W3data'];
1506 $W4data = $http_post_vars['W4data'];
1507 $W5data = $http_post_vars['W5data'];
1508 if (is_array($data)) {
1509 foreach ($data as $key => $var) {
1510 if (isset($theConstants[$key])) {
1511 // If checkbox is set, update the value
1512 if ($this->ext_dontCheckIssetValues ||
isset($check[$key])) {
1513 // Exploding with linebreak, just to make sure that no multiline input is given!
1514 list($var) = explode(LF
, $var);
1515 $typeDat = $this->ext_getTypeData($theConstants[$key]['type']);
1516 switch ($typeDat['type']) {
1518 if ($typeDat['paramstr']) {
1519 $var = MathUtility
::forceIntegerInRange($var, $typeDat['params'][0], $typeDat['params'][1]);
1525 $var = max(0, (int)$var);
1530 $var = preg_replace('/[^A-Fa-f0-9]*/', '', $var);
1531 $useFulHex = strlen($var) > 3;
1532 $col[] = hexdec($var[0]);
1533 $col[] = hexdec($var[1]);
1534 $col[] = hexdec($var[2]);
1536 $col[] = hexdec($var[3]);
1537 $col[] = hexdec($var[4]);
1538 $col[] = hexdec($var[5]);
1540 $var = substr(('0' . dechex($col[0])), -1) . substr(('0' . dechex($col[1])), -1) . substr(('0' . dechex($col[2])), -1);
1542 $var .= substr(('0' . dechex($col[3])), -1) . substr(('0' . dechex($col[4])), -1) . substr(('0' . dechex($col[5])), -1);
1544 $var = '#' . strtoupper($var);
1555 if (isset($Wdata[$key])) {
1556 $var .= '|' . $Wdata[$key];
1560 if (isset($Wdata[$key])) {
1561 $var = (int)$var . ',' . (int)$Wdata[$key];
1562 if (isset($W2data[$key])) {
1563 $var .= ',' . (int)$W2data[$key];
1564 if (isset($W3data[$key])) {
1565 $var .= ',' . (int)$W3data[$key];
1566 if (isset($W4data[$key])) {
1567 $var .= ',' . (int)$W4data[$key];
1568 if (isset($W5data[$key])) {
1569 $var .= ',' . (int)$W5data[$key];
1578 $var = $typeDat['paramstr'] ?
$typeDat['paramstr'] : 1;
1582 if ($this->ext_printAll ||
(string)$theConstants[$key]['value'] !== (string)$var) {
1583 // Put value in, if changed.
1584 $this->ext_putValueInConf($key, $var);
1586 // Remove the entry because it has been "used"
1587 unset($check[$key]);
1589 $this->ext_removeValueInConf($key);
1594 // Remaining keys in $check indicates fields that are just clicked "on" to be edited.
1595 // Therefore we get the default value and puts that in the template as a start...
1596 if (!$this->ext_dontCheckIssetValues
&& is_array($check)) {
1597 foreach ($check as $key => $var) {
1598 if (isset($theConstants[$key])) {
1599 $dValue = $theConstants[$key]['default_value'];
1600 $this->ext_putValueInConf($key, $dValue);
1608 * @param string $perms_clause
1611 public function ext_prevPageWithTemplate($id, $perms_clause)
1613 $rootLine = BackendUtility
::BEgetRootLine($id, $perms_clause ?
' AND ' . $perms_clause : '');
1614 foreach ($rootLine as $p) {
1615 if ($this->ext_getFirstTemplate($p['uid'])) {
1623 * Is set by runThroughTemplates(), previously set via TemplateAnalyzerModuleFunctionController from the outside
1627 protected function getRootLine()
1629 return is_array($this->absoluteRootLine
) ?
$this->absoluteRootLine
: [];
1633 * @return LanguageService
1635 protected function getLanguageService()
1637 return $GLOBALS['LANG'];
1641 * @return DocumentTemplate
1643 protected function getDocumentTemplate()
1645 return $GLOBALS['TBE_TEMPLATE'];