TYPO3 CMS  TYPO3_8-7
ExtendedTemplateService.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
30 
36 {
43  public $edit_divider = '###MOD_TS:EDITABLE_CONSTANTS###';
44 
50  public $tt_track = false;
51 
55  public $categories = [
56  'basic' => [],
57  // 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' => [],
59  // Menu setup. This includes fontfiles, sizes, background images. Depending on the menutype.
60  'content' => [],
61  // All constants related to the display of pagecontent elements
62  'page' => [],
63  // General configuration like metatags, link targets
64  'advanced' => [],
65  // Advanced functions, which are used very seldom.
66  'all' => []
67  ];
68 
74  protected $categoryLabels = [];
75 
81  public $subCategories = [
82  // Standard categories:
83  'enable' => ['Enable features', 'a'],
84  'dims' => ['Dimensions, widths, heights, pixels', 'b'],
85  'file' => ['Files', 'c'],
86  'typo' => ['Typography', 'd'],
87  'color' => ['Colors', 'e'],
88  'links' => ['Links and targets', 'f'],
89  'language' => ['Language specific constants', 'g'],
90  // subcategories based on the default content elements
91  'cheader' => ['Content: \'Header\'', 'ma'],
92  'cheader_g' => ['Content: \'Header\', Graphical', 'ma'],
93  'ctext' => ['Content: \'Text\'', 'mb'],
94  'cimage' => ['Content: \'Image\'', 'md'],
95  'ctextmedia' => ['Content: \'Textmedia\'', 'ml'],
96  'cbullets' => ['Content: \'Bullet list\'', 'me'],
97  'ctable' => ['Content: \'Table\'', 'mf'],
98  'cuploads' => ['Content: \'Filelinks\'', 'mg'],
99  'cmultimedia' => ['Content: \'Multimedia\'', 'mh'],
100  'cmedia' => ['Content: \'Media\'', 'mr'],
101  'cmailform' => ['Content: \'Form\'', 'mi'],
102  'csearch' => ['Content: \'Search\'', 'mj'],
103  'clogin' => ['Content: \'Login\'', 'mk'],
104  'cmenu' => ['Content: \'Menu/Sitemap\'', 'mm'],
105  'cshortcut' => ['Content: \'Insert records\'', 'mn'],
106  'clist' => ['Content: \'List of records\'', 'mo'],
107  'chtml' => ['Content: \'HTML\'', 'mq']
108  ];
109 
115  public $ext_inBrace = 0;
116 
123 
127  public $tsbrowser_depthKeys = [];
128 
132  public $constantMode = '';
133 
137  public $regexMode = '';
138 
142  public $fixedLgd = '';
143 
148 
153 
157  public $ext_noPMicons = 0;
158 
163 
168 
175 
179  public $ext_printAll = 0;
180 
184  public $ext_CEformName = 'forms[0]';
185 
190 
196  public $templateTitles = [];
197 
201  protected $lnToScript = null;
202 
207 
212 
216  public $bType = '';
217 
221  public $linkObjects = false;
222 
226  public $helpConfig = [];
227 
231  public $changed = false;
232 
236  protected $objReg = [];
237 
241  public $raw = [];
242 
246  public $rawP = 0;
247 
251  public $lastComment = '';
252 
256  protected $inlineJavaScript = [];
257 
263  public function getInlineJavaScript()
264  {
266  }
267 
274  public function substituteConstants($all)
275  {
276  return preg_replace_callback('/\\{\\$(.[^}]+)\\}/', [$this, 'substituteConstantsCallBack'], $all);
277  }
278 
286  public function substituteConstantsCallBack($matches)
287  {
288  $marker = substr(md5($matches[0]), 0, 6);
289  switch ($this->constantMode) {
290  case 'const':
291  $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . $marker . '_B##' . $matches[0] . '##' . $marker . '_E##' : $matches[0];
292  break;
293  case 'subst':
294  $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . $marker . '_B##' . $this->flatSetup[$matches[1]] . '##' . $marker . '_E##' : $matches[0];
295  break;
296  case 'untouched':
297  $ret_val = $matches[0];
298  break;
299  default:
300  $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? $this->flatSetup[$matches[1]] : $matches[0];
301  }
302  return $ret_val;
303  }
304 
311  public function substituteCMarkers($all)
312  {
313  switch ($this->constantMode) {
314  case 'const':
315  case 'subst':
316  $all = preg_replace(
317  '/##[a-z0-9]{6}_B##((?:(?!##[a-z0-9]{6}_E##).)+)?##[a-z0-9]{6}_E##/',
318  '<strong style="color: green;">$1</strong>',
319  $all
320  );
321  break;
322  default:
323  }
324  return $all;
325  }
326 
333  public function generateConfig_constants()
334  {
335  // These vars are also set lateron...
336  $this->setup['sitetitle'] = $this->sitetitle;
337  // Parse constants
338  $constants = GeneralUtility::makeInstance(Parser\TypoScriptParser::class);
339  // Register comments!
340  $constants->regComments = 1;
341  $constants->setup = $this->mergeConstantsFromPageTSconfig([]);
343  $matchObj = GeneralUtility::makeInstance(ConditionMatcher::class);
344  // Matches ALL conditions in TypoScript
345  $matchObj->setSimulateMatchResult(true);
346  $c = 0;
347  $cc = count($this->constants);
348  $defaultConstants = [];
349  foreach ($this->constants as $str) {
350  $c++;
351  if ($c == $cc) {
352  if (strstr($str, $this->edit_divider)) {
353  $parts = explode($this->edit_divider, $str, 2);
354  $str = $parts[1];
355  $constants->parse($parts[0], $matchObj);
356  }
357  $this->flatSetup = [];
358  $this->flattenSetup($constants->setup, '');
359  $defaultConstants = $this->flatSetup;
360  }
361  $constants->parse($str, $matchObj);
362  }
363  $this->flatSetup = [];
364  $this->flattenSetup($constants->setup, '');
365  $this->setup['constants'] = $constants->setup;
366  return $this->ext_compareFlatSetups($defaultConstants);
367  }
368 
374  public function ext_getSetup($theSetup, $theKey)
375  {
376  $parts = explode('.', $theKey, 2);
377  if ((string)$parts[0] !== '' && is_array($theSetup[$parts[0] . '.'])) {
378  if (trim($parts[1]) !== '') {
379  return $this->ext_getSetup($theSetup[$parts[0] . '.'], trim($parts[1]));
380  }
381  return [$theSetup[$parts[0] . '.'], $theSetup[$parts[0]]];
382  }
383  if (trim($theKey) !== '') {
384  return [[], $theSetup[$theKey]];
385  }
386  return [$theSetup, ''];
387  }
388 
400  public function ext_getObjTree($arr, $depth_in, $depthData, $parentType = '', $parentValue = '', $alphaSort = '0')
401  {
402  $HTML = '';
403  if ($alphaSort == '1') {
404  ksort($arr);
405  }
406  $keyArr_num = [];
407  $keyArr_alpha = [];
408  foreach ($arr as $key => $value) {
409  // Don't do anything with comments / linenumber registrations...
410  if (substr($key, -2) !== '..') {
411  $key = preg_replace('/\\.$/', '', $key);
412  if (substr($key, -1) !== '.') {
414  $keyArr_num[$key] = $arr[$key];
415  } else {
416  $keyArr_alpha[$key] = $arr[$key];
417  }
418  }
419  }
420  }
421  ksort($keyArr_num);
422  $keyArr = $keyArr_num + $keyArr_alpha;
423  if ($depth_in) {
424  $depth_in = $depth_in . '.';
425  }
426  foreach ($keyArr as $key => $value) {
427  $depth = $depth_in . $key;
428  // This excludes all constants starting with '_' from being shown.
429  if ($this->bType !== 'const' || $depth[0] !== '_') {
430  $goto = substr(md5($depth), 0, 6);
431  $deeper = is_array($arr[$key . '.']) && ($this->tsbrowser_depthKeys[$depth] || $this->ext_expandAllNotes) ? 1 : 0;
432  $PM = is_array($arr[$key . '.']) && !$this->ext_noPMicons ? ($deeper ? 'minus' : 'plus') : 'join';
433  $HTML .= $depthData . '<li><span class="list-tree-group">';
434  if ($PM !== 'join') {
435  $urlParameters = [
436  'id' => $GLOBALS['SOBE']->id,
437  'tsbr[' . $depth . ']' => $deeper ? 0 : 1
438  ];
439  if (GeneralUtility::_GP('breakPointLN')) {
440  $urlParameters['breakPointLN'] = GeneralUtility::_GP('breakPointLN');
441  }
442  $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters) . '#' . $goto;
443  $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>';
444  }
445  $label = $key;
446  // Read only...
447  if (($depth === 'types' || $depth === 'resources' || $depth === 'sitetitle') && $this->bType === 'setup') {
448  $label = '<span style="color: #666666;">' . $label . '</span>';
449  } else {
450  if ($this->linkObjects) {
451  $urlParameters = [
452  'id' => $GLOBALS['SOBE']->id,
453  'sObj' => $depth
454  ];
455  if (GeneralUtility::_GP('breakPointLN')) {
456  $urlParameters['breakPointLN'] = GeneralUtility::_GP('breakPointLN');
457  }
458  $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
459  if ($this->bType !== 'const') {
460  $ln = is_array($arr[$key . '.ln..']) ? 'Defined in: ' . $this->lineNumberToScript($arr[$key . '.ln..']) : 'N/A';
461  } else {
462  $ln = '';
463  }
464  if ($this->tsbrowser_searchKeys[$depth] & 4) {
465  $label = '<strong class="text-danger">' . $label . '</strong>';
466  }
467  // The key has matched the search string
468  $label = '<a href="' . htmlspecialchars($aHref) . '" title="' . htmlspecialchars($ln) . '">' . $label . '</a>';
469  }
470  }
471  $HTML .= '<span class="list-tree-label">[' . $label . ']</span>';
472  if (isset($arr[$key])) {
473  $theValue = $arr[$key];
474  if ($this->fixedLgd) {
475  $imgBlocks = ceil(1 + strlen($depthData) / 77);
476  $lgdChars = 68 - ceil(strlen(('[' . $key . ']')) * 0.8) - $imgBlocks * 3;
477  $theValue = $this->ext_fixed_lgd($theValue, $lgdChars);
478  }
479  // The value has matched the search string
480  if ($this->tsbrowser_searchKeys[$depth] & 2) {
481  $HTML .= ' = <span class="list-tree-value text-danger">' . htmlspecialchars($theValue) . '</span>';
482  } else {
483  $HTML .= ' = <span class="list-tree-value">' . htmlspecialchars($theValue) . '</span>';
484  }
485  if ($this->ext_regComments && isset($arr[$key . '..'])) {
486  $comment = $arr[$key . '..'];
487  // Skip INCLUDE_TYPOSCRIPT comments, they are almost useless
488  if (!preg_match('/### <INCLUDE_TYPOSCRIPT:.*/', $comment)) {
489  // Remove linebreaks, replace with ' '
490  $comment = preg_replace('/[\\r\\n]/', ' ', $comment);
491  // Remove # and * if more than twice in a row
492  $comment = preg_replace('/[#\\*]{2,}/', '', $comment);
493  // Replace leading # (just if it exists) and add it again. Result: Every comment should be prefixed by a '#'.
494  $comment = preg_replace('/^[#\\*\\s]+/', '# ', $comment);
495  // Masking HTML Tags: Replace < with &lt; and > with &gt;
496  $comment = htmlspecialchars($comment);
497  $HTML .= ' <i class="text-muted">' . trim($comment) . '</i>';
498  }
499  }
500  }
501  $HTML .= '</span>';
502  if ($deeper) {
503  $HTML .= $this->ext_getObjTree($arr[$key . '.'], $depth, $depthData, '', $arr[$key], $alphaSort);
504  }
505  }
506  }
507  if ($HTML !== '') {
508  $HTML = '<ul class="list-tree text-monospace">' . $HTML . '</ul>';
509  }
510 
511  return $HTML;
512  }
513 
524  public function lineNumberToScript(array $lnArr)
525  {
526  // On the first call, construct the lnToScript array.
527  if (!is_array($this->lnToScript)) {
528  $this->lnToScript = [];
529 
530  // aggregatedTotalLineCount
531  $c = 0;
532  foreach ($this->hierarchyInfo as $templateNumber => $info) {
533  // hierarchyInfo has the number of lines in configLines, but unfortunately this value
534  // was calculated *before* processing of any INCLUDE instructions
535  // for some yet unknown reason we have to add an extra +2 offset
536  $linecountAfterIncludeProcessing = substr_count($this->config[$templateNumber], LF) + 2;
537  $c += $linecountAfterIncludeProcessing;
538  $this->lnToScript[$c] = $info['title'];
539  }
540  }
541 
542  foreach ($lnArr as $k => $ln) {
543  foreach ($this->lnToScript as $endLn => $title) {
544  if ($endLn >= (int)$ln) {
545  $lnArr[$k] = '"' . $title . '", ' . $ln;
546  break;
547  }
548  }
549  }
550 
551  return implode('; ', $lnArr);
552  }
553 
562  public function ext_getSearchKeys($arr, $depth_in, $searchString, $keyArray)
563  {
564  $keyArr = [];
565  foreach ($arr as $key => $value) {
566  $key = preg_replace('/\\.$/', '', $key);
567  if (substr($key, -1) !== '.') {
568  $keyArr[$key] = 1;
569  }
570  }
571  if ($depth_in) {
572  $depth_in = $depth_in . '.';
573  }
574  $searchPattern = '';
575  if ($this->regexMode) {
576  $searchPattern = '/' . addcslashes($searchString, '/') . '/';
577  $matchResult = @preg_match($searchPattern, '');
578  if ($matchResult === false) {
579  throw new Exception(sprintf('Error evaluating regular expression "%s".', $searchPattern), 1446559458);
580  }
581  }
582  foreach ($keyArr as $key => $value) {
583  $depth = $depth_in . $key;
584  $deeper = is_array($arr[$key . '.']);
585  if ($this->regexMode) {
586  // The value has matched
587  if (preg_match($searchPattern, $arr[$key])) {
588  $this->tsbrowser_searchKeys[$depth] += 2;
589  }
590  // The key has matched
591  if (preg_match($searchPattern, $key)) {
592  $this->tsbrowser_searchKeys[$depth] += 4;
593  }
594  // Just open this subtree if the parent key has matched the search
595  if (preg_match($searchPattern, $depth_in)) {
596  $this->tsbrowser_searchKeys[$depth] = 1;
597  }
598  } else {
599  // The value has matched
600  if (stristr($arr[$key], $searchString)) {
601  $this->tsbrowser_searchKeys[$depth] += 2;
602  }
603  // The key has matches
604  if (stristr($key, $searchString)) {
605  $this->tsbrowser_searchKeys[$depth] += 4;
606  }
607  // Just open this subtree if the parent key has matched the search
608  if (stristr($depth_in, $searchString)) {
609  $this->tsbrowser_searchKeys[$depth] = 1;
610  }
611  }
612  if ($deeper) {
613  $cS = count($this->tsbrowser_searchKeys);
614  $keyArray = $this->ext_getSearchKeys($arr[$key . '.'], $depth, $searchString, $keyArray);
615  if ($cS != count($this->tsbrowser_searchKeys)) {
616  $keyArray[$depth] = 1;
617  }
618  }
619  }
620  return $keyArray;
621  }
622 
627  public function ext_getRootlineNumber($pid)
628  {
629  if ($pid) {
630  foreach ($this->getRootLine() as $key => $val) {
631  if ((int)$val['uid'] === (int)$pid) {
632  return (int)$key;
633  }
634  }
635  }
636  return -1;
637  }
638 
646  public function ext_getTemplateHierarchyArr($arr, $depthData, $keyArray, $first = 0)
647  {
648  $keyArr = [];
649  foreach ($arr as $key => $value) {
650  $key = preg_replace('/\\.$/', '', $key);
651  if (substr($key, -1) !== '.') {
652  $keyArr[$key] = 1;
653  }
654  }
655  $a = 0;
656  $c = count($keyArr);
658  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
659  foreach ($keyArr as $key => $value) {
660  $HTML = '';
661  $a++;
662  $deeper = is_array($arr[$key . '.']);
663  $row = $arr[$key];
664  $LN = $a == $c ? 'blank' : 'line';
665  $BTM = $a == $c ? 'top' : '';
666  $HTML .= $depthData;
667  $alttext = '[' . $row['templateID'] . ']';
668  $alttext .= $row['pid'] ? ' - ' . BackendUtility::getRecordPath($row['pid'], $GLOBALS['SOBE']->perms_clause, 20) : '';
669  $icon = substr($row['templateID'], 0, 3) === 'sys'
670  ? '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIconForRecord('sys_template', $row, Icon::SIZE_SMALL)->render() . '</span>'
671  : '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIcon('mimetypes-x-content-template-static', Icon::SIZE_SMALL)->render() . '</span>';
672  if (in_array($row['templateID'], $this->clearList_const) || in_array($row['templateID'], $this->clearList_setup)) {
673  $urlParameters = [
674  'id' => $GLOBALS['SOBE']->id,
675  'template' => $row['templateID']
676  ];
677  $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
678  $A_B = '<a href="' . htmlspecialchars($aHref) . '">';
679  $A_E = '</a>';
680  if (GeneralUtility::_GP('template') == $row['templateID']) {
681  $A_B = '<strong>' . $A_B;
682  $A_E .= '</strong>';
683  }
684  } else {
685  $A_B = '';
686  $A_E = '';
687  }
688  $HTML .= ($first ? '' : '<span class="treeline-icon treeline-icon-join' . $BTM . '"></span>') . $icon . ' ' . $A_B
689  . htmlspecialchars(GeneralUtility::fixed_lgd_cs($row['title'], $GLOBALS['BE_USER']->uc['titleLen']))
690  . $A_E . '&nbsp;&nbsp;';
691  $RL = $this->ext_getRootlineNumber($row['pid']);
692  $statusCheckedIcon = $iconFactory->getIcon('status-status-checked', Icon::SIZE_SMALL)->render();
693  $keyArray[] = '<tr>
694  <td class="nowrap">' . $HTML . '</td>
695  <td align="center">' . ($row['root'] ? $statusCheckedIcon : '') . '</td>
696  <td align="center">' . ($row['clConf'] ? $statusCheckedIcon : '') . '</td>
697  <td align="center">' . ($row['clConst'] ? $statusCheckedIcon : '') . '</td>
698  <td align="center">' . ($row['pid'] ?: '') . '</td>
699  <td align="center">' . ($RL >= 0 ? $RL : '') . '</td>
700  <td>' . ($row['next'] ? $row['next'] : '') . '</td>
701  </tr>';
702  if ($deeper) {
703  $keyArray = $this->ext_getTemplateHierarchyArr($arr[$key . '.'], $depthData . ($first ? '' : '<span class="treeline-icon treeline-icon-' . $LN . '"></span>'), $keyArray);
704  }
705  }
706  return $keyArray;
707  }
708 
717  public function ext_process_hierarchyInfo(array $depthDataArr, &$pointer)
718  {
719  $parent = $this->hierarchyInfo[$pointer - 1]['templateParent'];
720  while ($pointer > 0 && $this->hierarchyInfo[$pointer - 1]['templateParent'] == $parent) {
721  $pointer--;
722  $row = $this->hierarchyInfo[$pointer];
723  $depthDataArr[$row['templateID']] = $row;
724  unset($this->clearList_setup_temp[$row['templateID']]);
725  unset($this->clearList_const_temp[$row['templateID']]);
726  $this->templateTitles[$row['templateID']] = $row['title'];
727  if ($row['templateID'] == $this->hierarchyInfo[$pointer - 1]['templateParent']) {
728  $depthDataArr[$row['templateID'] . '.'] = $this->ext_process_hierarchyInfo([], $pointer);
729  }
730  }
731  return $depthDataArr;
732  }
733 
745  public function ext_outputTS(
746  array $config,
747  $lineNumbers = false,
748  $comments = false,
749  $crop = false,
750  $syntaxHL = false,
751  $syntaxHLBlockmode = 0
752  ) {
753  $all = '';
754  foreach ($config as $str) {
755  $all .= '[GLOBAL]' . LF . $str;
756  }
757  if ($syntaxHL) {
758  $tsparser = GeneralUtility::makeInstance(Parser\TypoScriptParser::class);
759  $tsparser->lineNumberOffset = $this->ext_lineNumberOffset + 1;
760  $tsparser->parentObject = $this;
761  return $tsparser->doSyntaxHighlight($all, $lineNumbers ? [$this->ext_lineNumberOffset + 1] : '', $syntaxHLBlockmode);
762  }
763  return $this->ext_formatTS($all, $lineNumbers, $comments, $crop);
764  }
765 
775  public function ext_fixed_lgd($string, $chars)
776  {
777  if ($chars >= 4) {
778  if (strlen($string) > $chars) {
779  if (strlen($string) > 24 && preg_match('/^##[a-z0-9]{6}_B##$/', substr($string, 0, 12))) {
780  $string = GeneralUtility::fixed_lgd_cs(substr($string, 12, -12), ($chars - 3));
781  $marker = substr(md5($string), 0, 6);
782  return '##' . $marker . '_B##' . $string . '##' . $marker . '_E##';
783  }
784  return GeneralUtility::fixed_lgd_cs($string, $chars - 3);
785  }
786  }
787  return $string;
788  }
789 
795  public function ext_lnBreakPointWrap($lineNumber, $str)
796  {
797  return '<a href="#" id="line-' . $lineNumber . '" onClick="return brPoint(' . $lineNumber . ','
798  . ($this->ext_lineNumberOffset_mode === 'setup' ? 1 : 0) . ');">' . $str . '</a>';
799  }
800 
808  public function ext_formatTS($input, $ln, $comments = true, $crop = false)
809  {
810  $cArr = explode(LF, $input);
811  $n = ceil(log10(count($cArr) + $this->ext_lineNumberOffset));
812  $lineNum = '';
813  foreach ($cArr as $k => $v) {
814  $lln = $k + $this->ext_lineNumberOffset + 1;
815  if ($ln) {
816  $lineNum = $this->ext_lnBreakPointWrap($lln, str_replace(' ', '&nbsp;', sprintf(('% ' . $n . 'd'), $lln))) . ': ';
817  }
818  $v = htmlspecialchars($v);
819  if ($crop) {
820  $v = $this->ext_fixed_lgd($v, $ln ? 71 : 77);
821  }
822  $cArr[$k] = $lineNum . str_replace(' ', '&nbsp;', $v);
823  $firstChar = substr(trim($v), 0, 1);
824  if ($firstChar === '[') {
825  $cArr[$k] = '<strong class="text-success">' . $cArr[$k] . '</strong>';
826  } elseif ($firstChar === '/' || $firstChar === '#') {
827  if ($comments) {
828  $cArr[$k] = '<span class="text-muted">' . $cArr[$k] . '</span>';
829  } else {
830  unset($cArr[$k]);
831  }
832  }
833  }
834  $output = implode('<br />', $cArr) . '<br />';
835  return $output;
836  }
837 
847  public function ext_getFirstTemplate($pid, $templateUid = 0)
848  {
849  if (empty($pid)) {
850  return null;
851  }
852 
853  // Query is taken from the runThroughTemplates($theRootLine) function in the parent class.
854  $queryBuilder = $this->getTemplateQueryBuilder($pid)
855  ->setMaxResults(1);
856  if ($templateUid) {
857  $queryBuilder->andWhere(
858  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($templateUid, \PDO::PARAM_INT))
859  );
860  }
861  $row = $queryBuilder->execute()->fetch();
862  BackendUtility::workspaceOL('sys_template', $row);
863 
864  return $row;
865  }
866 
873  public function ext_getAllTemplates($pid): array
874  {
875  if (empty($pid)) {
876  return [];
877  }
878  $result = $this->getTemplateQueryBuilder($pid)->execute();
879  $outRes = [];
880  while ($row = $result->fetch()) {
881  BackendUtility::workspaceOL('sys_template', $row);
882  if (is_array($row)) {
883  $outRes[] = $row;
884  }
885  }
886  return $outRes;
887  }
888 
896  protected function getTemplateQueryBuilder(int $pid): QueryBuilder
897  {
898  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
899  ->getQueryBuilderForTable('sys_template');
900  $queryBuilder->getRestrictions()
901  ->removeAll()
902  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
903  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
904 
905  $queryBuilder->select('*')
906  ->from('sys_template')
907  ->where(
908  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))
909  );
910  if (!empty($GLOBALS['TCA']['sys_template']['ctrl']['sortby'])) {
911  $queryBuilder->orderBy($GLOBALS['TCA']['sys_template']['ctrl']['sortby']);
912  }
913 
914  return $queryBuilder;
915  }
916 
924  public function ext_compareFlatSetups($default)
925  {
926  $editableComments = [];
927  $counter = 0;
928  foreach ($this->flatSetup as $const => $value) {
929  if (substr($const, -2) === '..' || !isset($this->flatSetup[$const . '..'])) {
930  continue;
931  }
932  $counter++;
933  $comment = trim($this->flatSetup[$const . '..']);
934  $c_arr = explode(LF, $comment);
935  foreach ($c_arr as $k => $v) {
936  $line = trim(preg_replace('/^[#\\/]*/', '', $v));
937  if (!$line) {
938  continue;
939  }
940  $parts = explode(';', $line);
941  foreach ($parts as $par) {
942  if (strstr($par, '=')) {
943  $keyValPair = explode('=', $par, 2);
944  switch (trim(strtolower($keyValPair[0]))) {
945  case 'type':
946  // Type:
947  $editableComments[$const]['type'] = trim($keyValPair[1]);
948  break;
949  case 'cat':
950  // List of categories.
951  $catSplit = explode('/', strtolower($keyValPair[1]));
952  $catSplit[0] = trim($catSplit[0]);
953  if (isset($this->categoryLabels[$catSplit[0]])) {
954  $catSplit[0] = $this->categoryLabels[$catSplit[0]];
955  }
956  $editableComments[$const]['cat'] = $catSplit[0];
957  // This is the subcategory. Must be a key in $this->subCategories[].
958  // catSplit[2] represents the search-order within the subcat.
959  $catSplit[1] = trim($catSplit[1]);
960  if ($catSplit[1] && isset($this->subCategories[$catSplit[1]])) {
961  $editableComments[$const]['subcat_name'] = $catSplit[1];
962  $orderIdentifier = isset($catSplit[2]) ? trim($catSplit[2]) : $counter;
963  $editableComments[$const]['subcat'] = $this->subCategories[$catSplit[1]][1]
964  . '/' . $catSplit[1] . '/' . $orderIdentifier . 'z';
965  } elseif (isset($catSplit[2])) {
966  $editableComments[$const]['subcat'] = 'x' . '/' . trim($catSplit[2]) . 'z';
967  } else {
968  $editableComments[$const]['subcat'] = 'x' . '/' . $counter . 'z';
969  }
970  break;
971  case 'label':
972  // Label
973  $editableComments[$const]['label'] = trim($keyValPair[1]);
974  break;
975  case 'customcategory':
976  // Custom category label
977  $customCategory = explode('=', $keyValPair[1], 2);
978  if (trim($customCategory[0])) {
979  $categoryKey = strtolower($customCategory[0]);
980  $this->categoryLabels[$categoryKey] = $this->getLanguageService()->sL($customCategory[1]);
981  }
982  break;
983  case 'customsubcategory':
984  // Custom subCategory label
985  $customSubcategory = explode('=', $keyValPair[1], 2);
986  if (trim($customSubcategory[0])) {
987  $subCategoryKey = strtolower($customSubcategory[0]);
988  $this->subCategories[$subCategoryKey][0] = $this->getLanguageService()->sL($customSubcategory[1]);
989  }
990  break;
991  }
992  }
993  }
994  }
995  if (isset($editableComments[$const])) {
996  $editableComments[$const]['name'] = $const;
997  $editableComments[$const]['value'] = trim($value);
998  if (isset($default[$const])) {
999  $editableComments[$const]['default_value'] = trim($default[$const]);
1000  }
1001  }
1002  }
1003  return $editableComments;
1004  }
1005 
1009  public function ext_categorizeEditableConstants($editConstArray)
1010  {
1011  // Runs through the available constants and fills the $this->categories array with pointers and priority-info
1012  foreach ($editConstArray as $constName => $constData) {
1013  if (!$constData['type']) {
1014  $constData['type'] = 'string';
1015  }
1016  $cats = explode(',', $constData['cat']);
1017  // if = only one category, while allows for many. We have agreed on only one category is the most basic way...
1018  foreach ($cats as $theCat) {
1019  $theCat = trim($theCat);
1020  if ($theCat) {
1021  $this->categories[$theCat][$constName] = $constData['subcat'];
1022  }
1023  }
1024  }
1025  }
1026 
1030  public function ext_getCategoryLabelArray()
1031  {
1032  // Returns array used for labels in the menu.
1033  $retArr = [];
1034  foreach ($this->categories as $k => $v) {
1035  if (!empty($v)) {
1036  $retArr[$k] = strtoupper($k) . ' (' . count($v) . ')';
1037  }
1038  }
1039  return $retArr;
1040  }
1041 
1046  public function ext_getTypeData($type)
1047  {
1048  $retArr = [];
1049  $type = trim($type);
1050  if (!$type) {
1051  $retArr['type'] = 'string';
1052  } else {
1053  $m = strcspn($type, ' [');
1054  $retArr['type'] = strtolower(substr($type, 0, $m));
1055  $types = ['int' => 1, 'options' => 1, 'file' => 1, 'boolean' => 1, 'offset' => 1, 'user' => 1];
1056  if (isset($types[$retArr['type']])) {
1057  $p = trim(substr($type, $m));
1058  $reg = [];
1059  preg_match('/\\[(.*)\\]/', $p, $reg);
1060  $p = trim($reg[1]);
1061  if ($p) {
1062  $retArr['paramstr'] = $p;
1063  switch ($retArr['type']) {
1064  case 'int':
1065  if ($retArr['paramstr'][0] === '-') {
1066  $retArr['params'] = GeneralUtility::intExplode('-', substr($retArr['paramstr'], 1));
1067  $retArr['params'][0] = (int)('-' . $retArr['params'][0]);
1068  } else {
1069  $retArr['params'] = GeneralUtility::intExplode('-', $retArr['paramstr']);
1070  }
1071  $retArr['min'] = $retArr['params'][0];
1072  $retArr['max'] = $retArr['params'][1];
1073  $retArr['paramstr'] = $retArr['params'][0] . ' - ' . $retArr['params'][1];
1074  break;
1075  case 'options':
1076  $retArr['params'] = explode(',', $retArr['paramstr']);
1077  break;
1078  }
1079  }
1080  }
1081  }
1082  return $retArr;
1083  }
1084 
1088  public function ext_getTSCE_config($category)
1089  {
1090  $catConf = $this->setup['constants']['TSConstantEditor.'][$category . '.'];
1091  $out = [];
1092  if (is_array($catConf)) {
1093  foreach ($catConf as $key => $val) {
1094  switch ($key) {
1095  case 'description':
1096  case 'bulletlist':
1097  case 'header':
1098  $out[$key] = $val;
1099  break;
1100  default:
1102  $constRefs = explode(',', $val);
1103  foreach ($constRefs as $const) {
1104  $const = trim($const);
1105  if ($const) {
1106  $out['constants'][$const] .= '<span class="label label-danger">' . $key . '</span>';
1107  }
1108  }
1109  }
1110  }
1111  }
1112  }
1113  $this->helpConfig = $out;
1114  }
1115 
1120  public function ext_fNandV($params)
1121  {
1122  $fN = 'data[' . $params['name'] . ']';
1123  $idName = str_replace('.', '-', $params['name']);
1124  $fV = $params['value'];
1125  // Values entered from the constantsedit cannot be constants! 230502; removed \{ and set {
1126  if (preg_match('/^{[\\$][a-zA-Z0-9\\.]*}$/', trim($fV), $reg)) {
1127  $fV = '';
1128  }
1129  $fV = htmlspecialchars($fV);
1130  return [$fN, $fV, $params, $idName];
1131  }
1132 
1140  public function ext_printFields($theConstants, $category)
1141  {
1142  reset($theConstants);
1143  $output = '';
1144  $subcat = '';
1145  if (is_array($this->categories[$category])) {
1146  $help = $this->helpConfig;
1147  if (!$this->doNotSortCategoriesBeforeMakingForm) {
1148  asort($this->categories[$category]);
1149  }
1151  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
1152  foreach ($this->categories[$category] as $name => $type) {
1153  $params = $theConstants[$name];
1154  if (is_array($params)) {
1155  if ($subcat != $params['subcat_name']) {
1156  $subcat = $params['subcat_name'];
1157  $subcat_name = $params['subcat_name'] ? $this->subCategories[$params['subcat_name']][0] : 'Others';
1158  $output .= '<h3>' . $subcat_name . '</h3>';
1159  }
1160  $label = $this->getLanguageService()->sL($params['label']);
1161  $label_parts = explode(':', $label, 2);
1162  if (count($label_parts) === 2) {
1163  $head = trim($label_parts[0]);
1164  $body = trim($label_parts[1]);
1165  } else {
1166  $head = trim($label_parts[0]);
1167  $body = '';
1168  }
1169  $typeDat = $this->ext_getTypeData($params['type']);
1170  $p_field = '';
1171  $raname = substr(md5($params['name']), 0, 10);
1172  $aname = '\'' . $raname . '\'';
1173  list($fN, $fV, $params, $idName) = $this->ext_fNandV($params);
1174  $idName = htmlspecialchars($idName);
1175  $hint = '';
1176  switch ($typeDat['type']) {
1177  case 'int':
1178  case 'int+':
1179  $additionalAttributes = '';
1180  if ($typeDat['paramstr']) {
1181  $hint = ' Range: ' . $typeDat['paramstr'];
1182  } elseif ($typeDat['type'] === 'int+') {
1183  $hint = ' Range: 0 - ';
1184  $typeDat['min'] = 0;
1185  } else {
1186  $hint = ' (Integer)';
1187  }
1188 
1189  if (isset($typeDat['min'])) {
1190  $additionalAttributes .= ' min="' . (int)$typeDat['min'] . '" ';
1191  }
1192  if (isset($typeDat['max'])) {
1193  $additionalAttributes .= ' max="' . (int)$typeDat['max'] . '" ';
1194  }
1195 
1196  $p_field =
1197  '<input class="form-control" id="' . $idName . '" type="number"'
1198  . ' name="' . $fN . '" value="' . $fV . '"' . ' onChange="uFormUrl(' . $aname . ')"' . $additionalAttributes . ' />';
1199  break;
1200  case 'color':
1201  $p_field = '
1202  <input class="form-control formengine-colorpickerelement t3js-color-picker" type="text" id="input-' . $idName . '" rel="' . $idName .
1203  '" name="' . $fN . '" value="' . $fV . '"' . $this->getDocumentTemplate()->formWidth(7) . ' onChange="uFormUrl(' . $aname . ')" />';
1204 
1205  if (empty($this->inlineJavaScript[$typeDat['type']])) {
1206  $this->inlineJavaScript[$typeDat['type']] = 'require([\'TYPO3/CMS/Backend/ColorPicker\'], function(ColorPicker){ColorPicker.initialize()});';
1207  }
1208  break;
1209  case 'wrap':
1210  $wArr = explode('|', $fV);
1211  $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 .= ' | ';
1213  $p_field .= '<input class="form-control" type="text" name="W' . $fN . '" value="' . $wArr[1] . '"' . $this->getDocumentTemplate()->formWidth(15) . ' onChange="uFormUrl(' . $aname . ')" />';
1214  break;
1215  case 'offset':
1216  $wArr = explode(',', $fV);
1217  $labels = GeneralUtility::trimExplode(',', $typeDat['paramstr']);
1218  $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 .= ' , ';
1220  $p_field .= ($labels[1] ? $labels[1] : 'y') . ':<input type="text" name="W' . $fN . '" value="' . $wArr[1] . '"' . $this->getDocumentTemplate()->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1221  $labelsCount = count($labels);
1222  for ($aa = 2; $aa < $labelsCount; $aa++) {
1223  if ($labels[$aa]) {
1224  $p_field .= ' , ' . $labels[$aa] . ':<input type="text" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '"' . $this->getDocumentTemplate()->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1225  } else {
1226  $p_field .= '<input type="hidden" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '" />';
1227  }
1228  }
1229  break;
1230  case 'options':
1231  if (is_array($typeDat['params'])) {
1232  $p_field = '';
1233  foreach ($typeDat['params'] as $val) {
1234  $vParts = explode('=', $val, 2);
1235  $label = $vParts[0];
1236  $val = isset($vParts[1]) ? $vParts[1] : $vParts[0];
1237  // option tag:
1238  $sel = '';
1239  if ($val === $params['value']) {
1240  $sel = ' selected';
1241  }
1242  $p_field .= '<option value="' . htmlspecialchars($val) . '"' . $sel . '>' . $this->getLanguageService()->sL($label) . '</option>';
1243  }
1244  $p_field = '<select class="form-control" id="' . $idName . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1245  }
1246  break;
1247  case 'boolean':
1248  $sel = $fV ? 'checked' : '';
1249  $p_field =
1250  '<input type="hidden" name="' . $fN . '" value="0" />'
1251  . '<label class="btn btn-default btn-checkbox">'
1252  . '<input id="' . $idName . '" type="checkbox" name="' . $fN . '" value="' . ($typeDat['paramstr'] ? $typeDat['paramstr'] : 1) . '" ' . $sel . ' onClick="uFormUrl(' . $aname . ')" />'
1253  . '<span class="t3-icon fa"></span>'
1254  . '</label>';
1255  break;
1256  case 'comment':
1257  $sel = $fV ? 'checked' : '';
1258  $p_field =
1259  '<input type="hidden" name="' . $fN . '" value="#" />'
1260  . '<label class="btn btn-default btn-checkbox">'
1261  . '<input id="' . $idName . '" type="checkbox" name="' . $fN . '" value="" ' . $sel . ' onClick="uFormUrl(' . $aname . ')" />'
1262  . '<span class="t3-icon fa"></span>'
1263  . '</label>';
1264  break;
1265  case 'file':
1266  // extensionlist
1267  $extList = $typeDat['paramstr'];
1268  if ($extList === 'IMAGE_EXT') {
1269  $extList = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
1270  }
1271  $p_field = '<option value="">(' . $extList . ')</option>';
1272  if (trim($params['value'])) {
1273  $val = $params['value'];
1274  $p_field .= '<option value=""></option>';
1275  $p_field .= '<option value="' . htmlspecialchars($val) . '" selected>' . $val . '</option>';
1276  }
1277  $p_field = '<select class="form-select" id="' . $idName . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1278  break;
1279  case 'user':
1280  $userFunction = $typeDat['paramstr'];
1281  $userFunctionParams = ['fieldName' => $fN, 'fieldValue' => $fV];
1282  $p_field = GeneralUtility::callUserFunction($userFunction, $userFunctionParams, $this);
1283  break;
1284  default:
1285  $p_field = '<input class="form-control" id="' . $idName . '" type="text" name="' . $fN . '" value="' . $fV . '"'
1286  . ' onChange="uFormUrl(' . $aname . ')" />';
1287  }
1288  // Define default names and IDs
1289  $userTyposcriptID = 'userTS-' . $idName;
1290  $defaultTyposcriptID = 'defaultTS-' . $idName;
1291  $checkboxName = 'check[' . $params['name'] . ']';
1292  $checkboxID = 'check-' . $idName;
1293  $userTyposcriptStyle = '';
1294  $deleteIconHTML = '';
1295  $constantCheckbox = '';
1296  $constantDefaultRow = '';
1297  if (!$this->ext_dontCheckIssetValues) {
1298  // Set the default styling options
1299  if (isset($this->objReg[$params['name']])) {
1300  $checkboxValue = 'checked';
1301  $defaultTyposcriptStyle = 'style="display:none;"';
1302  } else {
1303  $checkboxValue = '';
1304  $userTyposcriptStyle = 'style="display:none;"';
1305  $defaultTyposcriptStyle = '';
1306  }
1307  $deleteTitle = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.deleteTitle'));
1308  $deleteIcon = $iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL)->render();
1309  $deleteIconHTML =
1310  '<button type="button" class="btn btn-default t3js-toggle" data-toggle="undo" rel="' . $idName . '">'
1311  . '<span title="' . $deleteTitle . '" alt="' . $deleteTitle . '">'
1312  . $deleteIcon
1313  . '</span>'
1314  . '</button>';
1315  $editTitle = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.editTitle'));
1316  $editIcon = $iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render();
1317  $editIconHTML =
1318  '<button type="button" class="btn btn-default t3js-toggle" data-toggle="edit" rel="' . $idName . '">'
1319  . '<span title="' . $editTitle . '" alt="' . $editTitle . '">'
1320  . $editIcon
1321  . '</span>'
1322  . '</button>';
1323  $constantCheckbox = '<input type="hidden" name="' . $checkboxName . '" id="' . $checkboxID . '" value="' . $checkboxValue . '"/>';
1324  // If there's no default value for the field, use a static label.
1325  if (!$params['default_value']) {
1326  $params['default_value'] = '[Empty]';
1327  }
1328  $constantDefaultRow =
1329  '<div class="input-group defaultTS" id="' . $defaultTyposcriptID . '" ' . $defaultTyposcriptStyle . '>'
1330  . '<span class="input-group-btn">' . $editIconHTML . '</span>'
1331  . '<input class="form-control" type="text" placeholder="' . htmlspecialchars($params['default_value']) . '" readonly>'
1332  . '</div>';
1333  }
1334  $constantEditRow =
1335  '<div class="input-group userTS" id="' . $userTyposcriptID . '" ' . $userTyposcriptStyle . '>'
1336  . '<span class="input-group-btn">' . $deleteIconHTML . '</span>'
1337  . $p_field
1338  . '</div>';
1339  $constantLabel = '<label class="t3js-formengine-label"><span>' . htmlspecialchars($head) . '</span></label>';
1340  $constantName = '<span class="help-block">[' . $params['name'] . ']</span>';
1341  $constantDescription = $body ? '<p class="help-block">' . htmlspecialchars($body) . '</p>' : '';
1342  $constantData = '';
1343  if ($hint !== '') {
1344  $constantData .= '<span class="help-block">' . $hint . '</span>';
1345  }
1346  $constantData .=
1347  $constantCheckbox
1348  . $constantEditRow
1349  . $constantDefaultRow;
1350 
1351  $output .=
1352  '<fieldset class="form-section">'
1353  . '<a name="' . $raname . '"></a>' . $help['constants'][$params['name']]
1354  . '<div class="form-group">'
1355  . $constantLabel . $constantName . $constantDescription . $constantData
1356  . '</div>'
1357  . '</fieldset>';
1358  } else {
1359  debug('Error. Constant did not exist. Should not happen.');
1360  }
1361  }
1362  }
1363  return '<div class="tstemplate-constanteditor">' . $output . '</div>';
1364  }
1365 
1366  /***************************
1367  *
1368  * Processing input values
1369  *
1370  ***************************/
1375  {
1376  // This runs through the lines of the constants-field of the active template and registers the constants-names
1377  // and line positions in an array, $this->objReg
1378  $this->raw = explode(LF, $constants);
1379  $this->rawP = 0;
1380  // Resetting the objReg if the divider is found!!
1381  $this->objReg = [];
1382  $this->ext_regObjects('');
1383  }
1384 
1388  public function ext_regObjects($pre)
1389  {
1390  // Works with regObjectPositions. "expands" the names of the TypoScript objects
1391  while (isset($this->raw[$this->rawP])) {
1392  $line = ltrim($this->raw[$this->rawP]);
1393  if (strstr($line, $this->edit_divider)) {
1394  // Resetting the objReg if the divider is found!!
1395  $this->objReg = [];
1396  }
1397  $this->rawP++;
1398  if ($line) {
1399  if ($line[0] === '[') {
1400  } elseif (strcspn($line, '}#/') != 0) {
1401  $varL = strcspn($line, ' {=<');
1402  $var = substr($line, 0, $varL);
1403  $line = ltrim(substr($line, $varL));
1404  switch ($line[0]) {
1405  case '=':
1406  $this->objReg[$pre . $var] = $this->rawP - 1;
1407  break;
1408  case '{':
1409  $this->ext_inBrace++;
1410  $this->ext_regObjects($pre . $var . '.');
1411  break;
1412  }
1413  $this->lastComment = '';
1414  } elseif ($line[0] === '}') {
1415  $this->lastComment = '';
1416  $this->ext_inBrace--;
1417  if ($this->ext_inBrace < 0) {
1418  $this->ext_inBrace = 0;
1419  } else {
1420  break;
1421  }
1422  }
1423  }
1424  }
1425  }
1426 
1431  public function ext_putValueInConf($key, $var)
1432  {
1433  // Puts the value $var to the TypoScript value $key in the current lines of the templates.
1434  // If the $key is not found in the template constants field, a new line is inserted in the bottom.
1435  $theValue = ' ' . trim($var);
1436  if (isset($this->objReg[$key])) {
1437  $lineNum = $this->objReg[$key];
1438  $parts = explode('=', $this->raw[$lineNum], 2);
1439  if (count($parts) === 2) {
1440  $parts[1] = $theValue;
1441  }
1442  $this->raw[$lineNum] = implode('=', $parts);
1443  } else {
1444  $this->raw[] = $key . ' =' . $theValue;
1445  }
1446  $this->changed = true;
1447  }
1448 
1452  public function ext_removeValueInConf($key)
1453  {
1454  // Removes the value in the configuration
1455  if (isset($this->objReg[$key])) {
1456  $lineNum = $this->objReg[$key];
1457  unset($this->raw[$lineNum]);
1458  }
1459  $this->changed = true;
1460  }
1461 
1467  public function ext_depthKeys($arr, $settings)
1468  {
1469  $tsbrArray = [];
1470  foreach ($arr as $theK => $theV) {
1471  $theKeyParts = explode('.', $theK);
1472  $depth = '';
1473  $c = count($theKeyParts);
1474  $a = 0;
1475  foreach ($theKeyParts as $p) {
1476  $a++;
1477  $depth .= ($depth ? '.' : '') . $p;
1478  $tsbrArray[$depth] = $c == $a ? $theV : 1;
1479  }
1480  }
1481  // Modify settings
1482  foreach ($tsbrArray as $theK => $theV) {
1483  if ($theV) {
1484  $settings[$theK] = 1;
1485  } else {
1486  unset($settings[$theK]);
1487  }
1488  }
1489  return $settings;
1490  }
1491 
1500  public function ext_procesInput($http_post_vars, $http_post_files, $theConstants, $tplRow)
1501  {
1502  $data = $http_post_vars['data'];
1503  $check = $http_post_vars['check'];
1504  $Wdata = $http_post_vars['Wdata'];
1505  $W2data = $http_post_vars['W2data'];
1506  $W3data = $http_post_vars['W3data'];
1507  $W4data = $http_post_vars['W4data'];
1508  $W5data = $http_post_vars['W5data'];
1509  if (is_array($data)) {
1510  foreach ($data as $key => $var) {
1511  if (isset($theConstants[$key])) {
1512  // If checkbox is set, update the value
1513  if ($this->ext_dontCheckIssetValues || isset($check[$key])) {
1514  // Exploding with linebreak, just to make sure that no multiline input is given!
1515  list($var) = explode(LF, $var);
1516  $typeDat = $this->ext_getTypeData($theConstants[$key]['type']);
1517  switch ($typeDat['type']) {
1518  case 'int':
1519  if ($typeDat['paramstr']) {
1520  $var = MathUtility::forceIntegerInRange($var, $typeDat['params'][0], $typeDat['params'][1]);
1521  } else {
1522  $var = (int)$var;
1523  }
1524  break;
1525  case 'int+':
1526  $var = max(0, (int)$var);
1527  break;
1528  case 'color':
1529  $col = [];
1530  if ($var) {
1531  $var = preg_replace('/[^A-Fa-f0-9]*/', '', $var);
1532  $useFulHex = strlen($var) > 3;
1533  $col[] = hexdec($var[0]);
1534  $col[] = hexdec($var[1]);
1535  $col[] = hexdec($var[2]);
1536  if ($useFulHex) {
1537  $col[] = hexdec($var[3]);
1538  $col[] = hexdec($var[4]);
1539  $col[] = hexdec($var[5]);
1540  }
1541  $var = substr(('0' . dechex($col[0])), -1) . substr(('0' . dechex($col[1])), -1) . substr(('0' . dechex($col[2])), -1);
1542  if ($useFulHex) {
1543  $var .= substr(('0' . dechex($col[3])), -1) . substr(('0' . dechex($col[4])), -1) . substr(('0' . dechex($col[5])), -1);
1544  }
1545  $var = '#' . strtoupper($var);
1546  }
1547  break;
1548  case 'comment':
1549  if ($var) {
1550  $var = '#';
1551  } else {
1552  $var = '';
1553  }
1554  break;
1555  case 'wrap':
1556  if (isset($Wdata[$key])) {
1557  $var .= '|' . $Wdata[$key];
1558  }
1559  break;
1560  case 'offset':
1561  if (isset($Wdata[$key])) {
1562  $var = (int)$var . ',' . (int)$Wdata[$key];
1563  if (isset($W2data[$key])) {
1564  $var .= ',' . (int)$W2data[$key];
1565  if (isset($W3data[$key])) {
1566  $var .= ',' . (int)$W3data[$key];
1567  if (isset($W4data[$key])) {
1568  $var .= ',' . (int)$W4data[$key];
1569  if (isset($W5data[$key])) {
1570  $var .= ',' . (int)$W5data[$key];
1571  }
1572  }
1573  }
1574  }
1575  }
1576  break;
1577  case 'boolean':
1578  if ($var) {
1579  $var = $typeDat['paramstr'] ? $typeDat['paramstr'] : 1;
1580  }
1581  break;
1582  }
1583  if ($this->ext_printAll || (string)$theConstants[$key]['value'] !== (string)$var) {
1584  // Put value in, if changed.
1585  $this->ext_putValueInConf($key, $var);
1586  }
1587  // Remove the entry because it has been "used"
1588  unset($check[$key]);
1589  } else {
1590  $this->ext_removeValueInConf($key);
1591  }
1592  }
1593  }
1594  }
1595  // Remaining keys in $check indicates fields that are just clicked "on" to be edited.
1596  // Therefore we get the default value and puts that in the template as a start...
1597  if (!$this->ext_dontCheckIssetValues && is_array($check)) {
1598  foreach ($check as $key => $var) {
1599  if (isset($theConstants[$key])) {
1600  $dValue = $theConstants[$key]['default_value'];
1601  $this->ext_putValueInConf($key, $dValue);
1602  }
1603  }
1604  }
1605  }
1606 
1612  public function ext_prevPageWithTemplate($id, $perms_clause)
1613  {
1614  $rootLine = BackendUtility::BEgetRootLine($id, $perms_clause ? ' AND ' . $perms_clause : '');
1615  foreach ($rootLine as $p) {
1616  if ($this->ext_getFirstTemplate($p['uid'])) {
1617  return $p;
1618  }
1619  }
1620  return [];
1621  }
1622 
1628  protected function getRootLine()
1629  {
1630  return is_array($this->absoluteRootLine) ? $this->absoluteRootLine : [];
1631  }
1632 
1636  protected function getLanguageService()
1637  {
1638  return $GLOBALS['LANG'];
1639  }
1640 
1644  protected function getDocumentTemplate()
1645  {
1646  return $GLOBALS['TBE_TEMPLATE'];
1647  }
1648 }
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel='E_DEBUG')
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
ext_formatTS($input, $ln, $comments=true, $crop=false)
static callUserFunction($funcName, &$params, &$ref, $_='', $errorMode=0)
ext_getObjTree($arr, $depth_in, $depthData, $parentType='', $parentValue='', $alphaSort='0')
static BEgetRootLine($uid, $clause='', $workspaceOL=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
static makeInstance($className,... $constructorArguments)
ext_outputTS(array $config, $lineNumbers=false, $comments=false, $crop=false, $syntaxHL=false, $syntaxHLBlockmode=0)
ext_procesInput($http_post_vars, $http_post_files, $theConstants, $tplRow)
static fixed_lgd_cs($string, $chars, $appendString='...')
ext_getSearchKeys($arr, $depth_in, $searchString, $keyArray)
static getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']