TYPO3 CMS  TYPO3_6-2
DocumentTemplate.php
Go to the documentation of this file.
1 <?php
3 
23 
42 
43  // Vars you typically might want to/should set from outside after making instance of this class:
44  // 'backPath' pointing back to the PATH_typo3
48  public $backPath = '';
49 
50  // This can be set to the HTML-code for a formtag. Useful when you need a form to span the whole page; Inserted exactly after the body-tag.
54  public $form = '';
55 
56  // Similar to $JScode (see below) but used as an associative array to prevent double inclusion of JS code. This is used to include certain external Javascript libraries before the inline JS code. <script>-Tags are not wrapped around automatically
60  public $JScodeLibArray = array();
61 
62  // Additional header code (eg. a JavaScript section) could be accommulated in this var. It will be directly outputted in the header.
66  public $JScode = '';
67 
68  // Additional header code for ExtJS. It will be included in document header and inserted in a Ext.onReady(function()
72  public $extJScode = '';
73 
74  // Similar to $JScode but for use as array with associative keys to prevent double inclusion of JS code. a <script> tag is automatically wrapped around.
78  public $JScodeArray = array('jumpToUrl' => '
79 function jumpToUrl(URL) {
80  window.location.href = URL;
81  return false;
82 }
83  ');
84 
85  // Additional 'page-end' code could be accumulated in this var. It will be outputted at the end of page before </body> and some other internal page-end code.
89  public $postCode = '';
90 
91  // Doc-type used in the header. Default is xhtml_trans. You can also set it to 'html_3', 'xhtml_strict' or 'xhtml_frames'.
95  public $docType = '';
96 
97  // HTML template with markers for module
101  public $moduleTemplate = '';
102 
103  // the base file (not overlaid by TBE_STYLES) for the current module, useful for hooks when finding out which modules is rendered currently
104  protected $moduleTemplateFilename = '';
105 
106  // Other vars you can change, but less frequently used:
107  // Script ID.
111  public $scriptID = '';
112 
113  // Id which can be set for the body tag. Default value is based on script ID
117  public $bodyTagId = '';
118 
119  // You can add additional attributes to the body-tag through this variable.
123  public $bodyTagAdditions = '';
124 
125  // Additional CSS styles which will be added to the <style> section in the header
129  public $inDocStyles = '';
130 
131  // Like $inDocStyles but for use as array with associative keys to prevent double inclusion of css code
135  public $inDocStylesArray = array();
136 
137  // Compensation for large documents (used in \TYPO3\CMS\Backend\Form\FormEngine)
141  public $form_largeComp = 1.33;
142 
143  // If set, then a JavaScript section will be outputted in the bottom of page which will try and update the top.busy session expiry object.
147  public $endJS = 1;
148 
149  // TYPO3 Colorscheme.
150  // If you want to change this, please do so through a skin using the global var $GLOBALS['TBE_STYLES']
151  // Light background color
155  public $bgColor = '#F7F3EF';
156 
157  // Steel-blue
161  public $bgColor2 = '#9BA1A8';
162 
163  // dok.color
167  public $bgColor3 = '#F6F2E6';
168 
169  // light tablerow background, brownish
173  public $bgColor4 = '#D9D5C9';
174 
175  // light tablerow background, greenish
179  public $bgColor5 = '#ABBBB4';
180 
181  // light tablerow background, yellowish, for section headers. Light.
185  public $bgColor6 = '#E7DBA8';
186 
190  public $hoverColor = '#254D7B';
191 
192  // Filename of stylesheet (relative to PATH_typo3)
196  public $styleSheetFile = '';
197 
198  // Filename of stylesheet #2 - linked to right after the $this->styleSheetFile script (relative to PATH_typo3)
202  public $styleSheetFile2 = '';
203 
204  // Filename of a post-stylesheet - included right after all inline styles.
208  public $styleSheetFile_post = '';
209 
210  // Background image of page (relative to PATH_typo3)
214  public $backGroundImage = '';
215 
216  // Inline css styling set from TBE_STYLES array
221 
227  protected $useCompatibilityTag = TRUE;
228 
234  protected $xUaCompatibilityVersion = 'IE=10';
235 
236  // Skinning
237  // stylesheets from core
238  protected $stylesheetsCore = array(
239  'structure' => 'sysext/backend/Resources/Public/Css/structure/',
240  'visual' => 'sysext/backend/Resources/Public/Css/visual/',
241  'generatedSprites' => '../typo3temp/sprites/'
242  );
243 
244  // Include these CSS directories from skins by default
245  protected $stylesheetsSkins = array(
246  'structure' => 'Resources/Public/Css/structure/',
247  'visual' => 'Resources/Public/Css/visual/'
248  );
249 
255  protected $jsFiles = array(
256  );
257 
263  protected $jsFilesNoConcatenation = array(
264  'modernizr' => 'contrib/modernizr/modernizr.min.js'
265  );
266 
267  // DEV:
268  // Will output the parsetime of the scripts in milliseconds (for admin-users). Set this to FALSE when releasing TYPO3. Only for dev.
272  public $parseTimeFlag = 0;
273 
277  protected $charset = 'utf-8';
278 
279  // Internal: Indicates if a <div>-output section is open
283  public $sectionFlag = 0;
284 
285  // (Default) Class for wrapping <DIV>-tag of page. Is set in class extensions.
289  public $divClass = '';
290 
294  public $pageHeaderBlock = '';
295 
299  public $endOfPageJsBlock = '';
300 
304  public $hasDocheader = TRUE;
305 
309  protected $pageRenderer;
310 
311  // Alternative template file
313 
314  protected $extDirectStateProvider = FALSE;
315 
321  public $showFlashMessages = TRUE;
322 
323  const STATUS_ICON_ERROR = 3;
326  const STATUS_ICON_OK = -1;
331  public function __construct() {
332  // Initializes the page rendering object:
333  $this->getPageRenderer();
334  // Setting default scriptID:
335  if (($temp_M = (string) GeneralUtility::_GET('M')) && $GLOBALS['TBE_MODULES']['_PATHS'][$temp_M]) {
336  $this->scriptID = preg_replace('/^.*\\/(sysext|ext)\\//', 'ext/', $GLOBALS['TBE_MODULES']['_PATHS'][$temp_M] . 'index.php');
337  } else {
338  $this->scriptID = preg_replace('/^.*\\/(sysext|ext)\\//', 'ext/', \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(PATH_thisScript));
339  }
340  if (TYPO3_mainDir != 'typo3/' && substr($this->scriptID, 0, strlen(TYPO3_mainDir)) == TYPO3_mainDir) {
341  // This fixes if TYPO3_mainDir has been changed so the script ids are STILL "typo3/..."
342  $this->scriptID = 'typo3/' . substr($this->scriptID, strlen(TYPO3_mainDir));
343  }
344  $this->bodyTagId = preg_replace('/[^A-Za-z0-9-]/', '-', $this->scriptID);
345  // Individual configuration per script? If so, make a recursive merge of the arrays:
346  if (is_array($GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID])) {
347  // Make copy
348  $ovr = $GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID];
349  // merge styles.
351  // Have to unset - otherwise the second instantiation will do it again!
352  unset($GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID]);
353  }
354  // Color scheme:
355  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor']) {
356  $this->bgColor = $GLOBALS['TBE_STYLES']['mainColors']['bgColor'];
357  }
358  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor1']) {
359  $this->bgColor1 = $GLOBALS['TBE_STYLES']['mainColors']['bgColor1'];
360  }
361  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor2']) {
362  $this->bgColor2 = $GLOBALS['TBE_STYLES']['mainColors']['bgColor2'];
363  }
364  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor3']) {
365  $this->bgColor3 = $GLOBALS['TBE_STYLES']['mainColors']['bgColor3'];
366  }
367  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor4']) {
368  $this->bgColor4 = $GLOBALS['TBE_STYLES']['mainColors']['bgColor4'];
369  }
370  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor5']) {
371  $this->bgColor5 = $GLOBALS['TBE_STYLES']['mainColors']['bgColor5'];
372  }
373  if ($GLOBALS['TBE_STYLES']['mainColors']['bgColor6']) {
374  $this->bgColor6 = $GLOBALS['TBE_STYLES']['mainColors']['bgColor6'];
375  }
376  if ($GLOBALS['TBE_STYLES']['mainColors']['hoverColor']) {
377  $this->hoverColor = $GLOBALS['TBE_STYLES']['mainColors']['hoverColor'];
378  }
379  // Main Stylesheets:
380  if ($GLOBALS['TBE_STYLES']['stylesheet']) {
381  $this->styleSheetFile = $GLOBALS['TBE_STYLES']['stylesheet'];
382  }
383  if ($GLOBALS['TBE_STYLES']['stylesheet2']) {
384  $this->styleSheetFile2 = $GLOBALS['TBE_STYLES']['stylesheet2'];
385  }
386  if ($GLOBALS['TBE_STYLES']['styleSheetFile_post']) {
387  $this->styleSheetFile_post = $GLOBALS['TBE_STYLES']['styleSheetFile_post'];
388  }
389  if ($GLOBALS['TBE_STYLES']['inDocStyles_TBEstyle']) {
390  $this->inDocStyles_TBEstyle = $GLOBALS['TBE_STYLES']['inDocStyles_TBEstyle'];
391  }
392  // include all stylesheets
393  foreach ($this->getSkinStylesheetDirectories() as $stylesheetDirectory) {
394  $this->addStylesheetDirectory($stylesheetDirectory);
395  }
396  // Background image
397  if ($GLOBALS['TBE_STYLES']['background']) {
398  $this->backGroundImage = $GLOBALS['TBE_STYLES']['background'];
399  }
400  }
401 
407  public function getPageRenderer() {
408  if (!isset($this->pageRenderer)) {
409  $this->pageRenderer = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Page\\PageRenderer');
410  $this->pageRenderer->setLanguage($GLOBALS['LANG']->lang);
411  $this->pageRenderer->addCssLibrary($GLOBALS['BACK_PATH'] . 'contrib/normalize/normalize.css', 'stylesheet', 'all', '', TRUE, TRUE);
412  $this->pageRenderer->enableConcatenateFiles();
413  $this->pageRenderer->enableCompressCss();
414  $this->pageRenderer->enableCompressJavascript();
415  // Add all JavaScript files defined in $this->jsFiles to the PageRenderer
416  foreach ($this->jsFilesNoConcatenation as $file) {
417  $this->pageRenderer->addJsFile(
418  $GLOBALS['BACK_PATH'] . $file,
419  'text/javascript',
420  TRUE,
421  FALSE,
422  '',
423  TRUE
424  );
425  }
426  // Add all JavaScript files defined in $this->jsFiles to the PageRenderer
427  foreach ($this->jsFiles as $file) {
428  $this->pageRenderer->addJsFile($GLOBALS['BACK_PATH'] . $file);
429  }
430  }
431  if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] === 1) {
432  $this->pageRenderer->enableDebugMode();
433  }
434  return $this->pageRenderer;
435  }
436 
442  public function setExtDirectStateProvider() {
443  $this->extDirectStateProvider = TRUE;
444  }
445 
446  /*****************************************
447  *
448  * EVALUATION FUNCTIONS
449  * Various centralized processing
450  *
451  *****************************************/
467  public function wrapClickMenuOnIcon($str, $table, $uid = 0, $listFr = TRUE, $addParams = '', $enDisItems = '', $returnOnClick = FALSE) {
468  $backPath = rawurlencode($this->backPath) . '|' . GeneralUtility::shortMD5(($this->backPath . '|' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']));
469  $onClick = 'Clickmenu.show("' . $table . '","' . ($uid !== 0 ? $uid : '') . '","' . strval($listFr) . '","' . str_replace('+', '%2B', $enDisItems) . '","' . str_replace('&', '&amp;', addcslashes($backPath, '"')) . '","' . str_replace('&', '&amp;', addcslashes($addParams, '"')) . '");return false;';
470  return $returnOnClick ? $onClick : '<a href="#" onclick="' . htmlspecialchars($onClick) . '" oncontextmenu="this.click();return false;">' . $str . '</a>';
471  }
472 
485  public function viewPageIcon($id, $backPath, $addParams = 'hspace="3"') {
486  // If access to Web>List for user, then link to that module.
487  $str = BackendUtility::getListViewLink(array(
488  'id' => $id,
489  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
490  ), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.showList'));
491  // Make link to view page
492  $str .= '<a href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($id, $backPath, BackendUtility::BEgetRootLine($id))) . '">' . '<img' . IconUtility::skinImg($backPath, 'gfx/zoom.gif', 'width="12" height="12"') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', TRUE) . '"' . ($addParams ? ' ' . trim($addParams) : '') . ' hspace="3" alt="" />' . '</a>';
493  return $str;
494  }
495 
506  public function issueCommand($params, $redirectUrl = '') {
507  $redirectUrl = $redirectUrl ? $redirectUrl : GeneralUtility::getIndpEnv('REQUEST_URI');
508  $commandUrl = $this->backPath . 'tce_db.php?' . $params . '&redirect=' . ($redirectUrl == -1 ? '\'+T3_THIS_LOCATION+\'' : rawurlencode($redirectUrl)) . '&vC=' . rawurlencode($GLOBALS['BE_USER']->veriCode()) . BackendUtility::getUrlToken('tceAction') . '&prErr=1&uPT=1';
509  return $commandUrl;
510  }
511 
520  public function isCMlayers() {
522  return !$GLOBALS['BE_USER']->uc['disableCMlayers'] && !($GLOBALS['CLIENT']['SYSTEM'] == 'mac' && $GLOBALS['CLIENT']['BROWSER'] == 'Opera');
523  }
524 
540  public function getHeader($table, $row, $path, $noViewPageIcon = FALSE, $tWrap = array('', ''), $enableClickMenu = TRUE) {
541  $viewPage = '';
542  if (is_array($row) && $row['uid']) {
543  $iconImgTag = IconUtility::getSpriteIconForRecord($table, $row, array('title' => htmlspecialchars($path)));
544  $title = strip_tags(BackendUtility::getRecordTitle($table, $row));
545  $viewPage = $noViewPageIcon ? '' : $this->viewPageIcon($row['uid'], $this->backPath, '');
546  if ($table == 'pages') {
547  $path .= ' - ' . BackendUtility::titleAttribForPages($row, '', 0);
548  }
549  } else {
550  $iconImgTag = IconUtility::getSpriteIcon('apps-pagetree-page-domain', array('title' => htmlspecialchars($path)));
551  $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
552  }
553 
554  if ($enableClickMenu) {
555  $iconImgTag = $this->wrapClickMenuOnIcon($iconImgTag, $table, $row['uid']);
556  }
557 
558  return '<span class="typo3-moduleHeader">' . $iconImgTag . $viewPage . $tWrap[0] . htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, 45)) . $tWrap[1] . '</span>';
559  }
560 
570  public function getResourceHeader(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, $tWrap = array('', ''), $enableClickMenu = TRUE) {
571  try {
572  $path = $resource->getStorage()->getName() . $resource->getParentFolder()->getIdentifier();
573  $iconImgTag = IconUtility::getSpriteIconForResource($resource, array('title' => htmlspecialchars($path)));
574  } catch (\TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException $e) {
575  $iconImgTag = '';
576  }
577 
578  if ($enableClickMenu && ($resource instanceof \TYPO3\CMS\Core\Resource\File)) {
579  $metaData = $resource->_getMetaData();
580  $iconImgTag = $this->wrapClickMenuOnIcon($iconImgTag, 'sys_file_metadata', $metaData['uid']);
581  }
582 
583  return '<span class="typo3-moduleHeader">' . $iconImgTag . $tWrap[0] . htmlspecialchars(GeneralUtility::fixed_lgd_cs($resource->getName(), 45)) . $tWrap[1] . '</span>';
584  }
585 
596  public function getFileheader($title, $path, $iconfile) {
598  $fileInfo = GeneralUtility::split_fileref($title);
599  $title = htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileInfo['path'], -35)) . '<strong>' . htmlspecialchars($fileInfo['file']) . '</strong>';
600  return '<span class="typo3-moduleHeader"><img' . IconUtility::skinImg($this->backPath, $iconfile, 'width="18" height="16"') . ' title="' . htmlspecialchars($path) . '" alt="" />' . $title . '</span>';
601  }
602 
613  public function makeShortcutIcon($gvList, $setList, $modName, $motherModName = '') {
615  $storeUrl = $this->makeShortcutUrl($gvList, $setList);
616  $pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
617  // Add the module identifier automatically if typo3/mod.php is used:
618  if (preg_match('/typo3\\/mod\\.php$/', $pathInfo['path']) && isset($GLOBALS['TBE_MODULES']['_PATHS'][$modName])) {
619  $storeUrl = '&M=' . $modName . $storeUrl;
620  }
621  if ((int)$motherModName === 1) {
622  $mMN = '&motherModName=\'+top.currentModuleLoaded+\'';
623  } elseif ($motherModName) {
624  $mMN = '&motherModName=' . rawurlencode($motherModName);
625  } else {
626  $mMN = '';
627  }
628  $onClick = 'top.ShortcutManager.createShortcut('
629  . GeneralUtility::quoteJSvalue($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark')) . ', '
631  . GeneralUtility::quoteJSvalue(rawurlencode($modName)) . ', '
632  . GeneralUtility::quoteJSvalue(rawurlencode($pathInfo['path'] . '?' . $storeUrl) . $mMN) . ');return false;';
633  $sIcon = '<a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark', TRUE) . '">' . IconUtility::getSpriteIcon('actions-system-shortcut-new') . '</a>';
634  return $sIcon;
635  }
636 
648  public function makeShortcutUrl($gvList, $setList) {
649  $GET = GeneralUtility::_GET();
650  $storeArray = array_merge(GeneralUtility::compileSelectedGetVarsFromArray($gvList, $GET), array('SET' => GeneralUtility::compileSelectedGetVarsFromArray($setList, (array) $GLOBALS['SOBE']->MOD_SETTINGS)));
651  $storeUrl = GeneralUtility::implodeArrayForUrl('', $storeArray);
652  return $storeUrl;
653  }
654 
666  public function formWidth($size = 48, $textarea = FALSE, $styleOverride = '') {
667  return ' style="' . ($styleOverride ?: 'width:' . ceil($size * 9.58) . 'px;') . '"';
668  }
669 
685  public function formWidthText($size = 48, $styleOverride = '', $wrap = '') {
687  return $this->formWidth($size, TRUE, $styleOverride);
688  }
689 
699  public function redirectUrls($thisLocation = '') {
700  $thisLocation = $thisLocation ? $thisLocation : GeneralUtility::linkThisScript(array(
701  'CB' => '',
702  'SET' => '',
703  'cmd' => '',
704  'popViewId' => ''
705  ));
706  $out = '
707  var T3_RETURN_URL = \'' . str_replace('%20', '', rawurlencode(GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl')))) . '\';
708  var T3_THIS_LOCATION = \'' . str_replace('%20', '', rawurlencode($thisLocation)) . '\';
709  ';
710  return $out;
711  }
712 
722  public function formatTime($tstamp, $type) {
723  $dateStr = '';
724  switch ($type) {
725  case 1:
726  $dateStr = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $tstamp);
727  break;
728  case 10:
729  $dateStr = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $tstamp);
730  break;
731  }
732  return $dateStr;
733  }
734 
742  public function parseTime() {
743  if ($this->parseTimeFlag && $GLOBALS['BE_USER']->isAdmin()) {
744  return '<p>(ParseTime: ' . (GeneralUtility::milliseconds() - $GLOBALS['PARSETIME_START']) . ' ms</p>
745  <p>REQUEST_URI-length: ' . strlen(GeneralUtility::getIndpEnv('REQUEST_URI')) . ')</p>';
746  }
747  }
748 
755  public function useCompatibilityTag($useCompatibilityTag = TRUE) {
756  $this->useCompatibilityTag = (bool) $useCompatibilityTag;
757  }
758 
759  /*****************************************
760  *
761  * PAGE BUILDING FUNCTIONS.
762  * Use this to build the HTML of your backend modules
763  *
764  *****************************************/
775  public function startPage($title, $includeCsh = TRUE) {
776  // hook pre start page
777  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'])) {
778  $preStartPageHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'];
779  if (is_array($preStartPageHook)) {
780  $hookParameters = array(
781  'title' => &$title
782  );
783  foreach ($preStartPageHook as $hookFunction) {
784  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
785  }
786  }
787  }
788  $this->pageRenderer->backPath = $this->backPath;
789  // alternative template for Header and Footer
790  if ($this->pageHeaderFooterTemplateFile) {
791  $file = GeneralUtility::getFileAbsFileName($this->pageHeaderFooterTemplateFile, TRUE);
792  if ($file) {
793  $this->pageRenderer->setTemplateFile($file);
794  }
795  }
796  // Send HTTP header for selected charset. Added by Robert Lemke 23.10.2003
797  header('Content-Type:text/html;charset=' . $this->charset);
798  // Standard HTML tag
799  $htmlTag = '<html xmlns="http://www.w3.org/1999/xhtml">';
800  switch ($this->docType) {
801  case 'html_3':
802  $headerStart = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">';
803  $htmlTag = '<html>';
804  // Disable rendering of XHTML tags
805  $this->pageRenderer->setRenderXhtml(FALSE);
806  break;
807  case 'xhtml_strict':
808  $headerStart = '<!DOCTYPE html
809  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
810  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
811  break;
812  case 'xhtml_frames':
813  $headerStart = '<!DOCTYPE html
814  PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
815  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
816  break;
817  case 'xhtml_trans':
818  $headerStart = '<!DOCTYPE html
819  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
820  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
821  break;
822  case 'html5':
823 
824  default:
825  // The fallthrough is intended as HTML5, as this is the default for the BE since TYPO3 4.5
826  $headerStart = '<!DOCTYPE html>' . LF;
827  $htmlTag = '<html>';
828  // Disable rendering of XHTML tags
829  $this->pageRenderer->setRenderXhtml(FALSE);
830  }
831  $this->pageRenderer->setHtmlTag($htmlTag);
832  // This loads the tabulator-in-textarea feature. It automatically modifies
833  // every textarea which is found.
834  if (!$GLOBALS['BE_USER']->uc['disableTabInTextarea']) {
835  $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/tab.js');
836  }
837  // Include the JS for the Context Sensitive Help
838  if ($includeCsh) {
839  $this->loadCshJavascript();
840  }
841  // Get the browser info
842  $browserInfo = \TYPO3\CMS\Core\Utility\ClientUtility::getBrowserInfo(GeneralUtility::getIndpEnv('HTTP_USER_AGENT'));
843  // Set the XML prologue
844  $xmlPrologue = '<?xml version="1.0" encoding="' . $this->charset . '"?>';
845  // Set the XML stylesheet
846  $xmlStylesheet = '<?xml-stylesheet href="#internalStyle" type="text/css"?>';
847  // Add the XML prologue for XHTML doctypes
848  if (strpos($this->docType, 'xhtml') !== FALSE) {
849  // Put the XML prologue before or after the doctype declaration according to browser
850  if ($browserInfo['browser'] === 'msie' && $browserInfo['version'] < 7) {
851  $headerStart = $headerStart . LF . $xmlPrologue;
852  } else {
853  $headerStart = $xmlPrologue . LF . $headerStart;
854  }
855  // Add the xml stylesheet according to doctype
856  if ($this->docType !== 'xhtml_frames') {
857  $headerStart = $headerStart . LF . $xmlStylesheet;
858  }
859  }
860  $this->pageRenderer->setXmlPrologAndDocType($headerStart);
861  $this->pageRenderer->setHeadTag('<head>' . LF . '<!-- TYPO3 Script ID: ' . htmlspecialchars($this->scriptID) . ' -->');
862  $this->pageRenderer->setCharSet($this->charset);
863  $this->pageRenderer->addMetaTag($this->generator());
864  $this->pageRenderer->addMetaTag('<meta name="robots" content="noindex,follow" />');
865  $this->pageRenderer->setFavIcon($this->getBackendFavicon());
866  if ($this->useCompatibilityTag) {
867  $this->pageRenderer->addMetaTag($this->xUaCompatible($this->xUaCompatibilityVersion));
868  }
869  $this->pageRenderer->setTitle($title);
870  // add docstyles
871  $this->docStyle();
872  if ($this->extDirectStateProvider) {
873  $this->pageRenderer->addJsFile($this->backPath . 'sysext/backend/Resources/Public/JavaScript/ExtDirect.StateProvider.js');
874  }
875  // Add jsCode for overriding the console with a debug panel connection
876  $this->pageRenderer->addJsInlineCode('consoleOverrideWithDebugPanel', 'if (typeof top.Ext === "object") {
877  top.Ext.onReady(function() {
878  if (typeof console === "undefined") {
879  if (top && top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.DebugConsole) {
880  console = top.TYPO3.Backend.DebugConsole;
881  } else {
882  console = {
883  log: Ext.log,
884  info: Ext.log,
885  warn: Ext.log,
886  error: Ext.log
887  };
888  }
889  }
890  });
891  }
892  ', FALSE);
893  $this->pageRenderer->addHeaderData($this->JScode);
894  foreach ($this->JScodeArray as $name => $code) {
895  $this->pageRenderer->addJsInlineCode($name, $code, FALSE);
896  }
897  if (count($this->JScodeLibArray)) {
898  foreach ($this->JScodeLibArray as $library) {
899  $this->pageRenderer->addHeaderData($library);
900  }
901  }
902  if ($this->extJScode) {
903  $this->pageRenderer->addExtOnReadyCode($this->extJScode);
904  }
905  // hook for additional headerData
906  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'])) {
907  $preHeaderRenderHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'];
908  if (is_array($preHeaderRenderHook)) {
909  $hookParameters = array(
910  'pageRenderer' => &$this->pageRenderer
911  );
912  foreach ($preHeaderRenderHook as $hookFunction) {
913  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
914  }
915  }
916  }
917  // Construct page header.
918  $str = $this->pageRenderer->render(PageRenderer::PART_HEADER);
919  $this->JScodeLibArray = array();
920  $this->JScode = ($this->extJScode = '');
921  $this->JScodeArray = array();
922  $this->endOfPageJsBlock = $this->pageRenderer->render(PageRenderer::PART_FOOTER);
923  if ($this->docType == 'xhtml_frames') {
924  return $str;
925  } else {
926  $str .= $this->docBodyTagBegin() . ($this->divClass ? '
927 
928 <!-- Wrapping DIV-section for whole page BEGIN -->
929 <div class="' . $this->divClass . '">
930 ' : '') . trim($this->form);
931  }
932  return $str;
933  }
934 
942  public function endPage() {
943  $str = $this->sectionEnd() . $this->postCode . $this->endPageJS() . $this->wrapScriptTags(BackendUtility::getUpdateSignalCode()) . $this->parseTime() . ($this->form ? '
944 </form>' : '');
945  // If something is in buffer like debug, put it to end of page
946  if (ob_get_contents()) {
947  $str .= ob_get_clean();
948  if (!headers_sent()) {
949  header('Content-Encoding: None');
950  }
951  }
952  if ($this->docType !== 'xhtml_frames') {
953  $str .= ($this->divClass ? '
954 
955 <!-- Wrapping DIV-section for whole page END -->
956 </div>' : '') . $this->endOfPageJsBlock;
957  }
958  // Logging: Can't find better place to put it:
959  if (TYPO3_DLOG) {
960  GeneralUtility::devLog('END of BACKEND session', 'TYPO3\\CMS\\Backend\\Template\\DocumentTemplate', 0, array('_FLUSH' => TRUE));
961  }
962  return $str;
963  }
964 
973  public function render($title, $content, $includeCsh = TRUE) {
974  $pageContent = $this->startPage($title, $includeCsh);
975  $pageContent .= $content;
976  $pageContent .= $this->endPage();
977  return $this->insertStylesAndJS($pageContent);
978  }
979 
988  public function header($text) {
989  $str = '
990 
991  <!-- MAIN Header in page top -->
992  <h1>' . htmlspecialchars($text) . '</h1>
993 ';
994  return $this->sectionEnd() . $str;
995  }
996 
1010  public function section($label, $text, $nostrtoupper = FALSE, $sH = FALSE, $type = 0, $allowHTMLinHeader = FALSE) {
1011  $str = '';
1012  // Setting header
1013  if ($label) {
1014  if (!$allowHTMLinHeader) {
1015  $label = htmlspecialchars($label);
1016  }
1017  $str .= $this->sectionHeader($this->icons($type) . $label, $sH, $nostrtoupper ? '' : ' class="uppercase"');
1018  }
1019  // Setting content
1020  $str .= '
1021 
1022  <!-- Section content -->
1023 ' . $text;
1024  return $this->sectionBegin() . $str;
1025  }
1026 
1035  public function divider($dist) {
1036  $dist = (int)$dist;
1037  $str = '
1038 
1039  <!-- DIVIDER -->
1040  <hr style="margin-top: ' . $dist . 'px; margin-bottom: ' . $dist . 'px;" />
1041 ';
1042  return $this->sectionEnd() . $str;
1043  }
1044 
1052  public function spacer($dist) {
1053  if ($dist > 0) {
1054  return '
1055 
1056  <!-- Spacer element -->
1057  <div style="padding-top: ' . (int)$dist . 'px;"></div>
1058 ';
1059  }
1060  }
1061 
1072  public function sectionHeader($label, $sH = FALSE, $addAttrib = '') {
1073  $tag = $sH ? 'h2' : 'h3';
1074  if ($addAttrib && $addAttrib[0] !== ' ') {
1075  $addAttrib = ' ' . $addAttrib;
1076  }
1077  $str = '
1078 
1079  <!-- Section header -->
1080  <' . $tag . $addAttrib . '>' . $label . '</' . $tag . '>
1081 ';
1082  return $this->sectionBegin() . $str;
1083  }
1084 
1093  public function sectionBegin() {
1094  if (!$this->sectionFlag) {
1095  $this->sectionFlag = 1;
1096  $str = '
1097 
1098  <!-- ***********************
1099  Begin output section.
1100  *********************** -->
1101  <div>
1102 ';
1103  return $str;
1104  } else {
1105  return '';
1106  }
1107  }
1108 
1117  public function sectionEnd() {
1118  if ($this->sectionFlag) {
1119  $this->sectionFlag = 0;
1120  return '
1121  </div>
1122  <!-- *********************
1123  End output section.
1124  ********************* -->
1125 ';
1126  } else {
1127  return '';
1128  }
1129  }
1130 
1138  public function endPageJS() {
1139  return $this->endJS ? '
1140  <script type="text/javascript">
1141  /*<![CDATA[*/
1142  if (top.busy && top.busy.loginRefreshed) {
1143  top.busy.loginRefreshed();
1144  }
1145  /*]]>*/
1146  </script>' : '';
1147  }
1148 
1156  public function docBodyTagBegin() {
1157  $bodyContent = 'body onclick="if (top.menuReset) top.menuReset();" ' . trim(($this->bodyTagAdditions . ($this->bodyTagId ? ' id="' . $this->bodyTagId . '"' : '')));
1158  return '<' . trim($bodyContent) . '>';
1159  }
1160 
1167  public function docStyle() {
1168  // Request background image:
1169  if ($this->backGroundImage) {
1170  $this->inDocStylesArray[] = ' BODY { background-image: url(' . $this->backPath . $this->backGroundImage . '); }';
1171  }
1172  // Add inDoc styles variables as well:
1173  $this->inDocStylesArray[] = $this->inDocStyles;
1174  $this->inDocStylesArray[] = $this->inDocStyles_TBEstyle;
1175  // Implode it all:
1176  $inDocStyles = implode(LF, $this->inDocStylesArray);
1177 
1178  // Reset styles so they won't be added again in insertStylesAndJS()
1179  $this->inDocStylesArray = array();
1180  $this->inDocStyles = '';
1181  $this->inDocStyles_TBEstyle = '';
1182 
1183  if ($this->styleSheetFile) {
1184  $this->pageRenderer->addCssFile($this->backPath . $this->styleSheetFile);
1185  }
1186  if ($this->styleSheetFile2) {
1187  $this->pageRenderer->addCssFile($this->backPath . $this->styleSheetFile2);
1188  }
1189  $this->pageRenderer->addCssInlineBlock('inDocStyles', $inDocStyles . LF . '/*###POSTCSSMARKER###*/');
1190  if ($this->styleSheetFile_post) {
1191  $this->pageRenderer->addCssFile($this->backPath . $this->styleSheetFile_post);
1192  }
1193  }
1194 
1205  public function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
1206  if (strpos($href, '://') !== FALSE || $href[0] === '/') {
1207  $file = $href;
1208  } else {
1209  $file = $this->backPath . $href;
1210  }
1211  $this->pageRenderer->addCssFile($file, $relation, 'screen', $title);
1212  }
1213 
1221  public function addStyleSheetDirectory($path) {
1222  // Calculation needed, when TYPO3 source is used via a symlink
1223  // absolute path to the stylesheets
1224  $filePath = dirname(GeneralUtility::getIndpEnv('SCRIPT_FILENAME')) . '/' . $GLOBALS['BACK_PATH'] . $path;
1225  // Clean the path
1226  $resolvedPath = GeneralUtility::resolveBackPath($filePath);
1227  // Read all files in directory and sort them alphabetically
1228  $files = GeneralUtility::getFilesInDir($resolvedPath, 'css', FALSE, 1);
1229  foreach ($files as $file) {
1230  $this->pageRenderer->addCssFile($GLOBALS['BACK_PATH'] . $path . $file, 'stylesheet', 'all');
1231  }
1232  }
1233 
1242  public function insertStylesAndJS($content) {
1243  // Insert accumulated CSS
1244  if (!empty($this->inDocStyles)) {
1245  $this->inDocStylesArray[] = $this->inDocStyles;
1246  }
1247  $styles = LF . implode(LF, $this->inDocStylesArray);
1248  $content = str_replace('/*###POSTCSSMARKER###*/', $styles, $content);
1249 
1250  // Insert accumulated JS
1251  $jscode = $this->JScode . LF . $this->wrapScriptTags(implode(LF, $this->JScodeArray));
1252  $content = str_replace('<!--###POSTJSMARKER###-->', $jscode, $content);
1253  return $content;
1254  }
1255 
1261  public function getSkinStylesheetDirectories() {
1262  $stylesheetDirectories = array();
1263  // Add default core stylesheets
1264  foreach ($this->stylesheetsCore as $stylesheetDir) {
1265  $stylesheetDirectories[] = $stylesheetDir;
1266  }
1267  // Stylesheets from skins
1268  // merge default css directories ($this->stylesheetsSkin) with additional ones and include them
1269  if (is_array($GLOBALS['TBE_STYLES']['skins'])) {
1270  // loop over all registered skins
1271  foreach ($GLOBALS['TBE_STYLES']['skins'] as $skinExtKey => $skin) {
1272  $skinStylesheetDirs = $this->stylesheetsSkins;
1273  // Skins can add custom stylesheetDirectories using
1274  // $GLOBALS['TBE_STYLES']['skins'][$_EXTKEY]['stylesheetDirectories']
1275  if (is_array($skin['stylesheetDirectories'])) {
1276  $skinStylesheetDirs = array_merge($skinStylesheetDirs, $skin['stylesheetDirectories']);
1277  }
1278  // Add all registered directories
1279  foreach ($skinStylesheetDirs as $stylesheetDir) {
1280  // for EXT:myskin/stylesheets/ syntax
1281  if (substr($stylesheetDir, 0, 4) === 'EXT:') {
1282  list($extKey, $path) = explode('/', substr($stylesheetDir, 4), 2);
1283  if (!empty($extKey) && ExtensionManagementUtility::isLoaded($extKey) && !empty($path)) {
1284  $stylesheetDirectories[] = ExtensionManagementUtility::extRelPath($extKey) . $path;
1285  }
1286  } else {
1287  // For relative paths
1288  $stylesheetDirectories[] = ExtensionManagementUtility::extRelPath($skinExtKey) . $stylesheetDir;
1289  }
1290  }
1291  }
1292  }
1293  return $stylesheetDirectories;
1294  }
1295 
1302  public function generator() {
1303  $str = 'TYPO3 CMS, ' . TYPO3_URL_GENERAL . ', &#169; Kasper Sk&#229;rh&#248;j ' . TYPO3_copyright_year . ', extensions are copyright of their respective owners.';
1304  return '<meta name="generator" content="' . $str . '" />';
1305  }
1306 
1313  public function xUaCompatible($content = 'IE=8') {
1314  return '<meta http-equiv="X-UA-Compatible" content="' . $content . '" />';
1315  }
1316 
1317  /*****************************************
1318  *
1319  * OTHER ELEMENTS
1320  * Tables, buttons, formatting dimmed/red strings
1321  *
1322  ******************************************/
1337  public function icons($type, $styleAttribValue = '') {
1338  switch ($type) {
1339  case self::STATUS_ICON_ERROR:
1340  $icon = 'status-dialog-error';
1341  break;
1342  case self::STATUS_ICON_WARNING:
1343  $icon = 'status-dialog-warning';
1344  break;
1345  case self::STATUS_ICON_NOTIFICATION:
1346  $icon = 'status-dialog-notification';
1347  break;
1348  case self::STATUS_ICON_OK:
1349  $icon = 'status-dialog-ok';
1350  break;
1351  default:
1352  // Do nothing
1353  }
1354  if ($icon) {
1355  return IconUtility::getSpriteIcon($icon);
1356  }
1357  }
1358 
1367  public function t3Button($onClick, $label) {
1368  $button = '<input type="submit" onclick="' . htmlspecialchars($onClick) . '; return false;" value="' . htmlspecialchars($label) . '" />';
1369  return $button;
1370  }
1371 
1379  public function dfw($string) {
1380  return '<span class="typo3-dimmed">' . $string . '</span>';
1381  }
1382 
1390  public function rfw($string) {
1391  return '<span class="typo3-red">' . $string . '</span>';
1392  }
1393 
1401  public function wrapInCData($string) {
1402  $string = '/*<![CDATA[*/' . $string . '/*]]>*/';
1403  return $string;
1404  }
1405 
1416  public function wrapScriptTags($string, $linebreak = TRUE) {
1417  if (trim($string)) {
1418  // <script wrapped in nl?
1419  $cr = $linebreak ? LF : '';
1420  // Remove nl from the beginning
1421  $string = preg_replace('/^\\n+/', '', $string);
1422  // Re-ident to one tab using the first line as reference
1423  $match = array();
1424  if (preg_match('/^(\\t+)/', $string, $match)) {
1425  $string = str_replace($match[1], TAB, $string);
1426  }
1427  $string = $cr . '<script type="text/javascript">
1428 /*<![CDATA[*/
1429 ' . $string . '
1430 /*]]>*/
1431 </script>' . $cr;
1432  }
1433  return trim($string);
1434  }
1435 
1436  // These vars defines the layout for the table produced by the table() function.
1437  // You can override these values from outside if you like.
1441  public $tableLayout = array(
1442  'defRow' => array(
1443  'defCol' => array('<td valign="top">', '</td>')
1444  )
1445  );
1446 
1450  public $table_TR = '<tr>';
1451 
1455  public $table_TABLE = '<table border="0" cellspacing="0" cellpadding="0" class="typo3-dblist" id="typo3-tmpltable">';
1456 
1466  public function table($data, $layout = NULL) {
1467  $result = '';
1468  if (is_array($data)) {
1469  $tableLayout = is_array($layout) ? $layout : $this->tableLayout;
1470  $rowCount = 0;
1471  foreach ($data as $tableRow) {
1472  if ($rowCount % 2) {
1473  $layout = is_array($tableLayout['defRowOdd']) ? $tableLayout['defRowOdd'] : $tableLayout['defRow'];
1474  } else {
1475  $layout = is_array($tableLayout['defRowEven']) ? $tableLayout['defRowEven'] : $tableLayout['defRow'];
1476  }
1477  $rowLayout = is_array($tableLayout[$rowCount]) ? $tableLayout[$rowCount] : $layout;
1478  $rowResult = '';
1479  if (is_array($tableRow)) {
1480  $cellCount = 0;
1481  foreach ($tableRow as $tableCell) {
1482  $cellWrap = is_array($layout[$cellCount]) ? $layout[$cellCount] : $layout['defCol'];
1483  $cellWrap = is_array($rowLayout['defCol']) ? $rowLayout['defCol'] : $cellWrap;
1484  $cellWrap = is_array($rowLayout[$cellCount]) ? $rowLayout[$cellCount] : $cellWrap;
1485  $rowResult .= $cellWrap[0] . $tableCell . $cellWrap[1];
1486  $cellCount++;
1487  }
1488  }
1489  $rowWrap = is_array($layout['tr']) ? $layout['tr'] : array($this->table_TR, '</tr>');
1490  $rowWrap = is_array($rowLayout['tr']) ? $rowLayout['tr'] : $rowWrap;
1491  $result .= $rowWrap[0] . $rowResult . $rowWrap[1];
1492  $rowCount++;
1493  }
1494  $tableWrap = is_array($tableLayout['table']) ? $tableLayout['table'] : array($this->table_TABLE, '</table>');
1495  $result = $tableWrap[0] . $result . $tableWrap[1];
1496  }
1497  return $result;
1498  }
1499 
1510  public function menuTable($arr1, $arr2 = array(), $arr3 = array()) {
1511  $rows = max(array(count($arr1), count($arr2), count($arr3)));
1512  $menu = '
1513  <table border="0" cellpadding="0" cellspacing="0" id="typo3-tablemenu">';
1514  for ($a = 0; $a < $rows; $a++) {
1515  $menu .= '<tr>';
1516  $cls = array();
1517  $valign = 'middle';
1518  $cls[] = '<td valign="' . $valign . '">' . $arr1[$a][0] . '</td><td>' . $arr1[$a][1] . '</td>';
1519  if (count($arr2)) {
1520  $cls[] = '<td valign="' . $valign . '">' . $arr2[$a][0] . '</td><td>' . $arr2[$a][1] . '</td>';
1521  if (count($arr3)) {
1522  $cls[] = '<td valign="' . $valign . '">' . $arr3[$a][0] . '</td><td>' . $arr3[$a][1] . '</td>';
1523  }
1524  }
1525  $menu .= implode($cls, '<td>&nbsp;&nbsp;</td>');
1526  $menu .= '</tr>';
1527  }
1528  $menu .= '
1529  </table>
1530  ';
1531  return $menu;
1532  }
1533 
1543  public function funcMenu($content, $menu) {
1544  return '
1545  <table border="0" cellpadding="0" cellspacing="0" width="100%" id="typo3-funcmenu">
1546  <tr>
1547  <td valign="top" nowrap="nowrap">' . $content . '</td>
1548  <td valign="top" align="right" nowrap="nowrap">' . $menu . '</td>
1549  </tr>
1550  </table>';
1551  }
1552 
1561  public function loadJavascriptLib($lib) {
1562  $this->pageRenderer->addJsFile($this->backPath . $lib);
1563  }
1564 
1571  public function getContextMenuCode() {
1572  $this->pageRenderer->loadPrototype();
1573  $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/clickmenu.js');
1574  $this->JScodeArray['clickmenu'] = '
1575  Clickmenu.clickURL = "' . $this->backPath . 'alt_clickmenu.php";
1576  Clickmenu.ajax = true;';
1577  }
1578 
1587  public function getDragDropCode($table) {
1588  $this->pageRenderer->loadPrototype();
1589  $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/common.js');
1590  $this->loadJavascriptLib('js/tree.js');
1591  // Setting prefs for drag & drop
1592  $this->JScodeArray['dragdrop'] = '
1593  DragDrop.changeURL = "' . $this->backPath . 'alt_clickmenu.php";
1594  DragDrop.backPath = "' . GeneralUtility::shortMD5(('' . '|' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) . '";
1595  DragDrop.table = "' . $table . '";
1596  ';
1597  }
1598 
1604  protected function loadCshJavascript() {
1605  $this->pageRenderer->loadExtJS();
1606  $this->pageRenderer->addJsFile($this->backPath . 'sysext/backend/Resources/Public/JavaScript/contexthelp.js');
1607  $this->pageRenderer->addExtDirectCode();
1608  }
1609 
1625  public function getTabMenu($mainParams, $elementName, $currentValue, $menuItems, $script = '', $addparams = '') {
1626  $content = '';
1627  if (is_array($menuItems)) {
1628  if (!is_array($mainParams)) {
1629  $mainParams = array('id' => $mainParams);
1630  }
1631  $mainParams = GeneralUtility::implodeArrayForUrl('', $mainParams);
1632  if (!$script) {
1633  $script = basename(PATH_thisScript);
1634  }
1635  $menuDef = array();
1636  foreach ($menuItems as $value => $label) {
1637  $menuDef[$value]['isActive'] = (string)$currentValue === (string)$value;
1638  $menuDef[$value]['label'] = htmlspecialchars($label, ENT_COMPAT, 'UTF-8', FALSE);
1639  $menuDef[$value]['url'] = $script . '?' . $mainParams . $addparams . '&' . $elementName . '=' . $value;
1640  }
1641  $content = $this->getTabMenuRaw($menuDef);
1642  }
1643  return $content;
1644  }
1645 
1654  public function getTabMenuRaw($menuItems) {
1655  $content = '';
1656  if (is_array($menuItems)) {
1657  $options = '';
1658  $count = count($menuItems);
1659  $widthLeft = 1;
1660  $addToAct = 5;
1661  $widthRight = max(1, floor(30 - pow($count, 1.72)));
1662  $widthTabs = 100 - $widthRight - $widthLeft;
1663  $widthNo = floor(($widthTabs - $addToAct) / $count);
1664  $addToAct = max($addToAct, $widthTabs - $widthNo * $count);
1665  $widthAct = $widthNo + $addToAct;
1666  $widthRight = 100 - ($widthLeft + $count * $widthNo + $addToAct);
1667  foreach ($menuItems as $id => $def) {
1668  $isActive = $def['isActive'];
1669  $class = $isActive ? 'tabact' : 'tab';
1670  $width = $isActive ? $widthAct : $widthNo;
1671  // @rene: Here you should probably wrap $label and $url in htmlspecialchars() in order to make sure its XHTML compatible! I did it for $url already since that is VERY likely to break.
1672  $label = $def['label'];
1673  $url = htmlspecialchars($def['url']);
1674  $params = $def['addParams'];
1675  $options .= '<td width="' . $width . '%" class="' . $class . '"><a href="' . $url . '" ' . $params . '>' . $label . '</a></td>';
1676  }
1677  if ($options) {
1678  $content .= '
1679  <!-- Tab menu -->
1680  <table cellpadding="0" cellspacing="0" border="0" width="100%" id="typo3-tabmenu">
1681  <tr>
1682  <td width="' . $widthLeft . '%">&nbsp;</td>
1683  ' . $options . '
1684  <td width="' . $widthRight . '%">&nbsp;</td>
1685  </tr>
1686  </table>
1687  <div class="hr" style="margin:0px"></div>';
1688  }
1689  }
1690  return $content;
1691  }
1692 
1707  public function getDynTabMenu($menuItems, $identString, $toggle = 0, $foldout = FALSE, $noWrap = TRUE, $fullWidth = FALSE, $defaultTabIndex = 1, $dividers2tabs = 2) {
1708  // Load the static code, if not already done with the function below
1709  $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/tabmenu.js');
1710  $content = '';
1711  if (is_array($menuItems)) {
1712  // Init:
1713  $options = array(array());
1714  $divs = array();
1715  $JSinit = array();
1716  $id = $this->getDynTabMenuId($identString);
1717  $noWrap = $noWrap ? ' nowrap="nowrap"' : '';
1718  // Traverse menu items
1719  $c = 0;
1720  $tabRows = 0;
1721  $titleLenCount = 0;
1722  foreach ($menuItems as $index => $def) {
1723  // Need to add one so checking for first index in JavaScript
1724  // is different than if it is not set at all.
1725  $index += 1;
1726  // Switch to next tab row if needed
1727  if (!$foldout && ($def['newline'] === TRUE && $titleLenCount > 0)) {
1728  $titleLenCount = 0;
1729  $tabRows++;
1730  $options[$tabRows] = array();
1731  }
1732  if ($toggle == 1) {
1733  $onclick = 'this.blur(); DTM_toggle("' . $id . '","' . $index . '"); return false;';
1734  } else {
1735  $onclick = 'this.blur(); DTM_activate("' . $id . '","' . $index . '", ' . ($toggle < 0 ? 1 : 0) . '); return false;';
1736  }
1737  $isEmpty = trim($def['content']) === '' && trim($def['icon']) === '';
1738  // "Removes" empty tabs
1739  if ($isEmpty && $dividers2tabs == 1) {
1740  continue;
1741  }
1742  $requiredIcon = '<img name="' . $id . '-' . $index . '-REQ" src="' . $GLOBALS['BACK_PATH'] . 'gfx/clear.gif" class="t3-TCEforms-reqTabImg" alt="" />';
1743  if (!$foldout) {
1744  // Create TAB cell:
1745  $options[$tabRows][] = '
1746  <td class="' . ($isEmpty ? 'disabled' : 'tab') . '" id="' . $id . '-' . $index . '-MENU"' . $noWrap . '>' . ($isEmpty ? '' : '<a href="#" onclick="' . htmlspecialchars($onclick) . '"' . ($def['linkTitle'] ? ' title="' . htmlspecialchars($def['linkTitle']) . '"' : '') . '>') . $def['icon'] . ($def['label'] ? htmlspecialchars($def['label']) : '&nbsp;') . $requiredIcon . $this->icons($def['stateIcon'], 'margin-left: 10px;') . ($isEmpty ? '' : '</a>') . '</td>';
1747  $titleLenCount += strlen($def['label']);
1748  } else {
1749  // Create DIV layer for content:
1750  $divs[] = '
1751  <div class="' . ($isEmpty ? 'disabled' : 'tab') . '" id="' . $id . '-' . $index . '-MENU">' . ($isEmpty ? '' : '<a href="#" onclick="' . htmlspecialchars($onclick) . '"' . ($def['linkTitle'] ? ' title="' . htmlspecialchars($def['linkTitle']) . '"' : '') . '>') . $def['icon'] . ($def['label'] ? htmlspecialchars($def['label']) : '&nbsp;') . $requiredIcon . ($isEmpty ? '' : '</a>') . '</div>';
1752  }
1753  // Create DIV layer for content:
1754  $divs[] = '
1755  <div style="display: none;" id="' . $id . '-' . $index . '-DIV" class="c-tablayer">' . ($def['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($def['description'])) . '</p>' : '') . $def['content'] . '</div>';
1756  // Create initialization string:
1757  $JSinit[] = '
1758  DTM_array["' . $id . '"][' . $c . '] = "' . $id . '-' . $index . '";
1759  ';
1760  // If not empty and we have the toggle option on, check if the tab needs to be expanded
1761  if ($toggle == 1 && !$isEmpty) {
1762  $JSinit[] = '
1763  if (top.DTM_currentTabs["' . $id . '-' . $index . '"]) { DTM_toggle("' . $id . '","' . $index . '",1); }
1764  ';
1765  }
1766  $c++;
1767  }
1768  // Render menu:
1769  if (count($options)) {
1770  // Tab menu is compiled:
1771  if (!$foldout) {
1772  $tabContent = '';
1773  for ($a = 0; $a <= $tabRows; $a++) {
1774  $tabContent .= '
1775 
1776  <!-- Tab menu -->
1777  <table cellpadding="0" cellspacing="0" border="0"' . ($fullWidth ? ' width="100%"' : '') . ' class="typo3-dyntabmenu">
1778  <tr>
1779  ' . implode('', $options[$a]) . '
1780  </tr>
1781  </table>';
1782  }
1783  $content .= '<div class="typo3-dyntabmenu-tabs">' . $tabContent . '</div>';
1784  }
1785  // Div layers are added:
1786  $content .= '
1787  <!-- Div layers for tab menu: -->
1788  <div class="typo3-dyntabmenu-divs' . ($foldout ? '-foldout' : '') . '">
1789  ' . implode('', $divs) . '</div>';
1790  // Java Script section added:
1791  $content .= '
1792  <!-- Initialization JavaScript for the menu -->
1793  <script type="text/javascript">
1794  DTM_array["' . $id . '"] = new Array();
1795  ' . implode('', $JSinit) . '
1796  ' . ($toggle <= 0 ? 'DTM_activate("' . $id . '", top.DTM_currentTabs["' . $id . '"]?top.DTM_currentTabs["' . $id . '"]:' . (int)$defaultTabIndex . ', 0);' : '') . '
1797  </script>
1798 
1799  ';
1800  }
1801  }
1802  return $content;
1803  }
1804 
1812  public function getDynTabMenuId($identString) {
1813  $id = 'DTM-' . GeneralUtility::shortMD5($identString);
1814  return $id;
1815  }
1816 
1825  public function getVersionSelector($id, $noAction = FALSE) {
1826  if (
1829  ) {
1830  $versionGuiObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Version\\View\\VersionView');
1831  return $versionGuiObj->getVersionSelector($id, $noAction);
1832  }
1833  }
1834 
1843  public function getHtmlTemplate($filename) {
1844  // setting the name of the original HTML template
1845  $this->moduleTemplateFilename = $filename;
1846  if ($GLOBALS['TBE_STYLES']['htmlTemplates'][$filename]) {
1847  $filename = $GLOBALS['TBE_STYLES']['htmlTemplates'][$filename];
1848  }
1849  if (GeneralUtility::isFirstPartOfStr($filename, 'EXT:')) {
1850  $filename = GeneralUtility::getFileAbsFileName($filename, TRUE, TRUE);
1851  } elseif (!GeneralUtility::isAbsPath($filename)) {
1852  $filename = GeneralUtility::resolveBackPath($this->backPath . $filename);
1853  } elseif (!GeneralUtility::isAllowedAbsPath($filename)) {
1854  $filename = '';
1855  }
1856  $htmlTemplate = '';
1857  if ($filename !== '') {
1858  $htmlTemplate = GeneralUtility::getUrl($filename);
1859  }
1860  return $htmlTemplate;
1861  }
1862 
1869  public function setModuleTemplate($filename) {
1870  // Load Prototype lib for IE event
1871  $this->pageRenderer->loadPrototype();
1872  $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/iecompatibility.js');
1873  $this->moduleTemplate = $this->getHtmlTemplate($filename);
1874  }
1875 
1886  public function moduleBody($pageRecord = array(), $buttons = array(), $markerArray = array(), $subpartArray = array()) {
1887  // Get the HTML template for the module
1888  $moduleBody = HtmlParser::getSubpart($this->moduleTemplate, '###FULLDOC###');
1889  // Add CSS
1890  $this->inDocStylesArray[] = 'html { overflow: hidden; }';
1891  // Get the page path for the docheader
1892  $markerArray['PAGEPATH'] = $this->getPagePath($pageRecord);
1893  // Get the page info for the docheader
1894  $markerArray['PAGEINFO'] = $this->getPageInfo($pageRecord);
1895  // Get all the buttons for the docheader
1896  $docHeaderButtons = $this->getDocHeaderButtons($buttons);
1897  // Merge docheader buttons with the marker array
1898  $markerArray = array_merge($markerArray, $docHeaderButtons);
1899  // replacing subparts
1900  foreach ($subpartArray as $marker => $content) {
1901  $moduleBody = HtmlParser::substituteSubpart($moduleBody, $marker, $content);
1902  }
1903  // adding flash messages
1904  if ($this->showFlashMessages) {
1905  $flashMessages = $this->getFlashMessages();
1906  if (!empty($flashMessages)) {
1907  $markerArray['FLASHMESSAGES'] = $flashMessages;
1908  // If there is no dedicated marker for the messages present
1909  // then force them to appear before the content
1910  if (strpos($moduleBody, '###FLASHMESSAGES###') === FALSE) {
1911  $moduleBody = str_replace('###CONTENT###', '###FLASHMESSAGES######CONTENT###', $moduleBody);
1912  }
1913  }
1914  }
1915  // Hook for adding more markers/content to the page, like the version selector
1916  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['moduleBodyPostProcess'])) {
1917  $params = array(
1918  'moduleTemplateFilename' => &$this->moduleTemplateFilename,
1919  'moduleTemplate' => &$this->moduleTemplate,
1920  'moduleBody' => &$moduleBody,
1921  'markers' => &$markerArray,
1922  'parentObject' => &$this
1923  );
1924  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['moduleBodyPostProcess'] as $funcRef) {
1925  GeneralUtility::callUserFunction($funcRef, $params, $this);
1926  }
1927  }
1928  // Replacing all markers with the finished markers and return the HTML content
1929  return HtmlParser::substituteMarkerArray($moduleBody, $markerArray, '###|###');
1930  }
1931 
1937  public function getFlashMessages() {
1939  $flashMessageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessageService');
1941  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1942  $flashMessages = $defaultFlashMessageQueue->renderFlashMessages();
1943  if (!empty($flashMessages)) {
1944  $flashMessages = '<div id="typo3-messages">' . $flashMessages . '</div>';
1945  }
1946  return $flashMessages;
1947  }
1948 
1956  public function renderFlashMessages(array $params, \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj) {
1957  $ajaxObj->addContent('result', $this->getFlashMessages());
1958  $ajaxObj->setContentFormat('html');
1959  }
1960 
1967  protected function getDocHeaderButtons($buttons) {
1968  $markers = array();
1969  // Fill buttons for left and right float
1970  $floats = array('left', 'right');
1971  foreach ($floats as $key) {
1972  // Get the template for each float
1973  $buttonTemplate = HtmlParser::getSubpart($this->moduleTemplate, '###BUTTON_GROUPS_' . strtoupper($key) . '###');
1974  // Fill the button markers in this float
1975  $buttonTemplate = HtmlParser::substituteMarkerArray($buttonTemplate, $buttons, '###|###', TRUE);
1976  // getting the wrap for each group
1977  $buttonWrap = HtmlParser::getSubpart($this->moduleTemplate, '###BUTTON_GROUP_WRAP###');
1978  // looping through the groups (max 6) and remove the empty groups
1979  for ($groupNumber = 1; $groupNumber < 6; $groupNumber++) {
1980  $buttonMarker = '###BUTTON_GROUP' . $groupNumber . '###';
1981  $buttonGroup = HtmlParser::getSubpart($buttonTemplate, $buttonMarker);
1982  if (trim($buttonGroup)) {
1983  if ($buttonWrap) {
1984  $buttonGroup = HtmlParser::substituteMarker($buttonWrap, '###BUTTONS###', $buttonGroup);
1985  }
1986  $buttonTemplate = HtmlParser::substituteSubpart($buttonTemplate, $buttonMarker, trim($buttonGroup));
1987  }
1988  }
1989  // Replace the marker with the template and remove all line breaks (for IE compat)
1990  $markers['BUTTONLIST_' . strtoupper($key)] = str_replace(LF, '', $buttonTemplate);
1991  }
1992  // Hook for manipulating docHeaderButtons
1993  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['docHeaderButtonsHook'])) {
1994  $params = array(
1995  'buttons' => $buttons,
1996  'markers' => &$markers,
1997  'pObj' => &$this
1998  );
1999  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['docHeaderButtonsHook'] as $funcRef) {
2000  GeneralUtility::callUserFunction($funcRef, $params, $this);
2001  }
2002  }
2003  return $markers;
2004  }
2005 
2012  protected function getPagePath($pageRecord) {
2013  // Is this a real page
2014  if (is_array($pageRecord) && $pageRecord['uid']) {
2015  $title = substr($pageRecord['_thePathFull'], 0, -1);
2016  // Remove current page title
2017  $pos = strrpos($title, $pageRecord['title']);
2018  if ($pos !== FALSE) {
2019  $title = substr($title, 0, $pos);
2020  }
2021  } else {
2022  $title = '';
2023  }
2024  // Setting the path of the page
2025  $pagePath = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.path', TRUE) . ': <span class="typo3-docheader-pagePath">';
2026  // crop the title to title limit (or 50, if not defined)
2027  $cropLength = empty($GLOBALS['BE_USER']->uc['titleLen']) ? 50 : $GLOBALS['BE_USER']->uc['titleLen'];
2028  $croppedTitle = GeneralUtility::fixed_lgd_cs($title, -$cropLength);
2029  if ($croppedTitle !== $title) {
2030  $pagePath .= '<abbr title="' . htmlspecialchars($title) . '">' . htmlspecialchars($croppedTitle) . '</abbr>';
2031  } else {
2032  $pagePath .= htmlspecialchars($title);
2033  }
2034  $pagePath .= '</span>';
2035  return $pagePath;
2036  }
2037 
2044  protected function getPageInfo($pageRecord) {
2045  // Add icon with clickmenu, etc:
2046  // If there IS a real page
2047  if (is_array($pageRecord) && $pageRecord['uid']) {
2048  $alttext = BackendUtility::getRecordIconAltText($pageRecord, 'pages');
2049  $iconImg = IconUtility::getSpriteIconForRecord('pages', $pageRecord, array('title' => $alttext));
2050  // Make Icon:
2051  $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg, 'pages', $pageRecord['uid']);
2052  $uid = $pageRecord['uid'];
2053  $title = BackendUtility::getRecordTitle('pages', $pageRecord);
2054  } else {
2055  // On root-level of page tree
2056  // Make Icon
2057  $iconImg = IconUtility::getSpriteIcon('apps-pagetree-root', array('title' => htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'])));
2058  if ($GLOBALS['BE_USER']->user['admin']) {
2059  $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg, 'pages', 0);
2060  } else {
2061  $theIcon = $iconImg;
2062  }
2063  $uid = '0';
2064  $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
2065  }
2066  // Setting icon with clickmenu + uid
2067  $pageInfo = $theIcon . '<strong>' . htmlspecialchars($title) . '&nbsp;[' . $uid . ']</strong>';
2068  return $pageInfo;
2069  }
2070 
2080  public function collapseableSection($title, $html, $id, $saveStatePointer = '') {
2081  $hasSave = $saveStatePointer ? TRUE : FALSE;
2082  $collapsedStyle = ($collapsedClass = '');
2083  if ($hasSave) {
2085  $settings = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\User\\ExtDirect\\BackendUserSettingsDataProvider');
2086  $value = $settings->get($saveStatePointer . '.' . $id);
2087  if ($value) {
2088  $collapsedStyle = ' style="display: none"';
2089  $collapsedClass = ' collapsed';
2090  } else {
2091  $collapsedStyle = '';
2092  $collapsedClass = ' expanded';
2093  }
2094  }
2095  $this->pageRenderer->loadExtJS();
2096  $this->pageRenderer->addExtOnReadyCode('
2097  Ext.select("h2.section-header").each(function(element){
2098  element.on("click", function(event, tag) {
2099  var state = 0,
2100  el = Ext.fly(tag),
2101  div = el.next("div"),
2102  saveKey = el.getAttribute("rel");
2103  if (el.hasClass("collapsed")) {
2104  el.removeClass("collapsed").addClass("expanded");
2105  div.slideIn("t", {
2106  easing: "easeIn",
2107  duration: .5
2108  });
2109  } else {
2110  el.removeClass("expanded").addClass("collapsed");
2111  div.slideOut("t", {
2112  easing: "easeOut",
2113  duration: .5,
2114  remove: false,
2115  useDisplay: true
2116  });
2117  state = 1;
2118  }
2119  if (saveKey) {
2120  try {
2121  top.TYPO3.BackendUserSettings.ExtDirect.set(saveKey + "." + tag.id, state, function(response) {});
2122  } catch(e) {}
2123  }
2124  });
2125  });
2126  ');
2127  return '
2128  <h2 id="' . $id . '" class="section-header' . $collapsedClass . '" rel="' . $saveStatePointer . '"> ' . $title . '</h2>
2129  <div' . $collapsedStyle . '>' . $html . '</div>
2130  ';
2131  }
2132 
2138  protected function getBackendFavicon() {
2139  return IconUtility::skinImg($this->backPath, 'gfx/favicon.ico', '', 1);
2140  }
2141 }
moduleBody($pageRecord=array(), $buttons=array(), $markerArray=array(), $subpartArray=array())
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
static skinImg($backPath, $src, $wHattribs='', $outputMode=0)
addStyleSheet($key, $href, $title='', $relation='stylesheet')
static BEgetRootLine($uid, $clause='', $workspaceOL=FALSE)
static devLog($msg, $extKey, $severity=0, $dataVar=FALSE)
static isFirstPartOfStr($str, $partStr)
static getSpriteIconForResource(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, array $options=array(), array $overlays=array())
$uid
Definition: server.php:36
render($title, $content, $includeCsh=TRUE)
formWidthText($size=48, $styleOverride='', $wrap='')
static getUrlToken($formName='securityToken', $tokenName='formToken')
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
getDynTabMenu($menuItems, $identString, $toggle=0, $foldout=FALSE, $noWrap=TRUE, $fullWidth=FALSE, $defaultTabIndex=1, $dividers2tabs=2)
sectionHeader($label, $sH=FALSE, $addAttrib='')
static viewOnClick($pageUid, $backPath='', $rootLine='', $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=TRUE)
static getRecordTitle($table, $row, $prep=FALSE, $forceResult=TRUE)
static getSpriteIconForRecord($table, array $row, array $options=array())
getTabMenu($mainParams, $elementName, $currentValue, $menuItems, $script='', $addparams='')
static split_fileref($fileNameWithPath)
getResourceHeader(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, $tWrap=array('', ''), $enableClickMenu=TRUE)
static linkThisScript(array $getParams=array())
static substituteMarker($content, $marker, $markContent)
Definition: HtmlParser.php:167
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static compileSelectedGetVarsFromArray($varList, array $getArray, $GPvarAlt=TRUE)
static getUrl($url, $includeHeader=0, $requestHeaders=FALSE, &$report=NULL)
viewPageIcon($id, $backPath, $addParams='hspace="3"')
static titleAttribForPages($row, $perms_clause='', $includeAttrib=1)
static getSubpart($content, $marker)
Definition: HtmlParser.php:39
static substituteMarkerArray($content, $markContentArray, $wrap='', $uppercase=FALSE, $deleteUnused=FALSE)
Definition: HtmlParser.php:189
static getSpriteIcon($iconName, array $options=array(), array $overlays=array())
section($label, $text, $nostrtoupper=FALSE, $sH=FALSE, $type=0, $allowHTMLinHeader=FALSE)
static substituteSubpart($content, $marker, $subpartContent, $recursive=TRUE, $keepMarker=FALSE)
Definition: HtmlParser.php:79
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
static getFilesInDir($path, $extensionList='', $prependPath=FALSE, $order='', $excludePattern='')
static getRecordIconAltText($row, $table='pages')
static fixed_lgd_cs($string, $chars, $appendString='...')
makeShortcutIcon($gvList, $setList, $modName, $motherModName='')
menuTable($arr1, $arr2=array(), $arr3=array())
getHeader($table, $row, $path, $noViewPageIcon=FALSE, $tWrap=array('', ''), $enableClickMenu=TRUE)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
wrapClickMenuOnIcon($str, $table, $uid=0, $listFr=TRUE, $addParams='', $enDisItems='', $returnOnClick=FALSE)
formWidth($size=48, $textarea=FALSE, $styleOverride='')
static getFileAbsFileName($filename, $onlyRelative=TRUE, $relToTYPO3_mainDir=FALSE)
if($ajaxRegistryEntry !==NULL) $ajaxObj
Definition: ajax.php:63
renderFlashMessages(array $params, \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj)
static getListViewLink($urlParameters=array(), $linkTitle='', $linkText='')