‪TYPO3CMS  9.5
DocumentTemplate.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Psr\Log\LoggerAwareInterface;
18 use Psr\Log\LoggerAwareTrait;
33 
47 class ‪DocumentTemplate implements LoggerAwareInterface
48 {
49  use LoggerAwareTrait;
51 
55  protected ‪$deprecatedPublicProperties = [
56  'hasDocheader' => 'Using $hasDocheader of class DocumentTemplate is discouraged. The property is not evaluated in the TYPO3 core anymore and will be removed in TYPO3 v10.0.'
57  ];
58 
59  // Vars you typically might want to/should set from outside after making instance of this class:
66  public ‪$form = '';
67 
73  public ‪$JScode = '';
74 
80  public ‪$JScodeArray = ['jumpToUrl' => '
81 function jumpToUrl(URL) {
82  window.location.href = URL;
83  return false;
84 }
85  '];
86 
92  public ‪$postCode = '';
93 
99  public ‪$moduleTemplate = '';
100 
106  protected ‪$moduleTemplateFilename = '';
107 
113  public ‪$scriptID = '';
114 
120  public ‪$bodyTagId = '';
121 
127  public ‪$bodyTagAdditions = '';
128 
135  public ‪$inDocStylesArray = [];
136 
142  public ‪$styleSheetFile = '';
143 
149  public ‪$styleSheetFile2 = '';
150 
156  public ‪$styleSheetFile_post = '';
157 
163  protected ‪$useCompatibilityTag = false;
164 
170  protected ‪$xUaCompatibilityVersion = 'IE=edge';
171 
172  // Skinning
178  protected ‪$stylesheetsSkins = [
179  'structure' => 'Resources/Public/Css/structure/',
180  'visual' => 'Resources/Public/Css/visual/'
181  ];
182 
188  protected ‪$jsFiles = [];
189 
195  protected ‪$jsFilesNoConcatenation = [];
196 
203  public ‪$sectionFlag = 0;
204 
210  public ‪$divClass = '';
211 
215  public ‪$pageHeaderBlock = '';
216 
220  public ‪$endOfPageJsBlock = '';
221 
226  protected ‪$hasDocheader = true;
227 
231  protected ‪$pageRenderer;
232 
238  protected ‪$pageHeaderFooterTemplateFile = '';
239 
245  public ‪$showFlashMessages = true;
246 
250  protected ‪$iconFactory;
251 
255  protected ‪$templateService;
256 
260  public function ‪__construct()
261  {
262  // Initializes the page rendering object:
263  $this->‪initPageRenderer();
264 
265  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
266 
267  // initialize Marker Support
268  $this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
269 
270  // Setting default scriptID, trim forward slash from route
271  $this->scriptID = ltrim(GeneralUtility::_GET('route'), '/');
272  $this->bodyTagId = preg_replace('/[^A-Za-z0-9-]/', '-', $this->scriptID);
273  // Individual configuration per script? If so, make a recursive merge of the arrays:
274  if (is_array(‪$GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID] ?? false)) {
275  // Make copy
276  $ovr = ‪$GLOBALS['TBE_STYLES']['scriptIDindex'][‪$this->scriptID];
277  // merge styles.
279  // Have to unset - otherwise the second instantiation will do it again!
280  unset(‪$GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID]);
281  }
282  // Main Stylesheets:
283  if (!empty(‪$GLOBALS['TBE_STYLES']['stylesheet'])) {
284  $this->styleSheetFile = ‪$GLOBALS['TBE_STYLES']['stylesheet'];
285  }
286  if (!empty(‪$GLOBALS['TBE_STYLES']['stylesheet2'])) {
287  $this->styleSheetFile2 = ‪$GLOBALS['TBE_STYLES']['stylesheet2'];
288  }
289  if (!empty(‪$GLOBALS['TBE_STYLES']['styleSheetFile_post'])) {
290  $this->styleSheetFile_post = ‪$GLOBALS['TBE_STYLES']['styleSheetFile_post'];
291  }
292  if (!empty(‪$GLOBALS['TBE_STYLES']['inDocStyles_TBEstyle'])) {
293  $this->inDocStylesArray['TBEstyle'] = ‪$GLOBALS['TBE_STYLES']['inDocStyles_TBEstyle'];
294  }
295  // include all stylesheets
296  foreach ($this->‪getSkinStylesheetDirectories() as $stylesheetDirectory) {
297  $this->‪addStyleSheetDirectory($stylesheetDirectory);
298  }
299  }
300 
304  protected function ‪initPageRenderer()
305  {
306  if ($this->pageRenderer !== null) {
307  return;
308  }
309  $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
310  $this->pageRenderer->setLanguage(‪$GLOBALS['LANG']->lang);
311  $this->pageRenderer->enableConcatenateCss();
312  $this->pageRenderer->enableConcatenateJavascript();
313  $this->pageRenderer->enableCompressCss();
314  $this->pageRenderer->enableCompressJavascript();
315  // Add all JavaScript files defined in $this->jsFiles to the PageRenderer
316  foreach ($this->jsFilesNoConcatenation as $file) {
317  $this->pageRenderer->addJsFile(
318  $file,
319  'text/javascript',
320  true,
321  false,
322  '',
323  true
324  );
325  }
326  // Add all JavaScript files defined in $this->jsFiles to the PageRenderer
327  foreach ($this->jsFiles as $file) {
328  $this->pageRenderer->addJsFile($file);
329  }
330  if ((int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] === 1) {
331  $this->pageRenderer->enableDebugMode();
332  }
333  }
334 
335  /*****************************************
336  *
337  * EVALUATION FUNCTIONS
338  * Various centralized processing
339  *
340  *****************************************/
341 
352  public function ‪makeShortcutIcon($gvList, $setList, $modName, $motherModName = '', $classes = '')
353  {
354  $gvList = 'route,' . $gvList;
355  $storeUrl = $this->‪makeShortcutUrl($gvList, $setList);
356  $pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
357  // Fallback for alt_mod. We still pass in the old xMOD... stuff, but TBE_MODULES only knows about "record_edit".
358  // We still need to pass the xMOD name to createShortcut below, since this is used for icons.
359  $moduleName = $modName === 'xMOD_alt_doc.php' ? 'record_edit' : $modName;
360  // Add the module identifier automatically if typo3/index.php is used:
361  if (GeneralUtility::_GET('M') !== null) {
362  $storeUrl = '&M=' . $moduleName . $storeUrl;
363  }
364  if ((int)$motherModName === 1) {
365  $motherModule = 'top.currentModuleLoaded';
366  } elseif ($motherModName) {
367  $motherModule = GeneralUtility::quoteJSvalue($motherModName);
368  } else {
369  $motherModule = '\'\'';
370  }
371  $confirmationText = GeneralUtility::quoteJSvalue(‪$GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.makeBookmark'));
372 
373  $shortcutUrl = $pathInfo['path'] . '?' . $storeUrl;
374  $shortcutRepository = GeneralUtility::makeInstance(ShortcutRepository::class);
375  $shortcutExist = $shortcutRepository->shortcutExists($shortcutUrl);
376 
377  if ($shortcutExist) {
378  return '<a class="active ' . htmlspecialchars($classes) . '" title="">' .
379  $this->iconFactory->getIcon('actions-system-shortcut-active', ‪Icon::SIZE_SMALL)->render() . '</a>';
380  }
381  $url = GeneralUtility::quoteJSvalue(rawurlencode($shortcutUrl));
382  $onClick = 'top.TYPO3.ShortcutMenu.createShortcut(' . GeneralUtility::quoteJSvalue(rawurlencode($modName)) .
383  ', ' . $url . ', ' . $confirmationText . ', ' . $motherModule . ', this);return false;';
384 
385  return '<a href="#" class="' . htmlspecialchars($classes) . '" onclick="' . htmlspecialchars($onClick) . '" title="' .
386  htmlspecialchars(‪$GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.makeBookmark')) . '">' .
387  $this->iconFactory->getIcon('actions-system-shortcut-new', ‪Icon::SIZE_SMALL)->render() . '</a>';
388  }
389 
400  public function ‪makeShortcutUrl($gvList, $setList)
401  {
402  $GET = GeneralUtility::_GET();
403  $storeArray = array_merge(
404  GeneralUtility::compileSelectedGetVarsFromArray($gvList, $GET),
405  ['SET' => GeneralUtility::compileSelectedGetVarsFromArray($setList, (array)‪$GLOBALS['SOBE']->MOD_SETTINGS)]
406  );
407  return ‪HttpUtility::buildQueryString($storeArray, '&');
408  }
409 
421  public function ‪formWidth($size = 48, $textarea = false, $styleOverride = '')
422  {
423  trigger_error('DocumentTemplate->formWidth() will be removed in TYPO3 10.0 - use responsive code or direct inline styles to format your input fields instead.', E_USER_DEPRECATED);
424  return ' style="' . ($styleOverride ?: 'width:' . ceil($size * 9.58) . 'px;') . '"';
425  }
426 
435  public function ‪redirectUrls($thisLocation = '')
436  {
437  $thisLocation = $thisLocation ? $thisLocation : GeneralUtility::linkThisScript([
438  'CB' => '',
439  'SET' => '',
440  'cmd' => '',
441  'popViewId' => ''
442  ]);
443  $out = '
444  var T3_RETURN_URL = ' . GeneralUtility::quoteJSvalue(str_replace('%20', '', rawurlencode(GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'))))) . ';
445  var T3_THIS_LOCATION = ' . GeneralUtility::quoteJSvalue(str_replace('%20', '', rawurlencode($thisLocation))) . '
446  ';
447  return $out;
448  }
449 
455  public function ‪useCompatibilityTag(‪$useCompatibilityTag = true)
456  {
458  }
459 
460  /*****************************************
461  *
462  * PAGE BUILDING FUNCTIONS.
463  * Use this to build the HTML of your backend modules
464  *
465  *****************************************/
474  public function ‪startPage($title)
475  {
476  // hook pre start page
477  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'] ?? [] as $hookFunction) {
478  $hookParameters = [
479  'title' => &$title
480  ];
481  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
482  }
483  // alternative template for Header and Footer
484  if ($this->pageHeaderFooterTemplateFile) {
485  $file = GeneralUtility::getFileAbsFileName($this->pageHeaderFooterTemplateFile);
486  if ($file) {
487  $this->pageRenderer->setTemplateFile($file);
488  }
489  }
490 
491  // Disable rendering of XHTML tags
492  $this->pageRenderer->setRenderXhtml(false);
493 
494  $languageCode = $this->pageRenderer->getLanguage() === 'default' ? 'en' : $this->pageRenderer->getLanguage();
495  $this->pageRenderer->setHtmlTag('<html lang="' . $languageCode . '">');
496 
497  $headerStart = '<!DOCTYPE html>';
498  $this->pageRenderer->setXmlPrologAndDocType($headerStart);
499  $this->pageRenderer->setHeadTag('<head>' . LF . '<!-- TYPO3 Script ID: ' . htmlspecialchars($this->scriptID) . ' -->');
500  header('Content-Type:text/html;charset=utf-8');
501  $this->pageRenderer->setCharSet('utf-8');
502  $this->pageRenderer->setMetaTag('name', 'generator', $this->‪generator());
503  $this->pageRenderer->setMetaTag('name', 'robots', 'noindex,follow');
504  $this->pageRenderer->setMetaTag('name', 'viewport', 'width=device-width, initial-scale=1');
505  $this->pageRenderer->setFavIcon($this->‪getBackendFavicon());
506  if ($this->‪useCompatibilityTag) {
507  $this->pageRenderer->setMetaTag('http-equiv', 'X-UA-Compatible', $this->xUaCompatibilityVersion);
508  }
509  $this->pageRenderer->setTitle($title);
510  // add docstyles
511  $this->‪docStyle();
512  $this->pageRenderer->addHeaderData($this->JScode);
513  foreach ($this->JScodeArray as $name => $code) {
514  $this->pageRenderer->addJsInlineCode($name, $code, false);
515  }
516 
517  // Note: please do not reference "bootstrap" outside of the TYPO3 Core (not in your own extensions)
518  // as this is preliminary as long as Twitter bootstrap does not support AMD modules
519  // this logic will be changed once Twitter bootstrap 4 is included
520  // @todo
521  $this->pageRenderer->addJsFile('EXT:core/Resources/Public/JavaScript/Contrib/bootstrap/bootstrap.js');
522 
523  // csh manual require js module & moduleUrl
524  if (TYPO3_MODE === 'BE' && $this->‪getBackendUser() && !empty($this->‪getBackendUser()->user)) {
525  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
526  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
527  $this->pageRenderer->addInlineSetting(
528  'ContextHelp',
529  'moduleUrl',
530  (string)$uriBuilder->buildUriFromRoute('help_cshmanual', ['action' => 'detail'])
531  );
532  }
533 
534  // hook for additional headerData
535  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'] ?? [] as $hookFunction) {
536  $hookParameters = [
537  'pageRenderer' => &‪$this->pageRenderer
538  ];
539  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
540  }
541  // Construct page header.
542  $str = $this->pageRenderer->render(‪PageRenderer::PART_HEADER);
543  $this->JScode = '';
544  $this->JScodeArray = [];
545  $this->endOfPageJsBlock = $this->pageRenderer->render(‪PageRenderer::PART_FOOTER);
546  $str .= $this->‪docBodyTagBegin() . ($this->divClass ? '
547 
548 <!-- Wrapping DIV-section for whole page BEGIN -->
549 <div class="' . $this->divClass . '">
550 ' : '') . trim($this->form);
551  return $str;
552  }
553 
560  public function ‪endPage()
561  {
562  $str = $this->postCode . GeneralUtility::wrapJS(‪BackendUtility::getUpdateSignalCode()) . ($this->form ? '
563 </form>' : '');
564  // If something is in buffer like debug, put it to end of page
565  if (ob_get_contents()) {
566  $str .= ob_get_clean();
567  if (!headers_sent()) {
568  header('Content-Encoding: None');
569  }
570  }
571  $str .= ($this->divClass ? '
572 
573 <!-- Wrapping DIV-section for whole page END -->
574 </div>' : '') . $this->endOfPageJsBlock;
575 
576  // Logging: Can't find better place to put it:
577  $this->logger->debug('END of BACKEND session', ['_FLUSH' => true]);
578  return $str;
579  }
580 
588  public function ‪render($title, $content)
589  {
590  $pageContent = $this->‪startPage($title);
591  $pageContent .= $content;
592  $pageContent .= $this->‪endPage();
593  return $this->‪insertStylesAndJS($pageContent);
594  }
595 
602  public function ‪docBodyTagBegin()
603  {
604  return '<body ' . trim($this->bodyTagAdditions . ($this->bodyTagId ? ' id="' . $this->bodyTagId . '"' : '')) . '>';
605  }
606 
610  public function ‪docStyle()
611  {
612  // Implode it all:
613  $inDocStyles = implode(LF, $this->inDocStylesArray);
614 
615  // Reset styles so they won't be added again in insertStylesAndJS()
616  $this->inDocStylesArray = [];
617 
618  if ($this->styleSheetFile) {
619  $this->pageRenderer->addCssFile($this->styleSheetFile);
620  }
621  if ($this->styleSheetFile2) {
622  $this->pageRenderer->addCssFile($this->styleSheetFile2);
623  }
624 
625  if ($inDocStyles !== '') {
626  $this->pageRenderer->addCssInlineBlock('inDocStyles', $inDocStyles . LF . '/*###POSTCSSMARKER###*/');
627  }
628 
629  if ($this->styleSheetFile_post) {
630  $this->pageRenderer->addCssFile($this->styleSheetFile_post);
631  }
632  }
633 
644  public function ‪addStyleSheet($key, $href, $title = '', $relation = 'stylesheet')
645  {
646  trigger_error('DocumentTemplate->->addStyleSheet() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
647  $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
648  }
649 
655  public function ‪addStyleSheetDirectory($path)
656  {
657  $path = GeneralUtility::getFileAbsFileName($path);
658  // Read all files in directory and sort them alphabetically
659  $cssFiles = GeneralUtility::getFilesInDir($path, 'css');
660  foreach ($cssFiles as $cssFile) {
661  $this->pageRenderer->addCssFile(‪PathUtility::getRelativePathTo($path) . $cssFile);
662  }
663  }
664 
672  public function ‪insertStylesAndJS($content)
673  {
674  $styles = LF . implode(LF, $this->inDocStylesArray);
675  $content = str_replace('/*###POSTCSSMARKER###*/', $styles, $content);
676 
677  // Insert accumulated JS
678  $jscode = $this->JScode . LF . GeneralUtility::wrapJS(implode(LF, $this->JScodeArray));
679  $content = str_replace('<!--###POSTJSMARKER###-->', $jscode, $content);
680  return $content;
681  }
682 
688  public function ‪getSkinStylesheetDirectories()
689  {
690  $stylesheetDirectories = [];
691  // Stylesheets from skins
692  // merge default css directories ($this->stylesheetsSkin) with additional ones and include them
693  if (is_array(‪$GLOBALS['TBE_STYLES']['skins'])) {
694  // loop over all registered skins
695  foreach (‪$GLOBALS['TBE_STYLES']['skins'] as $skinExtKey => $skin) {
696  $skinStylesheetDirs = ‪$this->stylesheetsSkins;
697  // Skins can add custom stylesheetDirectories using
698  // $GLOBALS['TBE_STYLES']['skins'][$_EXTKEY]['stylesheetDirectories']
699  if (is_array($skin['stylesheetDirectories'])) {
700  $skinStylesheetDirs = array_merge($skinStylesheetDirs, $skin['stylesheetDirectories']);
701  }
702  // Add all registered directories
703  foreach ($skinStylesheetDirs as $stylesheetDir) {
704  // for EXT:myskin/stylesheets/ syntax
705  if (strpos($stylesheetDir, 'EXT:') === 0) {
706  list($extKey, $path) = explode('/', substr($stylesheetDir, 4), 2);
707  if (!empty($extKey) && ‪ExtensionManagementUtility::isLoaded($extKey) && !empty($path)) {
708  $stylesheetDirectories[] = ‪ExtensionManagementUtility::extPath($extKey) . $path;
709  }
710  } else {
711  // For relative paths
712  $stylesheetDirectories[] = ‪ExtensionManagementUtility::extPath($skinExtKey) . $stylesheetDir;
713  }
714  }
715  }
716  }
717  return $stylesheetDirectories;
718  }
719 
725  public function ‪generator()
726  {
727  return 'TYPO3 CMS, ' . TYPO3_URL_GENERAL . ', &#169; Kasper Sk&#229;rh&#248;j ' . TYPO3_copyright_year . ', extensions are copyright of their respective owners.';
728  }
729 
737  public function ‪xUaCompatible($content = 'IE=8')
738  {
739  trigger_error('DocumentTemplate->xUaCompatible() will be removed with TYPO3 v10.0. Use PageRenderer->setMetaTag() instead.', E_USER_DEPRECATED);
740  return '<meta http-equiv="X-UA-Compatible" content="' . $content . '" />';
741  }
742 
743  /*****************************************
744  *
745  * OTHER ELEMENTS
746  * Tables, buttons, formatting dimmed/red strings
747  *
748  ******************************************/
749 
757  public function ‪getHtmlTemplate($filename)
758  {
759  // setting the name of the original HTML template
760  $this->moduleTemplateFilename = $filename;
761  if (‪$GLOBALS['TBE_STYLES']['htmlTemplates'][$filename]) {
762  $filename = ‪$GLOBALS['TBE_STYLES']['htmlTemplates'][$filename];
763  }
764  $filename = GeneralUtility::getFileAbsFileName($filename);
765  return $filename !== '' ? file_get_contents($filename) : '';
766  }
767 
773  public function ‪setModuleTemplate($filename)
774  {
775  $this->moduleTemplate = $this->‪getHtmlTemplate($filename);
776  }
777 
788  public function ‪moduleBody($pageRecord = [], $buttons = [], $markerArray = [], $subpartArray = [])
789  {
790  // Get the HTML template for the module
791  $moduleBody = $this->templateService->getSubpart($this->moduleTemplate, '###FULLDOC###');
792  // Add CSS
793  $this->inDocStylesArray[] = 'html { overflow: hidden; }';
794  // Get the page path for the docheader
795  $markerArray['PAGEPATH'] = $this->‪getPagePath($pageRecord);
796  // Get the page info for the docheader
797  $markerArray['PAGEINFO'] = $this->‪getPageInfo($pageRecord);
798  // Get all the buttons for the docheader
799  $docHeaderButtons = $this->‪getDocHeaderButtons($buttons);
800  // Merge docheader buttons with the marker array
801  $markerArray = array_merge($markerArray, $docHeaderButtons);
802  // replacing subparts
803  foreach ($subpartArray as $marker => $content) {
804  $moduleBody = $this->templateService->substituteSubpart($moduleBody, $marker, $content);
805  }
806  // adding flash messages
807  if ($this->showFlashMessages) {
808  $flashMessages = $this->‪getFlashMessages();
809  if (!empty($flashMessages)) {
810  $markerArray['FLASHMESSAGES'] = $flashMessages;
811  // If there is no dedicated marker for the messages present
812  // then force them to appear before the content
813  if (strpos($moduleBody, '###FLASHMESSAGES###') === false) {
814  $moduleBody = str_replace('###CONTENT###', '###FLASHMESSAGES######CONTENT###', $moduleBody);
815  }
816  }
817  }
818  // Hook for adding more markers/content to the page, like the version selector
819  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['moduleBodyPostProcess'] ?? [] as $funcRef) {
820  $params = [
821  'moduleTemplateFilename' => &‪$this->moduleTemplateFilename,
822  'moduleTemplate' => &‪$this->moduleTemplate,
823  'moduleBody' => &$moduleBody,
824  'markers' => &$markerArray,
825  'parentObject' => &$this
826  ];
827  GeneralUtility::callUserFunction($funcRef, $params, $this);
828  }
829  // Replacing all markers with the finished markers and return the HTML content
830  return $this->templateService->substituteMarkerArray($moduleBody, $markerArray, '###|###');
831  }
832 
838  public function ‪getFlashMessages()
839  {
841  $flashMessageService = GeneralUtility::makeInstance(\‪TYPO3\CMS\Core\Messaging\FlashMessageService::class);
843  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
844  return $defaultFlashMessageQueue->renderFlashMessages();
845  }
846 
853  protected function ‪getDocHeaderButtons($buttons)
854  {
855  $markers = [];
856  // Fill buttons for left and right float
857  $floats = ['left', 'right'];
858  foreach ($floats as $key) {
859  // Get the template for each float
860  $buttonTemplate = $this->templateService->getSubpart($this->moduleTemplate, '###BUTTON_GROUPS_' . strtoupper($key) . '###');
861  // Fill the button markers in this float
862  $buttonTemplate = $this->templateService->substituteMarkerArray($buttonTemplate, $buttons, '###|###', true);
863  // getting the wrap for each group
864  $buttonWrap = $this->templateService->getSubpart($this->moduleTemplate, '###BUTTON_GROUP_WRAP###');
865  // looping through the groups (max 6) and remove the empty groups
866  for ($groupNumber = 1; $groupNumber < 6; $groupNumber++) {
867  $buttonMarker = '###BUTTON_GROUP' . $groupNumber . '###';
868  $buttonGroup = $this->templateService->getSubpart($buttonTemplate, $buttonMarker);
869  if (trim($buttonGroup)) {
870  if ($buttonWrap) {
871  $buttonGroup = $this->templateService->substituteMarker($buttonWrap, '###BUTTONS###', $buttonGroup);
872  }
873  $buttonTemplate = $this->templateService->substituteSubpart($buttonTemplate, $buttonMarker, trim($buttonGroup));
874  }
875  }
876  // Replace the marker with the template and remove all line breaks (for IE compat)
877  $markers['BUTTONLIST_' . strtoupper($key)] = str_replace(LF, '', $buttonTemplate);
878  }
879  // Hook for manipulating docHeaderButtons
880  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['docHeaderButtonsHook'] ?? [] as $funcRef) {
881  $params = [
882  'buttons' => $buttons,
883  'markers' => &$markers,
884  'pObj' => &$this
885  ];
886  GeneralUtility::callUserFunction($funcRef, $params, $this);
887  }
888  return $markers;
889  }
890 
897  protected function ‪getPagePath($pageRecord)
898  {
899  // Is this a real page
900  if (is_array($pageRecord) && $pageRecord['uid']) {
901  $title = substr($pageRecord['_thePathFull'], 0, -1);
902  // Remove current page title
903  $pos = strrpos($title, $pageRecord['title']);
904  if ($pos !== false) {
905  $title = substr($title, 0, $pos);
906  }
907  } else {
908  $title = '';
909  }
910  // Setting the path of the page
911  $pagePath = htmlspecialchars(‪$GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path')) . ': <span class="typo3-docheader-pagePath">';
912  // crop the title to title limit (or 50, if not defined)
913  $cropLength = empty(‪$GLOBALS['BE_USER']->uc['titleLen']) ? 50 : ‪$GLOBALS['BE_USER']->uc['titleLen'];
914  $croppedTitle = GeneralUtility::fixed_lgd_cs($title, -$cropLength);
915  if ($croppedTitle !== $title) {
916  $pagePath .= '<abbr title="' . htmlspecialchars($title) . '">' . htmlspecialchars($croppedTitle) . '</abbr>';
917  } else {
918  $pagePath .= htmlspecialchars($title);
919  }
920  $pagePath .= '</span>';
921  return $pagePath;
922  }
923 
930  protected function ‪getPageInfo($pageRecord)
931  {
932  // Add icon with context menu, etc:
933  // If there IS a real page
934  if (is_array($pageRecord) && $pageRecord['uid']) {
935  $alttext = ‪BackendUtility::getRecordIconAltText($pageRecord, 'pages');
936  $iconImg = '<span title="' . htmlspecialchars($alttext) . '">' . $this->iconFactory->getIconForRecord('pages', $pageRecord, ‪Icon::SIZE_SMALL)->render() . '</span>';
937  // Make Icon:
938  $theIcon = ‪BackendUtility::wrapClickMenuOnIcon($iconImg, 'pages', $pageRecord['uid']);
939  $uid = $pageRecord['uid'];
940  $title = ‪BackendUtility::getRecordTitle('pages', $pageRecord);
941  } else {
942  // On root-level of page tree
943  // Make Icon
944  $iconImg = '<span title="' . htmlspecialchars(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) . '">' . $this->iconFactory->getIcon('apps-pagetree-root', ‪Icon::SIZE_SMALL)->render() . '</span>';
945  if (‪$GLOBALS['BE_USER']->isAdmin()) {
946  $theIcon = ‪BackendUtility::wrapClickMenuOnIcon($iconImg, 'pages');
947  } else {
948  $theIcon = $iconImg;
949  }
950  $uid = '0';
951  $title = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
952  }
953  // Setting icon with context menu + uid
954  $pageInfo = $theIcon . '<strong>' . htmlspecialchars($title) . '&nbsp;[' . $uid . ']</strong>';
955  return $pageInfo;
956  }
957 
963  protected function ‪getBackendFavicon()
964  {
965  $backendFavicon = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('backend', 'backendFavicon');
966  if (!empty($backendFavicon)) {
967  $path = $this->‪getUriForFileName($backendFavicon);
968  } else {
969  $path = ‪ExtensionManagementUtility::extPath('backend') . 'Resources/Public/Icons/favicon.ico';
970  }
972  }
973 
982  protected function ‪getUriForFileName($filename)
983  {
984  if (strpos($filename, '://')) {
985  return $filename;
986  }
987  $urlPrefix = '';
988  if (strpos($filename, 'EXT:') === 0) {
989  $absoluteFilename = GeneralUtility::getFileAbsFileName($filename);
990  $filename = '';
991  if ($absoluteFilename !== '') {
992  $filename = ‪PathUtility::getAbsoluteWebPath($absoluteFilename);
993  }
994  } elseif (strpos($filename, '/') !== 0) {
995  $urlPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
996  }
997  return $urlPrefix . $filename;
998  }
999 
1003  protected function ‪getBackendUser()
1004  {
1005  return ‪$GLOBALS['BE_USER'] ?? null;
1006  }
1007 }
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$pageRenderer
‪PageRenderer $pageRenderer
Definition: DocumentTemplate.php:206
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$moduleTemplate
‪string $moduleTemplate
Definition: DocumentTemplate.php:93
‪TYPO3\CMS\Backend\Backend\Shortcut\ShortcutRepository
Definition: ShortcutRepository.php:41
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$scriptID
‪string $scriptID
Definition: DocumentTemplate.php:105
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getUriForFileName
‪string getUriForFileName($filename)
Definition: DocumentTemplate.php:953
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Backend\Template\DocumentTemplate\insertStylesAndJS
‪string insertStylesAndJS($content)
Definition: DocumentTemplate.php:643
‪TYPO3\CMS\Backend\Template\DocumentTemplate\addStyleSheet
‪addStyleSheet($key, $href, $title='', $relation='stylesheet')
Definition: DocumentTemplate.php:615
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getHtmlTemplate
‪string getHtmlTemplate($filename)
Definition: DocumentTemplate.php:728
‪TYPO3\CMS\Backend\Template\DocumentTemplate\makeShortcutUrl
‪string makeShortcutUrl($gvList, $setList)
Definition: DocumentTemplate.php:371
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$pageHeaderFooterTemplateFile
‪string $pageHeaderFooterTemplateFile
Definition: DocumentTemplate.php:212
‪TYPO3\CMS\Backend\Template\DocumentTemplate\makeShortcutIcon
‪string makeShortcutIcon($gvList, $setList, $modName, $motherModName='', $classes='')
Definition: DocumentTemplate.php:323
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:42
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$jsFiles
‪array $jsFiles
Definition: DocumentTemplate.php:170
‪TYPO3
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getBackendUser
‪BackendUserAuthentication null getBackendUser()
Definition: DocumentTemplate.php:974
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$xUaCompatibilityVersion
‪string $xUaCompatibilityVersion
Definition: DocumentTemplate.php:154
‪TYPO3\CMS\Backend\Template\DocumentTemplate\xUaCompatible
‪string xUaCompatible($content='IE=8')
Definition: DocumentTemplate.php:708
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$JScode
‪string $JScode
Definition: DocumentTemplate.php:70
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$showFlashMessages
‪bool $showFlashMessages
Definition: DocumentTemplate.php:218
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordIconAltText
‪static string getRecordIconAltText($row, $table='pages')
Definition: BackendUtility.php:1621
‪TYPO3\CMS\Backend\Template\DocumentTemplate\moduleBody
‪string moduleBody($pageRecord=[], $buttons=[], $markerArray=[], $subpartArray=[])
Definition: DocumentTemplate.php:759
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:31
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:614
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$styleSheetFile
‪string $styleSheetFile
Definition: DocumentTemplate.php:130
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$styleSheetFile2
‪string $styleSheetFile2
Definition: DocumentTemplate.php:136
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$bodyTagAdditions
‪string $bodyTagAdditions
Definition: DocumentTemplate.php:117
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$inDocStylesArray
‪array $inDocStylesArray
Definition: DocumentTemplate.php:124
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getBackendFavicon
‪string getBackendFavicon()
Definition: DocumentTemplate.php:934
‪TYPO3\CMS\Backend\Template\DocumentTemplate\startPage
‪string startPage($title)
Definition: DocumentTemplate.php:445
‪TYPO3\CMS\Backend\Template\DocumentTemplate\__construct
‪__construct()
Definition: DocumentTemplate.php:231
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$postCode
‪string $postCode
Definition: DocumentTemplate.php:87
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$moduleTemplateFilename
‪string $moduleTemplateFilename
Definition: DocumentTemplate.php:99
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Core\Utility\PathUtility\getRelativePathTo
‪static string null getRelativePathTo($targetPath)
Definition: PathUtility.php:31
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapClickMenuOnIcon
‪static string wrapClickMenuOnIcon( $content, $table, $uid=0, $context='', $_addParams='', $_enDisItems='', $returnTagParameters=false)
Definition: BackendUtility.php:2759
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:35
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$jsFilesNoConcatenation
‪array $jsFilesNoConcatenation
Definition: DocumentTemplate.php:176
‪TYPO3\CMS\Backend\Template\DocumentTemplate
Definition: DocumentTemplate.php:48
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$styleSheetFile_post
‪string $styleSheetFile_post
Definition: DocumentTemplate.php:142
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Core\Page\PageRenderer\PART_FOOTER
‪const PART_FOOTER
Definition: PageRenderer.php:39
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:160
‪TYPO3\CMS\Backend\Template
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1811
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getPagePath
‪string getPagePath($pageRecord)
Definition: DocumentTemplate.php:868
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getSkinStylesheetDirectories
‪array getSkinStylesheetDirectories()
Definition: DocumentTemplate.php:659
‪TYPO3\CMS\Backend\Template\DocumentTemplate\docBodyTagBegin
‪string docBodyTagBegin()
Definition: DocumentTemplate.php:573
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key, $exitOnError=null)
Definition: ExtensionManagementUtility.php:115
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Template\DocumentTemplate\formWidth
‪string formWidth($size=48, $textarea=false, $styleOverride='')
Definition: DocumentTemplate.php:392
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$templateService
‪MarkerBasedTemplateService $templateService
Definition: DocumentTemplate.php:226
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$iconFactory
‪IconFactory $iconFactory
Definition: DocumentTemplate.php:222
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$endOfPageJsBlock
‪string $endOfPageJsBlock
Definition: DocumentTemplate.php:197
‪TYPO3\CMS\Backend\Template\DocumentTemplate\docStyle
‪docStyle()
Definition: DocumentTemplate.php:581
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getPageInfo
‪string getPageInfo($pageRecord)
Definition: DocumentTemplate.php:901
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$JScodeArray
‪array $JScodeArray
Definition: DocumentTemplate.php:76
‪TYPO3\CMS\Backend\Template\DocumentTemplate\render
‪string render($title, $content)
Definition: DocumentTemplate.php:559
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$stylesheetsSkins
‪array $stylesheetsSkins
Definition: DocumentTemplate.php:161
‪TYPO3\CMS\Backend\Template\DocumentTemplate\redirectUrls
‪string redirectUrls($thisLocation='')
Definition: DocumentTemplate.php:406
‪TYPO3\CMS\Backend\Template\DocumentTemplate\generator
‪string generator()
Definition: DocumentTemplate.php:696
‪TYPO3\CMS\Backend\Template\DocumentTemplate\addStyleSheetDirectory
‪addStyleSheetDirectory($path)
Definition: DocumentTemplate.php:626
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$useCompatibilityTag
‪bool $useCompatibilityTag
Definition: DocumentTemplate.php:148
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:149
‪TYPO3\CMS\Backend\Template\DocumentTemplate\initPageRenderer
‪initPageRenderer()
Definition: DocumentTemplate.php:275
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$pageHeaderBlock
‪string $pageHeaderBlock
Definition: DocumentTemplate.php:193
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$divClass
‪string $divClass
Definition: DocumentTemplate.php:189
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:66
‪TYPO3\CMS\Backend\Template\DocumentTemplate\setModuleTemplate
‪setModuleTemplate($filename)
Definition: DocumentTemplate.php:744
‪TYPO3\CMS\Backend\Template\DocumentTemplate\endPage
‪string endPage()
Definition: DocumentTemplate.php:531
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getFlashMessages
‪string getFlashMessages()
Definition: DocumentTemplate.php:809
‪TYPO3\CMS\Core\Service\MarkerBasedTemplateService
Definition: MarkerBasedTemplateService.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$form
‪string $form
Definition: DocumentTemplate.php:64
‪TYPO3\CMS\Core\Utility\PathUtility\getAbsoluteWebPath
‪static string getAbsoluteWebPath($targetPath)
Definition: PathUtility.php:42
‪TYPO3\CMS\Backend\Utility\BackendUtility\getUpdateSignalCode
‪static string getUpdateSignalCode()
Definition: BackendUtility.php:3190
‪TYPO3\CMS\Core\Page\PageRenderer\PART_HEADER
‪const PART_HEADER
Definition: PageRenderer.php:38
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$deprecatedPublicProperties
‪array $deprecatedPublicProperties
Definition: DocumentTemplate.php:54
‪TYPO3\CMS\Backend\Template\DocumentTemplate\useCompatibilityTag
‪useCompatibilityTag($useCompatibilityTag=true)
Definition: DocumentTemplate.php:426
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$sectionFlag
‪int $sectionFlag
Definition: DocumentTemplate.php:183
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$hasDocheader
‪bool $hasDocheader
Definition: DocumentTemplate.php:202
‪TYPO3\CMS\Backend\Template\DocumentTemplate\getDocHeaderButtons
‪array getDocHeaderButtons($buttons)
Definition: DocumentTemplate.php:824
‪TYPO3\CMS\Backend\Template\DocumentTemplate\$bodyTagId
‪string $bodyTagId
Definition: DocumentTemplate.php:111