TYPO3 CMS  TYPO3_7-6
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 
27 
42 {
43  // Vars you typically might want to/should set from outside after making instance of this class:
50  public $form = '';
51 
59  public $JScodeLibArray = [];
60 
66  public $JScode = '';
67 
73  public $extJScode = '';
74 
80  public $JScodeArray = ['jumpToUrl' => '
81 function jumpToUrl(URL) {
82  window.location.href = URL;
83  return false;
84 }
85  '];
86 
92  public $postCode = '';
93 
98  public $docType = '';
99 
105  public $moduleTemplate = '';
106 
112  protected $moduleTemplateFilename = '';
113 
119  public $scriptID = '';
120 
126  public $bodyTagId = '';
127 
133  public $bodyTagAdditions = '';
134 
140  public $inDocStyles = '';
141 
148  public $inDocStylesArray = [];
149 
155  public $form_largeComp = 1.33;
156 
163  public $endJS = 1;
164 
165  // TYPO3 Colorscheme.
166  // If you want to change this, please do so through a skin using the global var $GLOBALS['TBE_STYLES']
167 
173  public $bgColor = '#F7F3EF';
174 
180  public $bgColor2 = '#9BA1A8';
181 
187  public $bgColor3 = '#F6F2E6';
188 
194  public $bgColor4 = '#D9D5C9';
195 
201  public $bgColor5 = '#ABBBB4';
202 
208  public $bgColor6 = '#E7DBA8';
209 
213  public $hoverColor = '#254D7B';
214 
220  public $styleSheetFile = '';
221 
227  public $styleSheetFile2 = '';
228 
234  public $styleSheetFile_post = '';
235 
242  public $backGroundImage = '';
243 
251 
257  protected $useCompatibilityTag = true;
258 
264  protected $xUaCompatibilityVersion = 'IE=edge';
265 
266  // Skinning
272  protected $stylesheetsCore = [
273  'generatedSprites' => '../typo3temp/sprites/'
274  ];
275 
281  protected $stylesheetsSkins = [
282  'structure' => 'Resources/Public/Css/structure/',
283  'visual' => 'Resources/Public/Css/visual/'
284  ];
285 
291  protected $jsFiles = [];
292 
298  protected $jsFilesNoConcatenation = [];
299 
307  public $parseTimeFlag = false;
308 
315  protected $charset = 'utf-8';
316 
323  public $sectionFlag = 0;
324 
330  public $divClass = '';
331 
335  public $pageHeaderBlock = '';
336 
340  public $endOfPageJsBlock = '';
341 
345  public $hasDocheader = true;
346 
350  protected $pageRenderer = null;
351 
358 
362  protected $extDirectStateProvider = false;
363 
369  public $showFlashMessages = true;
370 
374  protected $iconFactory;
375 
379  protected $templateService;
380 
381  const STATUS_ICON_ERROR = 3;
384  const STATUS_ICON_OK = -1;
385 
389  public function __construct()
390  {
391  // Initializes the page rendering object:
392  $this->initPageRenderer();
393 
394  // load Legacy CSS Support
395  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LegacyCssClasses');
396  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
397 
398  // initialize Marker Support
399  $this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
400 
401  // Setting default scriptID:
402  if (($temp_M = (string)GeneralUtility::_GET('M')) && $GLOBALS['TBE_MODULES']['_PATHS'][$temp_M]) {
403  $this->scriptID = preg_replace('/^.*\\/(sysext|ext)\\//', 'ext/', $GLOBALS['TBE_MODULES']['_PATHS'][$temp_M] . 'index.php');
404  } else {
405  $this->scriptID = preg_replace('/^.*\\/(sysext|ext)\\//', 'ext/', \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(PATH_thisScript));
406  }
407  if (TYPO3_mainDir != 'typo3/' && substr($this->scriptID, 0, strlen(TYPO3_mainDir)) == TYPO3_mainDir) {
408  // This fixes if TYPO3_mainDir has been changed so the script ids are STILL "typo3/..."
409  $this->scriptID = 'typo3/' . substr($this->scriptID, strlen(TYPO3_mainDir));
410  }
411  $this->bodyTagId = preg_replace('/[^A-Za-z0-9-]/', '-', $this->scriptID);
412  // Individual configuration per script? If so, make a recursive merge of the arrays:
413  if (is_array($GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID])) {
414  // Make copy
415  $ovr = $GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID];
416  // merge styles.
418  // Have to unset - otherwise the second instantiation will do it again!
419  unset($GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID]);
420  }
421  // Main Stylesheets:
422  if ($GLOBALS['TBE_STYLES']['stylesheet']) {
423  $this->styleSheetFile = $GLOBALS['TBE_STYLES']['stylesheet'];
424  }
425  if ($GLOBALS['TBE_STYLES']['stylesheet2']) {
426  $this->styleSheetFile2 = $GLOBALS['TBE_STYLES']['stylesheet2'];
427  }
428  if ($GLOBALS['TBE_STYLES']['styleSheetFile_post']) {
429  $this->styleSheetFile_post = $GLOBALS['TBE_STYLES']['styleSheetFile_post'];
430  }
431  if ($GLOBALS['TBE_STYLES']['inDocStyles_TBEstyle']) {
432  $this->inDocStylesArray['TBEstyle'] = $GLOBALS['TBE_STYLES']['inDocStyles_TBEstyle'];
433  }
434  // include all stylesheets
435  foreach ($this->getSkinStylesheetDirectories() as $stylesheetDirectory) {
436  $this->addStylesheetDirectory($stylesheetDirectory);
437  }
438  // Background image
439  if ($GLOBALS['TBE_STYLES']['background']) {
440  GeneralUtility::deprecationLog('Usage of $TBE_STYLES["background"] is deprecated. Please use stylesheets directly.');
441  }
442  }
443 
447  protected function initPageRenderer()
448  {
449  if ($this->pageRenderer !== null) {
450  return;
451  }
452  $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
453  $this->pageRenderer->setLanguage($GLOBALS['LANG']->lang);
454  $this->pageRenderer->enableConcatenateFiles();
455  $this->pageRenderer->enableCompressCss();
456  $this->pageRenderer->enableCompressJavascript();
457  // Add all JavaScript files defined in $this->jsFiles to the PageRenderer
458  foreach ($this->jsFilesNoConcatenation as $file) {
459  $this->pageRenderer->addJsFile(
460  $GLOBALS['BACK_PATH'] . $file,
461  'text/javascript',
462  true,
463  false,
464  '',
465  true
466  );
467  }
468  // Add all JavaScript files defined in $this->jsFiles to the PageRenderer
469  foreach ($this->jsFiles as $file) {
470  $this->pageRenderer->addJsFile($GLOBALS['BACK_PATH'] . $file);
471  }
472  if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] === 1) {
473  $this->pageRenderer->enableDebugMode();
474  }
475  }
476 
483  public function getPageRenderer()
484  {
486  $this->initPageRenderer();
487 
488  return $this->pageRenderer;
489  }
490 
496  public function setExtDirectStateProvider()
497  {
498  $this->extDirectStateProvider = true;
499  }
500 
501  /*****************************************
502  *
503  * EVALUATION FUNCTIONS
504  * Various centralized processing
505  *
506  *****************************************/
522  public function wrapClickMenuOnIcon($content, $table, $uid = 0, $listFr = true, $addParams = '', $enDisItems = '', $returnTagParameters = false)
523  {
525  return BackendUtility::wrapClickMenuOnIcon($content, $table, $uid, $listFr, $addParams, $enDisItems, $returnTagParameters);
526  }
527 
538  public function viewPageIcon($id, $_ = '')
539  {
540  // If access to Web>List for user, then link to that module.
541  $str = BackendUtility::getListViewLink([
542  'id' => $id,
543  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
544  ], $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.showList'));
545  // Make link to view page
546  $str .= '<a href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($id, '', BackendUtility::BEgetRootLine($id))) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', true) . '">' . $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '</a>';
547  return $str;
548  }
549 
560  public function issueCommand($params, $redirectUrl = '')
561  {
564  }
565 
580  public function getHeader($table, $row, $path, $noViewPageIcon = false, $tWrap = ['', ''], $enableClickMenu = true)
581  {
582  $viewPage = '';
583  if (is_array($row) && $row['uid']) {
584  $iconImgTag = '<span title="' . htmlspecialchars($path) . '">' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
585  $title = strip_tags(BackendUtility::getRecordTitle($table, $row));
586  $viewPage = $noViewPageIcon ? '' : $this->viewPageIcon($row['uid']);
587  } else {
588  $iconImgTag = '<span title="' . htmlspecialchars($path) . '">' . $this->iconFactory->getIcon('apps-pagetree-page-domain', Icon::SIZE_SMALL)->render() . '</span>';
589  $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
590  }
591 
592  if ($enableClickMenu) {
593  $iconImgTag = BackendUtility::wrapClickMenuOnIcon($iconImgTag, $table, $row['uid']);
594  }
595 
596  return '<span class="typo3-moduleHeader">' . $iconImgTag . $viewPage . $tWrap[0] . htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, 45)) . $tWrap[1] . '</span>';
597  }
598 
608  public function getResourceHeader(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, $tWrap = ['', ''], $enableClickMenu = true)
609  {
610  try {
611  $path = $resource->getStorage()->getName() . $resource->getParentFolder()->getIdentifier();
612  $iconImgTag = '<span title="' . htmlspecialchars($path) . '">' . $this->iconFactory->getIconForResource($resource, Icon::SIZE_SMALL)->render() . '</span>';
613  } catch (\TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException $e) {
614  $iconImgTag = '';
615  }
616 
617  if ($enableClickMenu && ($resource instanceof \TYPO3\CMS\Core\Resource\File)) {
618  $metaData = $resource->_getMetaData();
619  $iconImgTag = BackendUtility::wrapClickMenuOnIcon($iconImgTag, 'sys_file_metadata', $metaData['uid']);
620  }
621 
622  return '<span class="typo3-moduleHeader">' . $iconImgTag . $tWrap[0] . htmlspecialchars(GeneralUtility::fixed_lgd_cs($resource->getName(), 45)) . $tWrap[1] . '</span>';
623  }
624 
635  public function makeShortcutIcon($gvList, $setList, $modName, $motherModName = '', $classes = '')
636  {
637  $gvList = 'route,' . $gvList;
638  $storeUrl = $this->makeShortcutUrl($gvList, $setList);
639  $pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
640  // Fallback for alt_mod. We still pass in the old xMOD... stuff, but TBE_MODULES only knows about "record_edit".
641  // We still need to pass the xMOD name to createShortcut below, since this is used for icons.
642  $moduleName = $modName === 'xMOD_alt_doc.php' ? 'record_edit' : $modName;
643  // Add the module identifier automatically if typo3/index.php is used:
644  if (GeneralUtility::_GET('M') !== null && isset($GLOBALS['TBE_MODULES']['_PATHS'][$moduleName])) {
645  $storeUrl = '&M=' . $moduleName . $storeUrl;
646  }
647  if ((int)$motherModName === 1) {
648  $motherModule = 'top.currentModuleLoaded';
649  } elseif ($motherModName) {
650  $motherModule = GeneralUtility::quoteJSvalue($motherModName);
651  } else {
652  $motherModule = '\'\'';
653  }
654  $confirmationText = GeneralUtility::quoteJSvalue($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark'));
655 
656  $shortcutUrl = $pathInfo['path'] . '?' . $storeUrl;
657  $shortcutExist = BackendUtility::shortcutExists($shortcutUrl);
658 
659  if ($shortcutExist) {
660  return '<a class="active ' . htmlspecialchars($classes) . '" title="">' .
661  $this->iconFactory->getIcon('actions-system-shortcut-active', Icon::SIZE_SMALL)->render() . '</a>';
662  }
663  $url = GeneralUtility::quoteJSvalue(rawurlencode($shortcutUrl));
664  $onClick = 'top.TYPO3.ShortcutMenu.createShortcut(' . GeneralUtility::quoteJSvalue(rawurlencode($modName)) .
665  ', ' . $url . ', ' . $confirmationText . ', ' . $motherModule . ', this);return false;';
666 
667  return '<a href="#" class="' . htmlspecialchars($classes) . '" onclick="' . htmlspecialchars($onClick) . '" title="' .
668  $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark', true) . '">' .
669  $this->iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render() . '</a>';
670  }
671 
682  public function makeShortcutUrl($gvList, $setList)
683  {
684  $GET = GeneralUtility::_GET();
685  $storeArray = array_merge(GeneralUtility::compileSelectedGetVarsFromArray($gvList, $GET), ['SET' => GeneralUtility::compileSelectedGetVarsFromArray($setList, (array)$GLOBALS['SOBE']->MOD_SETTINGS)]);
686  $storeUrl = GeneralUtility::implodeArrayForUrl('', $storeArray);
687  return $storeUrl;
688  }
689 
700  public function formWidth($size = 48, $textarea = false, $styleOverride = '')
701  {
702  return ' style="' . ($styleOverride ?: 'width:' . ceil($size * 9.58) . 'px;') . '"';
703  }
704 
713  public function redirectUrls($thisLocation = '')
714  {
715  $thisLocation = $thisLocation ? $thisLocation : GeneralUtility::linkThisScript([
716  'CB' => '',
717  'SET' => '',
718  'cmd' => '',
719  'popViewId' => ''
720  ]);
721  $out = '
722  var T3_RETURN_URL = ' . GeneralUtility::quoteJSvalue(str_replace('%20', '', rawurlencode(GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'))))) . ';
723  var T3_THIS_LOCATION = ' . GeneralUtility::quoteJSvalue(str_replace('%20', '', rawurlencode($thisLocation))) . '
724  ';
725  return $out;
726  }
727 
737  public function formatTime($tstamp, $type)
738  {
740  $dateStr = '';
741  switch ($type) {
742  case 1:
743  $dateStr = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $tstamp);
744  break;
745  case 10:
746  $dateStr = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $tstamp);
747  break;
748  }
749  return $dateStr;
750  }
751 
759  public function parseTime()
760  {
762  if ($this->parseTimeFlag && $GLOBALS['BE_USER']->isAdmin()) {
763  return '<p>(ParseTime: ' . (GeneralUtility::milliseconds() - $GLOBALS['PARSETIME_START']) . ' ms</p>
764  <p>REQUEST_URI-length: ' . strlen(GeneralUtility::getIndpEnv('REQUEST_URI')) . ')</p>';
765  }
766  }
767 
775  {
777  }
778 
779  /*****************************************
780  *
781  * PAGE BUILDING FUNCTIONS.
782  * Use this to build the HTML of your backend modules
783  *
784  *****************************************/
793  public function startPage($title)
794  {
795  // hook pre start page
796  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'])) {
797  $preStartPageHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'];
798  if (is_array($preStartPageHook)) {
799  $hookParameters = [
800  'title' => &$title
801  ];
802  foreach ($preStartPageHook as $hookFunction) {
803  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
804  }
805  }
806  }
807  // alternative template for Header and Footer
808  if ($this->pageHeaderFooterTemplateFile) {
809  $file = GeneralUtility::getFileAbsFileName($this->pageHeaderFooterTemplateFile, true);
810  if ($file) {
811  $this->pageRenderer->setTemplateFile($file);
812  }
813  }
814 
815  // Disable rendering of XHTML tags
816  $this->pageRenderer->setRenderXhtml(false);
817 
818  $languageCode = $this->pageRenderer->getLanguage() === 'default' ? 'en' : $this->pageRenderer->getLanguage();
819  $this->pageRenderer->setHtmlTag('<html lang="' . $languageCode . '">');
820 
821  $headerStart = '<!DOCTYPE html>';
822  $this->pageRenderer->setXmlPrologAndDocType($headerStart);
823  $this->pageRenderer->setHeadTag('<head>' . LF . '<!-- TYPO3 Script ID: ' . htmlspecialchars($this->scriptID) . ' -->');
824  header('Content-Type:text/html;charset=utf-8');
825  $this->pageRenderer->setCharSet('utf-8');
826  $this->pageRenderer->addMetaTag($this->generator());
827  $this->pageRenderer->addMetaTag('<meta name="robots" content="noindex,follow">');
828  $this->pageRenderer->addMetaTag('<meta charset="utf-8">');
829  $this->pageRenderer->addMetaTag('<meta name="viewport" content="width=device-width, initial-scale=1">');
830  $this->pageRenderer->setFavIcon($this->getBackendFavicon());
831  if ($this->useCompatibilityTag) {
832  $this->pageRenderer->addMetaTag($this->xUaCompatible($this->xUaCompatibilityVersion));
833  }
834  $this->pageRenderer->setTitle($title);
835  // add docstyles
836  $this->docStyle();
837  if ($this->extDirectStateProvider) {
838  $this->pageRenderer->addJsFile(ExtensionManagementUtility::extRelPath('backend') . 'Resources/Public/JavaScript/ExtDirect.StateProvider.js');
839  }
840  $this->pageRenderer->addHeaderData($this->JScode);
841  foreach ($this->JScodeArray as $name => $code) {
842  $this->pageRenderer->addJsInlineCode($name, $code, false);
843  }
844  if (!empty($this->JScodeLibArray)) {
845  GeneralUtility::deprecationLog('DocumentTemplate->JScodeLibArray is deprecated since TYPO3 CMS 7. Use the functionality within pageRenderer directly');
846  foreach ($this->JScodeLibArray as $library) {
847  $this->pageRenderer->addHeaderData($library);
848  }
849  }
850  if ($this->extJScode) {
851  $this->pageRenderer->addExtOnReadyCode($this->extJScode);
852  }
853 
854  // Load jquery and twbs JS libraries on every backend request
855  $this->pageRenderer->loadJquery();
856  // Note: please do not reference "bootstrap" outside of the TYPO3 Core (not in your own extensions)
857  // as this is preliminary as long as Twitter bootstrap does not support AMD modules
858  // this logic will be changed once Twitter bootstrap 4 is included
859  $this->pageRenderer->addJsFile(ExtensionManagementUtility::extRelPath('core') . 'Resources/Public/JavaScript/Contrib/bootstrap/bootstrap.js');
860 
861  // hook for additional headerData
862  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'])) {
863  $preHeaderRenderHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'];
864  if (is_array($preHeaderRenderHook)) {
865  $hookParameters = [
866  'pageRenderer' => &$this->pageRenderer
867  ];
868  foreach ($preHeaderRenderHook as $hookFunction) {
869  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
870  }
871  }
872  }
873  // Construct page header.
874  $str = $this->pageRenderer->render(PageRenderer::PART_HEADER);
875  $this->JScode = ($this->extJScode = '');
876  $this->JScodeArray = [];
877  $this->endOfPageJsBlock = $this->pageRenderer->render(PageRenderer::PART_FOOTER);
878  $str .= $this->docBodyTagBegin() . ($this->divClass ? '
879 
880 <!-- Wrapping DIV-section for whole page BEGIN -->
881 <div class="' . $this->divClass . '">
882 ' : '') . trim($this->form);
883  return $str;
884  }
885 
892  public function endPage()
893  {
894  $str = $this->sectionEnd() . $this->postCode . $this->wrapScriptTags(BackendUtility::getUpdateSignalCode()) . ($this->form ? '
895 </form>' : '');
896  // If something is in buffer like debug, put it to end of page
897  if (ob_get_contents()) {
898  $str .= ob_get_clean();
899  if (!headers_sent()) {
900  header('Content-Encoding: None');
901  }
902  }
903  $str .= ($this->divClass ? '
904 
905 <!-- Wrapping DIV-section for whole page END -->
906 </div>' : '') . $this->endOfPageJsBlock;
907 
908  // Logging: Can't find better place to put it:
909  if (TYPO3_DLOG) {
910  GeneralUtility::devLog('END of BACKEND session', \TYPO3\CMS\Backend\Template\DocumentTemplate::class, 0, ['_FLUSH' => true]);
911  }
912  return $str;
913  }
914 
922  public function render($title, $content)
923  {
924  $pageContent = $this->startPage($title);
925  $pageContent .= $content;
926  $pageContent .= $this->endPage();
927  return $this->insertStylesAndJS($pageContent);
928  }
929 
937  public function header($text)
938  {
939  $str = '
940 
941  <!-- MAIN Header in page top -->
942  <h1 class="t3js-title-inlineedit">' . htmlspecialchars($text) . '</h1>
943 ';
944  return $this->sectionEnd() . $str;
945  }
946 
959  public function section($label, $text, $nostrtoupper = false, $sH = false, $type = 0, $allowHTMLinHeader = false)
960  {
961  $str = '';
962  // Setting header
963  if ($label) {
964  if (!$allowHTMLinHeader) {
965  $label = htmlspecialchars($label);
966  }
967  $str .= $this->sectionHeader($this->icons($type) . $label, $sH, $nostrtoupper ? '' : ' class="uppercase"');
968  }
969  // Setting content
970  $str .= '
971 
972  <!-- Section content -->
973 ' . $text;
974  return $this->sectionBegin() . $str;
975  }
976 
984  public function divider($dist)
985  {
986  $dist = (int)$dist;
987  $str = '
988 
989  <!-- DIVIDER -->
990  <hr style="margin-top: ' . $dist . 'px; margin-bottom: ' . $dist . 'px;" />
991 ';
992  return $this->sectionEnd() . $str;
993  }
994 
1002  public function spacer($dist)
1003  {
1005  if ($dist > 0) {
1006  return '
1007 
1008  <!-- Spacer element -->
1009  <div style="padding-top: ' . (int)$dist . 'px;"></div>
1010 ';
1011  }
1012  }
1013 
1023  public function sectionHeader($label, $sH = false, $addAttrib = '')
1024  {
1025  $tag = $sH ? 'h2' : 'h3';
1026  if ($addAttrib && $addAttrib[0] !== ' ') {
1027  $addAttrib = ' ' . $addAttrib;
1028  }
1029  $str = '
1030 
1031  <!-- Section header -->
1032  <' . $tag . $addAttrib . '>' . $label . '</' . $tag . '>
1033 ';
1034  return $this->sectionBegin() . $str;
1035  }
1036 
1044  public function sectionBegin()
1045  {
1046  if (!$this->sectionFlag) {
1047  $this->sectionFlag = 1;
1048  $str = '
1049 
1050  <!-- ***********************
1051  Begin output section.
1052  *********************** -->
1053  <div>
1054 ';
1055  return $str;
1056  } else {
1057  return '';
1058  }
1059  }
1060 
1068  public function sectionEnd()
1069  {
1070  if ($this->sectionFlag) {
1071  $this->sectionFlag = 0;
1072  return '
1073  </div>
1074  <!-- *********************
1075  End output section.
1076  ********************* -->
1077 ';
1078  } else {
1079  return '';
1080  }
1081  }
1082 
1090  public function endPageJS()
1091  {
1093  return '';
1094  }
1095 
1102  public function docBodyTagBegin()
1103  {
1104  return '<body ' . trim($this->bodyTagAdditions . ($this->bodyTagId ? ' id="' . $this->bodyTagId . '"' : '')) . '>';
1105  }
1106 
1112  public function docStyle()
1113  {
1114  // Implode it all:
1115  $inDocStyles = implode(LF, $this->inDocStylesArray);
1116 
1117  // Reset styles so they won't be added again in insertStylesAndJS()
1118  $this->inDocStylesArray = [];
1119 
1120  if ($this->styleSheetFile) {
1121  $this->pageRenderer->addCssFile($this->styleSheetFile);
1122  }
1123  if ($this->styleSheetFile2) {
1124  $this->pageRenderer->addCssFile($this->styleSheetFile2);
1125  }
1126 
1127  if ($inDocStyles !== '') {
1128  $this->pageRenderer->addCssInlineBlock('inDocStyles', $inDocStyles . LF . '/*###POSTCSSMARKER###*/');
1129  }
1130 
1131  if ($this->styleSheetFile_post) {
1132  $this->pageRenderer->addCssFile($this->styleSheetFile_post);
1133  }
1134  }
1135 
1145  public function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet')
1146  {
1147  $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
1148  }
1149 
1156  public function addStyleSheetDirectory($path)
1157  {
1158  // Calculation needed, when TYPO3 source is used via a symlink
1159  // absolute path to the stylesheets
1160  $filePath = dirname(GeneralUtility::getIndpEnv('SCRIPT_FILENAME')) . '/' . $GLOBALS['BACK_PATH'] . $path;
1161  // Clean the path
1162  $resolvedPath = GeneralUtility::resolveBackPath($filePath);
1163  // Read all files in directory and sort them alphabetically
1164  $files = GeneralUtility::getFilesInDir($resolvedPath, 'css', false, 1);
1165  foreach ($files as $file) {
1166  $this->pageRenderer->addCssFile($GLOBALS['BACK_PATH'] . $path . $file, 'stylesheet', 'all');
1167  }
1168  }
1169 
1177  public function insertStylesAndJS($content)
1178  {
1179  $styles = LF . implode(LF, $this->inDocStylesArray);
1180  $content = str_replace('/*###POSTCSSMARKER###*/', $styles, $content);
1181 
1182  // Insert accumulated JS
1183  $jscode = $this->JScode . LF . $this->wrapScriptTags(implode(LF, $this->JScodeArray));
1184  $content = str_replace('<!--###POSTJSMARKER###-->', $jscode, $content);
1185  return $content;
1186  }
1187 
1194  {
1195  $stylesheetDirectories = [];
1196  // Add default core stylesheets
1197  foreach ($this->stylesheetsCore as $stylesheetDir) {
1198  $stylesheetDirectories[] = $stylesheetDir;
1199  }
1200  // Stylesheets from skins
1201  // merge default css directories ($this->stylesheetsSkin) with additional ones and include them
1202  if (is_array($GLOBALS['TBE_STYLES']['skins'])) {
1203  // loop over all registered skins
1204  foreach ($GLOBALS['TBE_STYLES']['skins'] as $skinExtKey => $skin) {
1205  $skinStylesheetDirs = $this->stylesheetsSkins;
1206  // Skins can add custom stylesheetDirectories using
1207  // $GLOBALS['TBE_STYLES']['skins'][$_EXTKEY]['stylesheetDirectories']
1208  if (is_array($skin['stylesheetDirectories'])) {
1209  $skinStylesheetDirs = array_merge($skinStylesheetDirs, $skin['stylesheetDirectories']);
1210  }
1211  // Add all registered directories
1212  foreach ($skinStylesheetDirs as $stylesheetDir) {
1213  // for EXT:myskin/stylesheets/ syntax
1214  if (substr($stylesheetDir, 0, 4) === 'EXT:') {
1215  list($extKey, $path) = explode('/', substr($stylesheetDir, 4), 2);
1216  if (!empty($extKey) && ExtensionManagementUtility::isLoaded($extKey) && !empty($path)) {
1217  $stylesheetDirectories[] = ExtensionManagementUtility::extRelPath($extKey) . $path;
1218  }
1219  } else {
1220  // For relative paths
1221  $stylesheetDirectories[] = ExtensionManagementUtility::extRelPath($skinExtKey) . $stylesheetDir;
1222  }
1223  }
1224  }
1225  }
1226  return $stylesheetDirectories;
1227  }
1228 
1234  public function generator()
1235  {
1236  $str = 'TYPO3 CMS, ' . TYPO3_URL_GENERAL . ', &#169; Kasper Sk&#229;rh&#248;j ' . TYPO3_copyright_year . ', extensions are copyright of their respective owners.';
1237  return '<meta name="generator" content="' . $str . '" />';
1238  }
1239 
1246  public function xUaCompatible($content = 'IE=8')
1247  {
1248  return '<meta http-equiv="X-UA-Compatible" content="' . $content . '" />';
1249  }
1250 
1251  /*****************************************
1252  *
1253  * OTHER ELEMENTS
1254  * Tables, buttons, formatting dimmed/red strings
1255  *
1256  ******************************************/
1270  public function icons($type, $styleAttribValue = '')
1271  {
1272  switch ($type) {
1273  case self::STATUS_ICON_ERROR:
1274  $icon = 'status-dialog-error';
1275  break;
1276  case self::STATUS_ICON_WARNING:
1277  $icon = 'status-dialog-warning';
1278  break;
1279  case self::STATUS_ICON_NOTIFICATION:
1280  $icon = 'status-dialog-notification';
1281  break;
1282  case self::STATUS_ICON_OK:
1283  $icon = 'status-dialog-ok';
1284  break;
1285  default:
1286  // Do nothing
1287  }
1288  if ($icon) {
1289  return $this->iconFactory->getIcon($icon, Icon::SIZE_SMALL)->render();
1290  }
1291  }
1292 
1300  public function t3Button($onClick, $label)
1301  {
1302  $button = '<input class="btn btn-default" type="submit" onclick="' . htmlspecialchars($onClick) . '; return false;" value="' . htmlspecialchars($label) . '" />';
1303  return $button;
1304  }
1305 
1313  public function dfw($string)
1314  {
1316  return '<span class="text-muted">' . $string . '</span>';
1317  }
1318 
1326  public function rfw($string)
1327  {
1329  return '<span class="text-danger">' . $string . '</span>';
1330  }
1331 
1338  public function wrapInCData($string)
1339  {
1340  $string = '/*<![CDATA[*/' . $string . '/*]]>*/';
1341  return $string;
1342  }
1343 
1353  public function wrapScriptTags($string, $linebreak = true)
1354  {
1355  if (trim($string)) {
1356  // <script wrapped in nl?
1357  $cr = $linebreak ? LF : '';
1358  // Remove nl from the beginning
1359  $string = ltrim($string, LF);
1360  // Re-ident to one tab using the first line as reference
1361  if ($string[0] === TAB) {
1362  $string = TAB . ltrim($string, TAB);
1363  }
1364  $string = $cr . '<script type="text/javascript">
1365 /*<![CDATA[*/
1366 ' . $string . '
1367 /*]]>*/
1368 </script>' . $cr;
1369  }
1370  return trim($string);
1371  }
1372 
1373  // These vars defines the layout for the table produced by the table() function.
1374  // You can override these values from outside if you like.
1375  public $tableLayout = [
1376  'defRow' => [
1377  'defCol' => ['<td valign="top">', '</td>']
1378  ]
1379  ];
1380 
1381  public $table_TR = '<tr>';
1382 
1383  public $table_TABLE = '<table border="0" cellspacing="0" cellpadding="0" class="typo3-dblist" id="typo3-tmpltable">';
1384 
1394  public function table($data, $layout = null)
1395  {
1397  $result = '';
1398  if (is_array($data)) {
1399  $tableLayout = is_array($layout) ? $layout : $this->tableLayout;
1400  $rowCount = 0;
1401  foreach ($data as $tableRow) {
1402  if ($rowCount % 2) {
1403  $layout = is_array($tableLayout['defRowOdd']) ? $tableLayout['defRowOdd'] : $tableLayout['defRow'];
1404  } else {
1405  $layout = is_array($tableLayout['defRowEven']) ? $tableLayout['defRowEven'] : $tableLayout['defRow'];
1406  }
1407  $rowLayout = is_array($tableLayout[$rowCount]) ? $tableLayout[$rowCount] : $layout;
1408  $rowResult = '';
1409  if (is_array($tableRow)) {
1410  $cellCount = 0;
1411  foreach ($tableRow as $tableCell) {
1412  $cellWrap = is_array($layout[$cellCount]) ? $layout[$cellCount] : $layout['defCol'];
1413  $cellWrap = is_array($rowLayout['defCol']) ? $rowLayout['defCol'] : $cellWrap;
1414  $cellWrap = is_array($rowLayout[$cellCount]) ? $rowLayout[$cellCount] : $cellWrap;
1415  $rowResult .= $cellWrap[0] . $tableCell . $cellWrap[1];
1416  $cellCount++;
1417  }
1418  }
1419  $rowWrap = is_array($layout['tr']) ? $layout['tr'] : [$this->table_TR, '</tr>'];
1420  $rowWrap = is_array($rowLayout['tr']) ? $rowLayout['tr'] : $rowWrap;
1421  $result .= $rowWrap[0] . $rowResult . $rowWrap[1];
1422  $rowCount++;
1423  }
1424  $tableWrap = is_array($tableLayout['table']) ? $tableLayout['table'] : [$this->table_TABLE, '</table>'];
1425  $result = $tableWrap[0] . $result . $tableWrap[1];
1426  }
1427  return $result;
1428  }
1429 
1439  public function menuTable($arr1, $arr2 = [], $arr3 = [])
1440  {
1442  $rows = max([count($arr1), count($arr2), count($arr3)]);
1443  $menu = '
1444  <table border="0" cellpadding="0" cellspacing="0" id="typo3-tablemenu">';
1445  for ($a = 0; $a < $rows; $a++) {
1446  $menu .= '<tr>';
1447  $cls = [];
1448  $valign = 'middle';
1449  $cls[] = '<td valign="' . $valign . '">' . $arr1[$a][0] . '</td><td>' . $arr1[$a][1] . '</td>';
1450  if (!empty($arr2)) {
1451  $cls[] = '<td valign="' . $valign . '">' . $arr2[$a][0] . '</td><td>' . $arr2[$a][1] . '</td>';
1452  if (!empty($arr3)) {
1453  $cls[] = '<td valign="' . $valign . '">' . $arr3[$a][0] . '</td><td>' . $arr3[$a][1] . '</td>';
1454  }
1455  }
1456  $menu .= implode($cls, '<td>&nbsp;&nbsp;</td>');
1457  $menu .= '</tr>';
1458  }
1459  $menu .= '
1460  </table>
1461  ';
1462  return $menu;
1463  }
1464 
1473  public function funcMenu($content, $menu)
1474  {
1475  return '
1476  <table border="0" cellpadding="0" cellspacing="0" width="100%" id="typo3-funcmenu">
1477  <tr>
1478  <td valign="top" nowrap="nowrap">' . $content . '</td>
1479  <td valign="top" align="right" nowrap="nowrap">' . $menu . '</td>
1480  </tr>
1481  </table>';
1482  }
1483 
1490  public function loadJavascriptLib($lib)
1491  {
1492  // @todo: maybe we can remove this one as well
1493  $this->pageRenderer->addJsFile($lib);
1494  }
1495 
1501  public function getContextMenuCode()
1502  {
1503  $this->pageRenderer->loadJquery();
1504  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
1505  }
1506 
1515  public function getDragDropCode($table, $additionalJavaScriptCode = '')
1516  {
1517  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree', 'function() {
1518  DragDrop.table = "' . $table . '";
1519  ' . $additionalJavaScriptCode . '
1520  }');
1521  }
1522 
1537  public function getTabMenu($mainParams, $elementName, $currentValue, $menuItems, $script = '', $addparams = '')
1538  {
1539  $content = '';
1540  if (is_array($menuItems)) {
1541  if (!is_array($mainParams)) {
1542  $mainParams = ['id' => $mainParams];
1543  }
1544  $mainParams = GeneralUtility::implodeArrayForUrl('', $mainParams);
1545  if (!$script) {
1546  $script = basename(PATH_thisScript);
1547  }
1548  $menuDef = [];
1549  foreach ($menuItems as $value => $label) {
1550  $menuDef[$value]['isActive'] = (string)$currentValue === (string)$value;
1551  $menuDef[$value]['label'] = htmlspecialchars($label, ENT_COMPAT, 'UTF-8', false);
1552  $menuDef[$value]['url'] = $script . '?' . $mainParams . $addparams . '&' . $elementName . '=' . $value;
1553  }
1554  $content = $this->getTabMenuRaw($menuDef);
1555  }
1556  return $content;
1557  }
1558 
1566  public function getTabMenuRaw($menuItems)
1567  {
1568  if (!is_array($menuItems)) {
1569  return '';
1570  }
1571 
1572  $options = '';
1573  foreach ($menuItems as $id => $def) {
1574  $class = $def['isActive'] ? 'active' : '';
1575  $label = $def['label'];
1576  $url = htmlspecialchars($def['url']);
1577  $params = $def['addParams'];
1578 
1579  $options .= '<li class="' . $class . '">' .
1580  '<a href="' . $url . '" ' . $params . '>' . $label . '</a>' .
1581  '</li>';
1582  }
1583 
1584  return '<ul class="nav nav-tabs" role="tablist">' .
1585  $options .
1586  '</ul>';
1587  }
1588 
1601  public function getDynamicTabMenu(array $menuItems, $identString, $defaultTabIndex = 1, $collapseable = false, $wrapContent = true, $storeLastActiveTab = true)
1602  {
1604  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tabs');
1605  $templatePathAndFileName = 'EXT:backend/Resources/Private/Templates/DocumentTemplate/' . ($collapseable ? 'Collapse.html' : 'Tabs.html');
1606  $view = GeneralUtility::makeInstance(StandaloneView::class);
1607  $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFileName));
1608  $view->assignMultiple([
1609  'id' => 'DTM-' . GeneralUtility::shortMD5($identString),
1610  'items' => $menuItems,
1611  'defaultTabIndex' => $defaultTabIndex,
1612  'wrapContent' => $wrapContent,
1613  'storeLastActiveTab' => $storeLastActiveTab,
1614  'BACK_PATH' => $GLOBALS['BACK_PATH']
1615  ]);
1616  return $view->render();
1617  }
1618 
1634  public function getDynTabMenu($menuItems, $identString, $toggle = 0, $foldout = false, $noWrap = true, $fullWidth = false, $defaultTabIndex = 1, $tabBehaviour = 1)
1635  {
1637  return $this->getDynamicTabMenu($menuItems, $identString, $defaultTabIndex, $foldout, $noWrap);
1638  }
1639 
1647  public function getDynTabMenuId($identString)
1648  {
1650  $id = 'DTM-' . GeneralUtility::shortMD5($identString);
1651  return $id;
1652  }
1653 
1662  public function getVersionSelector($id, $noAction = false)
1663  {
1664  if (
1667  ) {
1668  $versionGuiObj = GeneralUtility::makeInstance(\TYPO3\CMS\Version\View\VersionView::class);
1669  return $versionGuiObj->getVersionSelector($id, $noAction);
1670  }
1671  }
1672 
1680  public function getHtmlTemplate($filename)
1681  {
1682  // setting the name of the original HTML template
1683  $this->moduleTemplateFilename = $filename;
1684  if ($GLOBALS['TBE_STYLES']['htmlTemplates'][$filename]) {
1685  $filename = $GLOBALS['TBE_STYLES']['htmlTemplates'][$filename];
1686  }
1687  if (GeneralUtility::isFirstPartOfStr($filename, 'EXT:')) {
1688  $filename = GeneralUtility::getFileAbsFileName($filename, true, true);
1689  } elseif (!GeneralUtility::isAbsPath($filename)) {
1690  $filename = GeneralUtility::resolveBackPath($filename);
1691  } elseif (!GeneralUtility::isAllowedAbsPath($filename)) {
1692  $filename = '';
1693  }
1694  $htmlTemplate = '';
1695  if ($filename !== '') {
1696  $htmlTemplate = GeneralUtility::getUrl($filename);
1697  }
1698  return $htmlTemplate;
1699  }
1700 
1707  public function setModuleTemplate($filename)
1708  {
1709  $this->moduleTemplate = $this->getHtmlTemplate($filename);
1710  }
1711 
1722  public function moduleBody($pageRecord = [], $buttons = [], $markerArray = [], $subpartArray = [])
1723  {
1724  // Get the HTML template for the module
1725  $moduleBody = $this->templateService->getSubpart($this->moduleTemplate, '###FULLDOC###');
1726  // Add CSS
1727  $this->inDocStylesArray[] = 'html { overflow: hidden; }';
1728  // Get the page path for the docheader
1729  $markerArray['PAGEPATH'] = $this->getPagePath($pageRecord);
1730  // Get the page info for the docheader
1731  $markerArray['PAGEINFO'] = $this->getPageInfo($pageRecord);
1732  // Get all the buttons for the docheader
1733  $docHeaderButtons = $this->getDocHeaderButtons($buttons);
1734  // Merge docheader buttons with the marker array
1735  $markerArray = array_merge($markerArray, $docHeaderButtons);
1736  // replacing subparts
1737  foreach ($subpartArray as $marker => $content) {
1738  $moduleBody = $this->templateService->substituteSubpart($moduleBody, $marker, $content);
1739  }
1740  // adding flash messages
1741  if ($this->showFlashMessages) {
1742  $flashMessages = $this->getFlashMessages();
1743  if (!empty($flashMessages)) {
1744  $markerArray['FLASHMESSAGES'] = $flashMessages;
1745  // If there is no dedicated marker for the messages present
1746  // then force them to appear before the content
1747  if (strpos($moduleBody, '###FLASHMESSAGES###') === false) {
1748  $moduleBody = str_replace('###CONTENT###', '###FLASHMESSAGES######CONTENT###', $moduleBody);
1749  }
1750  }
1751  }
1752  // Hook for adding more markers/content to the page, like the version selector
1753  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['moduleBodyPostProcess'])) {
1754  $params = [
1755  'moduleTemplateFilename' => &$this->moduleTemplateFilename,
1756  'moduleTemplate' => &$this->moduleTemplate,
1757  'moduleBody' => &$moduleBody,
1758  'markers' => &$markerArray,
1759  'parentObject' => &$this
1760  ];
1761  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['moduleBodyPostProcess'] as $funcRef) {
1762  GeneralUtility::callUserFunction($funcRef, $params, $this);
1763  }
1764  }
1765  // Replacing all markers with the finished markers and return the HTML content
1766  return $this->templateService->substituteMarkerArray($moduleBody, $markerArray, '###|###');
1767  }
1768 
1774  public function getFlashMessages()
1775  {
1777  $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
1779  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1780  return $defaultFlashMessageQueue->renderFlashMessages();
1781  }
1782 
1790  public function renderQueuedFlashMessages(ServerRequestInterface $request, ResponseInterface $response)
1791  {
1793  $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
1795  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1796  $flashMessages = $defaultFlashMessageQueue->getAllMessagesAndFlush();
1797 
1798  $messages = [];
1799  foreach ($flashMessages as $flashMessage) {
1800  $messages[] = [
1801  'title' => $flashMessage->getTitle(),
1802  'message' => $flashMessage->getMessage(),
1803  'severity' => $flashMessage->getSeverity()
1804  ];
1805  }
1806 
1807  $response->getBody()->write(json_encode($messages));
1808  return $response;
1809  }
1810 
1817  protected function getDocHeaderButtons($buttons)
1818  {
1819  $markers = [];
1820  // Fill buttons for left and right float
1821  $floats = ['left', 'right'];
1822  foreach ($floats as $key) {
1823  // Get the template for each float
1824  $buttonTemplate = $this->templateService->getSubpart($this->moduleTemplate, '###BUTTON_GROUPS_' . strtoupper($key) . '###');
1825  // Fill the button markers in this float
1826  $buttonTemplate = $this->templateService->substituteMarkerArray($buttonTemplate, $buttons, '###|###', true);
1827  // getting the wrap for each group
1828  $buttonWrap = $this->templateService->getSubpart($this->moduleTemplate, '###BUTTON_GROUP_WRAP###');
1829  // looping through the groups (max 6) and remove the empty groups
1830  for ($groupNumber = 1; $groupNumber < 6; $groupNumber++) {
1831  $buttonMarker = '###BUTTON_GROUP' . $groupNumber . '###';
1832  $buttonGroup = $this->templateService->getSubpart($buttonTemplate, $buttonMarker);
1833  if (trim($buttonGroup)) {
1834  if ($buttonWrap) {
1835  $buttonGroup = $this->templateService->substituteMarker($buttonWrap, '###BUTTONS###', $buttonGroup);
1836  }
1837  $buttonTemplate = $this->templateService->substituteSubpart($buttonTemplate, $buttonMarker, trim($buttonGroup));
1838  }
1839  }
1840  // Replace the marker with the template and remove all line breaks (for IE compat)
1841  $markers['BUTTONLIST_' . strtoupper($key)] = str_replace(LF, '', $buttonTemplate);
1842  }
1843  // Hook for manipulating docHeaderButtons
1844  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['docHeaderButtonsHook'])) {
1845  $params = [
1846  'buttons' => $buttons,
1847  'markers' => &$markers,
1848  'pObj' => &$this
1849  ];
1850  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['docHeaderButtonsHook'] as $funcRef) {
1851  GeneralUtility::callUserFunction($funcRef, $params, $this);
1852  }
1853  }
1854  return $markers;
1855  }
1856 
1863  protected function getPagePath($pageRecord)
1864  {
1865  // Is this a real page
1866  if (is_array($pageRecord) && $pageRecord['uid']) {
1867  $title = substr($pageRecord['_thePathFull'], 0, -1);
1868  // Remove current page title
1869  $pos = strrpos($title, $pageRecord['title']);
1870  if ($pos !== false) {
1871  $title = substr($title, 0, $pos);
1872  }
1873  } else {
1874  $title = '';
1875  }
1876  // Setting the path of the page
1877  $pagePath = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.path', true) . ': <span class="typo3-docheader-pagePath">';
1878  // crop the title to title limit (or 50, if not defined)
1879  $cropLength = empty($GLOBALS['BE_USER']->uc['titleLen']) ? 50 : $GLOBALS['BE_USER']->uc['titleLen'];
1880  $croppedTitle = GeneralUtility::fixed_lgd_cs($title, -$cropLength);
1881  if ($croppedTitle !== $title) {
1882  $pagePath .= '<abbr title="' . htmlspecialchars($title) . '">' . htmlspecialchars($croppedTitle) . '</abbr>';
1883  } else {
1884  $pagePath .= htmlspecialchars($title);
1885  }
1886  $pagePath .= '</span>';
1887  return $pagePath;
1888  }
1889 
1896  protected function getPageInfo($pageRecord)
1897  {
1898  // Add icon with clickmenu, etc:
1899  // If there IS a real page
1900  if (is_array($pageRecord) && $pageRecord['uid']) {
1901  $alttext = BackendUtility::getRecordIconAltText($pageRecord, 'pages');
1902  $iconImg = '<span title="' . htmlspecialchars($alttext) . '">' . $this->iconFactory->getIconForRecord('pages', $pageRecord, Icon::SIZE_SMALL)->render() . '</span>';
1903  // Make Icon:
1904  $theIcon = BackendUtility::wrapClickMenuOnIcon($iconImg, 'pages', $pageRecord['uid']);
1905  $uid = $pageRecord['uid'];
1906  $title = BackendUtility::getRecordTitle('pages', $pageRecord);
1907  } else {
1908  // On root-level of page tree
1909  // Make Icon
1910  $iconImg = '<span title="' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) . '">' . $this->iconFactory->getIcon('apps-pagetree-root', Icon::SIZE_SMALL)->render() . '</span>';
1911  if ($GLOBALS['BE_USER']->user['admin']) {
1912  $theIcon = BackendUtility::wrapClickMenuOnIcon($iconImg, 'pages', 0);
1913  } else {
1914  $theIcon = $iconImg;
1915  }
1916  $uid = '0';
1917  $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
1918  }
1919  // Setting icon with clickmenu + uid
1920  $pageInfo = $theIcon . '<strong>' . htmlspecialchars($title) . '&nbsp;[' . $uid . ']</strong>';
1921  return $pageInfo;
1922  }
1923 
1934  public function collapseableSection($title, $html, $id, $saveStatePointer = '')
1935  {
1937  $hasSave = (bool)$saveStatePointer;
1938  $collapsedStyle = ($collapsedClass = '');
1939  if ($hasSave) {
1941  $userSettingsController = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\UserSettingsController::class);
1942  $value = $userSettingsController->process('get', $saveStatePointer . '.' . $id);
1943  if ($value) {
1944  $collapsedStyle = ' style="display: none"';
1945  $collapsedClass = ' collapsed';
1946  } else {
1947  $collapsedStyle = '';
1948  $collapsedClass = ' expanded';
1949  }
1950  }
1951  $this->pageRenderer->loadExtJS();
1952  $this->pageRenderer->addExtOnReadyCode('
1953  Ext.select("h2.section-header").each(function(element){
1954  element.on("click", function(event, tag) {
1955  var state = 0,
1956  el = Ext.fly(tag),
1957  div = el.next("div"),
1958  saveKey = el.getAttribute("rel");
1959  if (el.hasClass("collapsed")) {
1960  el.removeClass("collapsed").addClass("expanded");
1961  div.slideIn("t", {
1962  easing: "easeIn",
1963  duration: .5
1964  });
1965  } else {
1966  el.removeClass("expanded").addClass("collapsed");
1967  div.slideOut("t", {
1968  easing: "easeOut",
1969  duration: .5,
1970  remove: false,
1971  useDisplay: true
1972  });
1973  state = 1;
1974  }
1975  if (saveKey) {
1976  try {
1977  top.TYPO3.Storage.Persistent.set(saveKey + "." + tag.id, state);
1978  } catch(e) {}
1979  }
1980  });
1981  });
1982  ');
1983  return '
1984  <h2 id="' . $id . '" class="section-header' . $collapsedClass . '" rel="' . $saveStatePointer . '"> ' . $title . '</h2>
1985  <div' . $collapsedStyle . '>' . $html . '</div>
1986  ';
1987  }
1988 
1994  protected function getBackendFavicon()
1995  {
1996  return $GLOBALS['TBE_STYLES']['favicon'] ?: ExtensionManagementUtility::extRelPath('backend') . 'Resources/Public/Icons/favicon.ico';
1997  }
1998 }
static devLog($msg, $extKey, $severity=0, $dataVar=false)
moduleBody($pageRecord=[], $buttons=[], $markerArray=[], $subpartArray=[])
static compileSelectedGetVarsFromArray($varList, array $getArray, $GPvarAlt=true)
getHeader($table, $row, $path, $noViewPageIcon=false, $tWrap=['', ''], $enableClickMenu=true)
static getFilesInDir($path, $extensionList='', $prependPath=false, $order='', $excludePattern='')
addStyleSheet($key, $href, $title='', $relation='stylesheet')
static isFirstPartOfStr($str, $partStr)
makeShortcutIcon($gvList, $setList, $modName, $motherModName='', $classes='')
formWidth($size=48, $textarea=false, $styleOverride='')
static BEgetRootLine($uid, $clause='', $workspaceOL=false)
section($label, $text, $nostrtoupper=false, $sH=false, $type=0, $allowHTMLinHeader=false)
static linkThisScript(array $getParams=[])
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
getResourceHeader(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, $tWrap=['', ''], $enableClickMenu=true)
getTabMenu($mainParams, $elementName, $currentValue, $menuItems, $script='', $addparams='')
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=false, $rawurlencodeParamName=false)
getDynTabMenu($menuItems, $identString, $toggle=0, $foldout=false, $noWrap=true, $fullWidth=false, $defaultTabIndex=1, $tabBehaviour=1)
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
getDragDropCode($table, $additionalJavaScriptCode='')
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
static getUrl($url, $includeHeader=0, $requestHeaders=false, &$report=null)
static viewOnClick($pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
static getRecordIconAltText($row, $table='pages')
static fixed_lgd_cs($string, $chars, $appendString='...')
$uid
Definition: server.php:38
static getFileAbsFileName($filename, $onlyRelative=true, $relToTYPO3_mainDir=false)
useCompatibilityTag($useCompatibilityTag=true)
static wrapClickMenuOnIcon( $content, $table, $uid=0, $listFrame=true, $addParams='', $enDisItems='', $returnTagParameters=false)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
sectionHeader($label, $sH=false, $addAttrib='')
static getLinkToDataHandlerAction($parameters, $redirectUrl='')
wrapClickMenuOnIcon($content, $table, $uid=0, $listFr=true, $addParams='', $enDisItems='', $returnTagParameters=false)
getDynamicTabMenu(array $menuItems, $identString, $defaultTabIndex=1, $collapseable=false, $wrapContent=true, $storeLastActiveTab=true)