/** * Index action shows install tool / step installer or redirect to action to enable install tool * * @param ServerRequestInterface $request * @param ResponseInterface $response * @return ResponseInterface */ public function index(ServerRequestInterface $request, ResponseInterface $response) { /** @var EnableFileService $enableFileService */ $enableFileService = GeneralUtility::makeInstance(EnableFileService::class); /** @var AbstractFormProtection $formProtection */ $formProtection = FormProtectionFactory::get(); if ($enableFileService->checkInstallToolEnableFile()) { // Install tool is open and valid, redirect to it $response = $response->withStatus(303)->withHeader('Location', 'sysext/install/Start/Install.php?install[context]=backend'); } elseif ($request->getMethod() === 'POST' && $request->getParsedBody()['action'] === 'enableInstallTool') { // Request to open the install tool $installToolEnableToken = $request->getParsedBody()['installToolEnableToken']; if (!$formProtection->validateToken($installToolEnableToken, 'installTool')) { throw new \RuntimeException('Given form token was not valid', 1369161225); } $enableFileService->createInstallToolEnableFile(); // Install tool is open and valid, redirect to it $response = $response->withStatus(303)->withHeader('Location', 'sysext/install/Start/Install.php?install[context]=backend'); } else { // Show the "create enable install tool" button /** @var StandaloneView $view */ $view = GeneralUtility::makeInstance(StandaloneView::class); $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:install/Resources/Private/Templates/BackendModule/ShowEnableInstallToolButton.html')); $token = $formProtection->generateToken('installTool'); $view->assign('installToolEnableToken', $token); /** @var ModuleTemplate $moduleTemplate */ $moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class); $cssFile = 'EXT:install/Resources/Public/Css/BackendModule/ShowEnableInstallToolButton.css'; $cssFile = GeneralUtility::getFileAbsFileName($cssFile); $moduleTemplate->getPageRenderer()->addCssFile(PathUtility::getAbsoluteWebPath($cssFile)); $moduleTemplate->setContent($view->render()); $response->getBody()->write($moduleTemplate->renderContent()); } return $response; }
/** * @param string $identifier * * @return string */ public function render($identifier = '') { $basePath = 'sysext/t3skin/images/icons/'; $nameParts = GeneralUtility::trimExplode('-', $identifier); $folder = array_shift($nameParts); $basePath .= $folder . '/' . implode('-', $nameParts) . '.png'; return '<img src="' . PathUtility::getAbsoluteWebPath($basePath) . '" />'; }
/** * @param Icon $icon * @param array $options * @return string * @throws \InvalidArgumentException */ protected function generateMarkup(Icon $icon, array $options) { if (empty($options['source'])) { throw new \InvalidArgumentException('[' . $icon->getIdentifier() . '] The option "source" is required and must not be empty', 1440754980); } $source = $options['source']; if (StringUtility::beginsWith($source, 'EXT:') || !StringUtility::beginsWith($source, '/')) { $source = GeneralUtility::getFileAbsFileName($source); } $source = PathUtility::getAbsoluteWebPath($source); return '<img src="' . htmlspecialchars($source) . '" width="' . $icon->getDimension()->getWidth() . '" height="' . $icon->getDimension()->getHeight() . '" />'; }
/** * Convert arrays with EXT: resource paths to web paths * * Input: * [ * 100 => 'EXT:form/Resources/Public/Css/form.css' * ] * * Output: * * [ * 0 => 'typo3/sysext/form/Resources/Public/Css/form.css' * ] * * @param array $resourcePaths * @return array */ protected function resolveResourcePaths(array $resourcePaths) : array { $return = []; foreach ($resourcePaths as $resourcePath) { $fullResourcePath = GeneralUtility::getFileAbsFileName($resourcePath); $resourcePath = PathUtility::getAbsoluteWebPath($fullResourcePath); if (empty($resourcePath)) { continue; } $return[] = $resourcePath; } return $return; }
/** * Renders the view and returns the content * * @param string $title The title to be shown * @param string $message The message to be shown * @param int $severity The severity of the error, see AbstractMessage constants * @param int $errorCode The error code to be referenced * @return string the output of the view */ public function errorAction(string $title, string $message, int $severity = AbstractMessage::ERROR, int $errorCode = 0) : string { $this->severity = $severity; $classes = [AbstractMessage::NOTICE => 'notice', AbstractMessage::INFO => 'information', AbstractMessage::OK => 'ok', AbstractMessage::WARNING => 'warning', AbstractMessage::ERROR => 'error']; $this->view->assign('severityCssClass', $classes[$this->severity]); $this->view->assign('severity', $this->severity); $this->view->assign('message', $message); $this->view->assign('title', $title); $this->view->assign('errorCodeUrlPrefix', TYPO3_URL_EXCEPTION); $this->view->assign('errorCode', $errorCode); $this->view->assign('logo', PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('backend', 'Resources/Public/Images/typo3_orange.svg'))); $this->view->assign('cssFile', PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('core', 'Resources/Public/Css/errorpage.css'))); $this->view->assign('copyrightYear', TYPO3_copyright_year); return $this->view->render('Error'); }
/** * Initializes the controller before invoking an action method. * * @return void */ protected function initializeAction() { $this->pageRenderer = $this->getPageRenderer(); // @todo Evaluate how the intval() call can be used with Extbase validators/filters $this->pageId = (int) GeneralUtility::_GP('id'); $iconFactory = GeneralUtility::makeInstance(IconFactory::class); $icons = array('language' => $iconFactory->getIcon('flags-multiple', Icon::SIZE_SMALL)->render(), 'integrity' => $iconFactory->getIcon('status-dialog-information', Icon::SIZE_SMALL)->render(), 'success' => $iconFactory->getIcon('status-dialog-ok', Icon::SIZE_SMALL)->render(), 'info' => $iconFactory->getIcon('status-dialog-information', Icon::SIZE_SMALL)->render(), 'warning' => $iconFactory->getIcon('status-dialog-warning', Icon::SIZE_SMALL)->render(), 'error' => $iconFactory->getIcon('status-dialog-error', Icon::SIZE_SMALL)->render()); $this->pageRenderer->addInlineSetting('Workspaces', 'icons', $icons); $this->pageRenderer->addInlineSetting('Workspaces', 'id', $this->pageId); $this->pageRenderer->addInlineSetting('Workspaces', 'depth', $this->pageId === 0 ? 999 : 1); $this->pageRenderer->addInlineSetting('Workspaces', 'language', $this->getLanguageSelection()); $cssFile = 'EXT:workspaces/Resources/Public/Css/module.css'; $cssFile = GeneralUtility::getFileAbsFileName($cssFile); $this->pageRenderer->addCssFile(PathUtility::getAbsoluteWebPath($cssFile)); $this->pageRenderer->addInlineLanguageLabelArray(array('title' => $GLOBALS['LANG']->getLL('title'), 'path' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.path'), 'table' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.table'), 'depth' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_perm.xlf:Depth'), 'depth_0' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_0'), 'depth_1' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_1'), 'depth_2' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_2'), 'depth_3' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_3'), 'depth_4' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_4'), 'depth_infi' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_infi'))); $this->pageRenderer->addInlineLanguageLabelFile('EXT:workspaces/Resources/Private/Language/locallang.xlf'); $this->assignExtensionSettings(); }
/** * Add the given icon to the TCA table type * * @param string $table * @param string $type * @param string $icon */ public static function addTcaTypeIcon($table, $type, $icon) { if (GeneralUtility::compat_version('7.0')) { $fullIconPath = substr(PathUtility::getAbsoluteWebPath($icon), 1); if (StringUtility::endsWith(strtolower($fullIconPath), 'svg')) { $iconProviderClass = 'TYPO3\\CMS\\Core\\Imaging\\IconProvider\\SvgIconProvider'; } else { $iconProviderClass = 'TYPO3\\CMS\\Core\\Imaging\\IconProvider\\BitmapIconProvider'; } /** @var IconRegistry $iconRegistry */ $iconRegistry = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Imaging\\IconRegistry'); $iconIdentifier = 'tcarecords-' . $table . '-' . $type; $iconRegistry->registerIcon($iconIdentifier, $iconProviderClass, ['source' => $fullIconPath]); $GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$type] = $iconIdentifier; } else { $fullIconPath = str_replace('../typo3/', '', $icon); SpriteManager::addTcaTypeIcon('tt_content', $type, $fullIconPath); } }
/** * Render t3editor element * * @return array As defined in initializeResultArray() of AbstractNode */ public function render() { $this->getLanguageService()->includeLLFile('EXT:t3editor/Resources/Private/Language/locallang.xlf'); $this->extPath = PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('t3editor')); $this->codemirrorPath = $this->extPath . $this->codemirrorPath; $this->resultArray = $this->initializeResultArray(); $parameterArray = $this->data['parameterArray']; $rows = MathUtility::forceIntegerInRange($parameterArray['fieldConf']['config']['rows'] ?: 10, 1, 40); $this->setMode(isset($parameterArray['fieldConf']['config']['format']) ? $parameterArray['fieldConf']['config']['format'] : T3editor::MODE_MIXED); $attributes = []; $attributes['rows'] = $rows; $attributes['wrap'] = 'off'; $attributes['style'] = 'width:100%;'; $attributes['onchange'] = GeneralUtility::quoteJSvalue($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']); $attributeString = ''; foreach ($attributes as $param => $value) { $attributeString .= $param . '="' . htmlspecialchars($value) . '" '; } $this->resultArray['html'] = $this->getHTMLCodeForEditor($parameterArray['itemFormElName'], 'text-monospace enable-tab', $parameterArray['itemFormElValue'], $attributeString, $this->data['tableName'] . ' > ' . $this->data['fieldName'], ['target' => 0]); $this->resultArray['additionalJavaScriptPost'][] = 'require(["TYPO3/CMS/T3editor/T3editor"], function(T3editor) {T3editor.findAndInitializeEditors();});'; $this->initJavascriptCode(); return $this->resultArray; }
/** * Returns the uri of a relative reference, resolves the "EXT:" prefix * (way of referring to files inside extensions) and checks that the file is inside * the PATH_site of the TYPO3 installation * * @param string $filename The input filename/filepath to evaluate * @return string Returns the filename of $filename if valid, otherwise blank string. * @internal */ private function getUriForFileName($filename) { if (strpos($filename, '://')) { return $filename; } $urlPrefix = ''; if (strpos($filename, 'EXT:') === 0) { $absoluteFilename = GeneralUtility::getFileAbsFileName($filename); $filename = ''; if ($absoluteFilename !== '') { $filename = PathUtility::getAbsoluteWebPath($absoluteFilename); } } elseif (strpos($filename, '/') !== 0) { $urlPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'); } return $urlPrefix . $filename; }
/** * Returns the Ajax URL for a given AjaxID including a CSRF token. * * This method is only called by the core and must not be used by extensions. * Ajax URLs of all registered backend Ajax handlers are automatically published * to JavaScript inline settings: TYPO3.settings.ajaxUrls['ajaxId'] * * @param string $ajaxIdentifier Identifier of the AJAX callback * @param array $urlParameters URL parameters that should be added as key value pairs * @param bool $backPathOverride (unused) * @param bool $returnAbsoluteUrl If set to TRUE, the URL returned will be absolute, $backPathOverride will be ignored in this case * @return string Calculated URL * @internal */ static public function getAjaxUrl($ajaxIdentifier, array $urlParameters = array(), $backPathOverride = FALSE, $returnAbsoluteUrl = FALSE) { $additionalUrlParameters = array( 'ajaxID' => $ajaxIdentifier ); if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxIdentifier]['csrfTokenCheck'])) { $additionalUrlParameters['ajaxToken'] = FormProtectionFactory::get()->generateToken('ajaxCall', $ajaxIdentifier); } $url = 'ajax.php?' . ltrim(GeneralUtility::implodeArrayForUrl('', ($additionalUrlParameters + $urlParameters), '', TRUE, TRUE), '&'); if ($returnAbsoluteUrl) { return GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $url; } else { return PathUtility::getAbsoluteWebPath(PATH_typo3 . $url); } }
/** * Retrieves configured favicon for backend (with fallback) * * @return string */ protected function getBackendFavicon() { return PathUtility::getAbsoluteWebPath($GLOBALS['TBE_STYLES']['favicon'] ?: ExtensionManagementUtility::extPath('backend') . 'Resources/Public/Icons/favicon.ico'); }
/** * Creates a link to the deprecation log file with the absolute path as the * link text. * * @return string Link to the deprecation log file */ protected function getDeprecationLogFileLink() { $logFile = GeneralUtility::getDeprecationLogFileName(); $linkToLogFile = PathUtility::getAbsoluteWebPath($logFile); return '<a href="' . $linkToLogFile . '">' . $logFile . '</a>'; }
/** * Internal method building a Uri object, merging the GET parameters array into a flat queryString * * @param array $parameters An array of GET parameters * @param string $referenceType The type of reference to be generated (one of the constants) * * @return Uri */ protected function buildUri($parameters, $referenceType) { $uri = 'index.php?' . ltrim(GeneralUtility::implodeArrayForUrl('', $parameters, '', true, true), '&'); if ($referenceType === self::ABSOLUTE_PATH) { $uri = PathUtility::getAbsoluteWebPath(PATH_typo3 . $uri); } else { $uri = GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $uri; } return GeneralUtility::makeInstance(Uri::class, $uri); }
/** * Render a list of items as a nicely formatted definition list including a * link, icon, title and description. * The keys of a single item are: * - title: Title of the item * - link: Link to the task * - icon: Path to the icon or Icon as HTML if it begins with <img * - description: Description of the task, using htmlspecialchars() * - descriptionHtml: Description allowing HTML tags which will override the * description * * @param array $items List of items to be displayed in the definition list. * @param bool $mainMenu Set it to TRUE to render the main menu * @return string Formatted definition list */ public function renderListMenu($items, $mainMenu = false) { $assigns = []; $assigns['mainMenu'] = $mainMenu; // Change the sorting of items to the user's one if ($mainMenu) { $userSorting = unserialize($this->getBackendUser()->uc['taskcenter']['sorting']); if (is_array($userSorting)) { $newSorting = []; foreach ($userSorting as $item) { if (isset($items[$item])) { $newSorting[] = $items[$item]; unset($items[$item]); } } $items = $newSorting + $items; } } if (is_array($items) && !empty($items)) { foreach ($items as $itemKey => &$item) { // Check for custom icon if (!empty($item['icon'])) { if (strpos($item['icon'], '<img ') === false) { $iconFile = GeneralUtility::getFileAbsFileName($item['icon']); if (@is_file($iconFile)) { $item['iconFile'] = PathUtility::getAbsoluteWebPath($iconFile); } } } $id = $this->getUniqueKey($item['uid']); $contentId = strtolower(str_replace('\\', '-', $id)); $item['uniqueKey'] = $id; $item['contentId'] = $contentId; // Collapsed & expanded menu items if (isset($this->getBackendUser()->uc['taskcenter']['states'][$id]) && $this->getBackendUser()->uc['taskcenter']['states'][$id]) { $item['ariaExpanded'] = 'true'; $item['collapseIcon'] = 'actions-view-list-expand'; $item['collapsed'] = ''; } else { $item['ariaExpanded'] = 'false'; $item['collapseIcon'] = 'actions-view-list-collapse'; $item['collapsed'] = 'in'; } // Active menu item $panelState = (string) $this->MOD_SETTINGS['function'] == $item['uid'] ? 'panel-active' : 'panel-default'; $item['panelState'] = $panelState; } } $assigns['items'] = $items; // Rendering of the output via fluid $view = GeneralUtility::makeInstance(StandaloneView::class); $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:taskcenter/Resources/Private/Templates/ListMenu.html')); $view->assignMultiple($assigns); return $view->render(); }
/** * Return a JS array for special anchor classes * * @return string classesAnchor array definition */ public function buildJSClassesAnchorArray() { $JSClassesAnchorArray = 'HTMLArea.classesAnchorSetup = [ ' . LF; $classesAnchorIndex = 0; foreach ($this->configuration['RTEsetup']['properties']['classesAnchor.'] as $label => $conf) { if (is_array($conf) && $conf['class']) { $JSClassesAnchorArray .= ($classesAnchorIndex++ ? ',' : '') . ' { ' . LF; $index = 0; $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'name : "' . str_replace('"', '', str_replace('\'', '', $conf['class'])) . '"' . LF; if ($conf['type']) { $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'type : "' . str_replace('"', '', str_replace('\'', '', $conf['type'])) . '"' . LF; } if (trim(str_replace('\'', '', str_replace('"', '', $conf['image'])))) { $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'image : "' . GeneralUtility::locationHeaderUrl(PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName(trim(str_replace('\'', '', str_replace('"', '', $conf['image'])))))) . '"' . LF; } $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'addIconAfterLink : ' . ($conf['addIconAfterLink'] ? 'true' : 'false') . LF; if (trim($conf['altText'])) { $string = GeneralUtility::quoteJSvalue($this->getLanguageService()->sL(trim($conf['altText']))); $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'altText : ' . str_replace('"', '\\"', str_replace('\\\'', '\'', $string)) . LF; } if (trim($conf['titleText'])) { $string = GeneralUtility::quoteJSvalue($this->getLanguageService()->sL(trim($conf['titleText']))); $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'titleText : ' . str_replace('"', '\\"', str_replace('\\\'', '\'', $string)) . LF; } if (trim($conf['target'])) { $JSClassesAnchorArray .= ($index++ ? ',' : '') . 'target : "' . trim($conf['target']) . '"' . LF; } $JSClassesAnchorArray .= '}' . LF; } } $JSClassesAnchorArray .= '];' . LF; return $JSClassesAnchorArray; }
/** * Rendering normal HTML-page with header by wrapping the generated content ($pageContent) in body-tags and setting the header accordingly. * * @param string $pageContent The page content which TypoScript objects has generated * @return void */ public static function renderContentWithHeader($pageContent) { /** @var TypoScriptFrontendController $tsfe */ $tsfe = $GLOBALS['TSFE']; /** @var TimeTracker $timeTracker */ $timeTracker = GeneralUtility::makeInstance(TimeTracker::class); $pageRenderer = static::getPageRenderer(); if ($tsfe->config['config']['moveJsFromHeaderToFooter']) { $pageRenderer->enableMoveJsFromHeaderToFooter(); } if ($tsfe->config['config']['pageRendererTemplateFile']) { $file = $tsfe->tmpl->getFileName($tsfe->config['config']['pageRendererTemplateFile']); if ($file) { $pageRenderer->setTemplateFile($file); } } $headerComment = $tsfe->config['config']['headerComment']; if (trim($headerComment)) { $pageRenderer->addInlineComment(TAB . str_replace(LF, LF . TAB, trim($headerComment)) . LF); } // Setting charset: $theCharset = $tsfe->metaCharset; // Reset the content variables: $tsfe->content = ''; $htmlTagAttributes = array(); $htmlLang = $tsfe->config['config']['htmlTag_langKey'] ?: ($tsfe->sys_language_isocode ?: 'en'); // Set content direction: (More info: http://www.tau.ac.il/~danon/Hebrew/HTML_and_Hebrew.html) if ($tsfe->config['config']['htmlTag_dir']) { $htmlTagAttributes['dir'] = htmlspecialchars($tsfe->config['config']['htmlTag_dir']); } // Setting document type: $docTypeParts = array(); $xmlDocument = true; // Part 1: XML prologue switch ((string) $tsfe->config['config']['xmlprologue']) { case 'none': $xmlDocument = false; break; case 'xml_10': $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>'; break; case 'xml_11': $docTypeParts[] = '<?xml version="1.1" encoding="' . $theCharset . '"?>'; break; case '': if ($tsfe->xhtmlVersion) { $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>'; } else { $xmlDocument = false; } break; default: $docTypeParts[] = $tsfe->config['config']['xmlprologue']; } // Part 2: DTD $doctype = $tsfe->config['config']['doctype']; if ($doctype) { switch ($doctype) { case 'xhtml_trans': $docTypeParts[] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'; break; case 'xhtml_strict': $docTypeParts[] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; break; case 'xhtml_frames': $docTypeParts[] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'; break; case 'xhtml_basic': $docTypeParts[] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">'; break; case 'xhtml_11': $docTypeParts[] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'; break; case 'xhtml+rdfa_10': $docTypeParts[] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">'; break; case 'html5': $docTypeParts[] = '<!DOCTYPE html>'; if ($xmlDocument) { $pageRenderer->setMetaCharsetTag('<meta charset="|" />'); } else { $pageRenderer->setMetaCharsetTag('<meta charset="|">'); } break; case 'none': break; default: $docTypeParts[] = $doctype; } } else { $docTypeParts[] = '<!DOCTYPE html>'; if ($xmlDocument) { $pageRenderer->setMetaCharsetTag('<meta charset="|" />'); } else { $pageRenderer->setMetaCharsetTag('<meta charset="|">'); } } if ($tsfe->xhtmlVersion) { $htmlTagAttributes['xml:lang'] = $htmlLang; } if ($tsfe->xhtmlVersion < 110 || $doctype === 'html5') { $htmlTagAttributes['lang'] = $htmlLang; } if ($tsfe->xhtmlVersion || $doctype === 'html5' && $xmlDocument) { // We add this to HTML5 to achieve a slightly better backwards compatibility $htmlTagAttributes['xmlns'] = 'http://www.w3.org/1999/xhtml'; if (is_array($tsfe->config['config']['namespaces.'])) { foreach ($tsfe->config['config']['namespaces.'] as $prefix => $uri) { // $uri gets htmlspecialchared later $htmlTagAttributes['xmlns:' . htmlspecialchars($prefix)] = $uri; } } } // Swap XML and doctype order around (for MSIE / Opera standards compliance) if ($tsfe->config['config']['doctypeSwitch']) { $docTypeParts = array_reverse($docTypeParts); } // Adding doctype parts: if (!empty($docTypeParts)) { $pageRenderer->setXmlPrologAndDocType(implode(LF, $docTypeParts)); } // Begin header section: if ($tsfe->config['config']['htmlTag_setParams'] !== 'none') { $_attr = $tsfe->config['config']['htmlTag_setParams'] ? $tsfe->config['config']['htmlTag_setParams'] : GeneralUtility::implodeAttributes($htmlTagAttributes); } else { $_attr = ''; } $htmlTag = '<html' . ($_attr ? ' ' . $_attr : '') . '>'; if (isset($tsfe->config['config']['htmlTag_stdWrap.'])) { $htmlTag = $tsfe->cObj->stdWrap($htmlTag, $tsfe->config['config']['htmlTag_stdWrap.']); } $pageRenderer->setHtmlTag($htmlTag); // Head tag: $headTag = $tsfe->pSetup['headTag'] ?: '<head>'; if (isset($tsfe->pSetup['headTag.'])) { $headTag = $tsfe->cObj->stdWrap($headTag, $tsfe->pSetup['headTag.']); } $pageRenderer->setHeadTag($headTag); // Setting charset meta tag: $pageRenderer->setCharSet($theCharset); $pageRenderer->addInlineComment(' This website is powered by TYPO3 - inspiring people to share! TYPO3 is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL. TYPO3 is copyright ' . TYPO3_copyright_year . ' of Kasper Skaarhoj. Extensions are copyright of their respective owners. Information and contribution at ' . TYPO3_URL_GENERAL . ' '); if ($tsfe->baseUrl) { $pageRenderer->setBaseUrl($tsfe->baseUrl); } if ($tsfe->pSetup['shortcutIcon']) { $favIcon = ltrim($tsfe->tmpl->getFileName($tsfe->pSetup['shortcutIcon']), '/'); $iconFileInfo = GeneralUtility::makeInstance(ImageInfo::class, PATH_site . $favIcon); if ($iconFileInfo->isFile()) { $iconMimeType = $iconFileInfo->getMimeType(); if ($iconMimeType) { $iconMimeType = ' type="' . $iconMimeType . '"'; $pageRenderer->setIconMimeType($iconMimeType); } $pageRenderer->setFavIcon(PathUtility::getAbsoluteWebPath($tsfe->absRefPrefix . $favIcon)); } } // Including CSS files if (is_array($tsfe->tmpl->setup['plugin.'])) { $stylesFromPlugins = ''; foreach ($tsfe->tmpl->setup['plugin.'] as $key => $iCSScode) { if (is_array($iCSScode)) { if ($iCSScode['_CSS_DEFAULT_STYLE'] && empty($tsfe->config['config']['removeDefaultCss'])) { if (isset($iCSScode['_CSS_DEFAULT_STYLE.'])) { $cssDefaultStyle = $tsfe->cObj->stdWrap($iCSScode['_CSS_DEFAULT_STYLE'], $iCSScode['_CSS_DEFAULT_STYLE.']); } else { $cssDefaultStyle = $iCSScode['_CSS_DEFAULT_STYLE']; } $stylesFromPlugins .= '/* default styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssDefaultStyle . LF; } if ($iCSScode['_CSS_PAGE_STYLE'] && empty($tsfe->config['config']['removePageCss'])) { $cssPageStyle = implode(LF, $iCSScode['_CSS_PAGE_STYLE']); if (isset($iCSScode['_CSS_PAGE_STYLE.'])) { $cssPageStyle = $tsfe->cObj->stdWrap($cssPageStyle, $iCSScode['_CSS_PAGE_STYLE.']); } $cssPageStyle = '/* specific page styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssPageStyle; self::addCssToPageRenderer($cssPageStyle, true); } } } if (!empty($stylesFromPlugins)) { self::addCssToPageRenderer($stylesFromPlugins); } } if ($tsfe->pSetup['stylesheet']) { $ss = $tsfe->tmpl->getFileName($tsfe->pSetup['stylesheet']); if ($ss) { $pageRenderer->addCssFile($ss); } } /**********************************************************************/ /* config.includeCSS / config.includeCSSLibs /**********************************************************************/ if (is_array($tsfe->pSetup['includeCSS.'])) { foreach ($tsfe->pSetup['includeCSS.'] as $key => $CSSfile) { if (!is_array($CSSfile)) { $cssFileConfig =& $tsfe->pSetup['includeCSS.'][$key . '.']; if (isset($cssFileConfig['if.']) && !$tsfe->cObj->checkIf($cssFileConfig['if.'])) { continue; } $ss = $cssFileConfig['external'] ? $CSSfile : $tsfe->tmpl->getFileName($CSSfile); if ($ss) { if ($cssFileConfig['import']) { if (!$cssFileConfig['external'] && $ss[0] !== '/') { // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende) $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss; } $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '") ' . htmlspecialchars($cssFileConfig['media']) . ';', empty($cssFileConfig['disableCompression']), (bool) $cssFileConfig['forceOnTop'], ''); } else { $pageRenderer->addCssFile($ss, $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet', $cssFileConfig['media'] ?: 'all', $cssFileConfig['title'] ?: '', empty($cssFileConfig['disableCompression']), (bool) $cssFileConfig['forceOnTop'], $cssFileConfig['allWrap'], (bool) $cssFileConfig['excludeFromConcatenation'], $cssFileConfig['allWrap.']['splitChar']); unset($cssFileConfig); } } } } } if (is_array($tsfe->pSetup['includeCSSLibs.'])) { foreach ($tsfe->pSetup['includeCSSLibs.'] as $key => $CSSfile) { if (!is_array($CSSfile)) { $cssFileConfig =& $tsfe->pSetup['includeCSSLibs.'][$key . '.']; if (isset($cssFileConfig['if.']) && !$tsfe->cObj->checkIf($cssFileConfig['if.'])) { continue; } $ss = $cssFileConfig['external'] ? $CSSfile : $tsfe->tmpl->getFileName($CSSfile); if ($ss) { if ($cssFileConfig['import']) { if (!$cssFileConfig['external'] && $ss[0] !== '/') { // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende) $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss; } $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '") ' . htmlspecialchars($cssFileConfig['media']) . ';', empty($cssFileConfig['disableCompression']), (bool) $cssFileConfig['forceOnTop'], ''); } else { $pageRenderer->addCssLibrary($ss, $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet', $cssFileConfig['media'] ?: 'all', $cssFileConfig['title'] ?: '', empty($cssFileConfig['disableCompression']), (bool) $cssFileConfig['forceOnTop'], $cssFileConfig['allWrap'], (bool) $cssFileConfig['excludeFromConcatenation'], $cssFileConfig['allWrap.']['splitChar']); unset($cssFileConfig); } } } } } // Stylesheets $style = ''; if ($tsfe->pSetup['insertClassesFromRTE']) { $pageTSConfig = $tsfe->getPagesTSconfig(); $RTEclasses = $pageTSConfig['RTE.']['classes.']; if (is_array($RTEclasses)) { foreach ($RTEclasses as $RTEclassName => $RTEvalueArray) { if ($RTEvalueArray['value']) { $style .= ' .' . substr($RTEclassName, 0, -1) . ' {' . $RTEvalueArray['value'] . '}'; } } } if ($tsfe->pSetup['insertClassesFromRTE.']['add_mainStyleOverrideDefs'] && is_array($pageTSConfig['RTE.']['default.']['mainStyleOverride_add.'])) { $mSOa_tList = GeneralUtility::trimExplode(',', strtoupper($tsfe->pSetup['insertClassesFromRTE.']['add_mainStyleOverrideDefs']), true); foreach ($pageTSConfig['RTE.']['default.']['mainStyleOverride_add.'] as $mSOa_key => $mSOa_value) { if (!is_array($mSOa_value) && (in_array('*', $mSOa_tList) || in_array($mSOa_key, $mSOa_tList))) { $style .= ' ' . $mSOa_key . ' {' . $mSOa_value . '}'; } } } } // Setting body tag margins in CSS: if (isset($tsfe->pSetup['bodyTagMargins']) && $tsfe->pSetup['bodyTagMargins.']['useCSS']) { $margins = (int) $tsfe->pSetup['bodyTagMargins']; $style .= ' BODY {margin: ' . $margins . 'px ' . $margins . 'px ' . $margins . 'px ' . $margins . 'px;}'; } // CSS_inlineStyle from TS $style .= trim($tsfe->pSetup['CSS_inlineStyle']); $style .= $tsfe->cObj->cObjGet($tsfe->pSetup['cssInline.'], 'cssInline.'); if (trim($style)) { self::addCssToPageRenderer($style, true, 'additionalTSFEInlineStyle'); } // Javascript Libraries if (is_array($tsfe->pSetup['javascriptLibs.'])) { // Include jQuery into the page renderer if (!empty($tsfe->pSetup['javascriptLibs.']['jQuery'])) { $jQueryTS = $tsfe->pSetup['javascriptLibs.']['jQuery.']; // Check if version / source is set, if not set variable to "NULL" to use the default of the page renderer $version = isset($jQueryTS['version']) ? $jQueryTS['version'] : null; $source = isset($jQueryTS['source']) ? $jQueryTS['source'] : null; // When "noConflict" is not set or "1" enable the default jQuery noConflict mode, otherwise disable the namespace if (!isset($jQueryTS['noConflict']) || !empty($jQueryTS['noConflict'])) { // Set namespace to the "noConflict.namespace" value if "noConflict.namespace" has a value if (!empty($jQueryTS['noConflict.']['namespace'])) { $namespace = $jQueryTS['noConflict.']['namespace']; } else { $namespace = PageRenderer::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT; } } else { $namespace = PageRenderer::JQUERY_NAMESPACE_NONE; } $pageRenderer->loadJquery($version, $source, $namespace); } if ($tsfe->pSetup['javascriptLibs.']['ExtJs']) { $css = (bool) $tsfe->pSetup['javascriptLibs.']['ExtJs.']['css']; $theme = (bool) $tsfe->pSetup['javascriptLibs.']['ExtJs.']['theme']; $pageRenderer->loadExtJS($css, $theme); if ($tsfe->pSetup['javascriptLibs.']['ExtJs.']['debug']) { $pageRenderer->enableExtJsDebug(); } } } // JavaScript library files if (is_array($tsfe->pSetup['includeJSLibs.'])) { foreach ($tsfe->pSetup['includeJSLibs.'] as $key => $JSfile) { if (!is_array($JSfile)) { if (isset($tsfe->pSetup['includeJSLibs.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJSLibs.'][$key . '.']['if.'])) { continue; } $ss = $tsfe->pSetup['includeJSLibs.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile); if ($ss) { $jsFileConfig =& $tsfe->pSetup['includeJSLibs.'][$key . '.']; $type = $jsFileConfig['type']; if (!$type) { $type = 'text/javascript'; } $pageRenderer->addJsLibrary($key, $ss, $type, empty($jsFileConfig['disableCompression']), (bool) $jsFileConfig['forceOnTop'], $jsFileConfig['allWrap'], (bool) $jsFileConfig['excludeFromConcatenation'], $jsFileConfig['allWrap.']['splitChar'], (bool) $jsFileConfig['async'], $jsFileConfig['integrity']); unset($jsFileConfig); } } } } if (is_array($tsfe->pSetup['includeJSFooterlibs.'])) { foreach ($tsfe->pSetup['includeJSFooterlibs.'] as $key => $JSfile) { if (!is_array($JSfile)) { if (isset($tsfe->pSetup['includeJSFooterlibs.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJSFooterlibs.'][$key . '.']['if.'])) { continue; } $ss = $tsfe->pSetup['includeJSFooterlibs.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile); if ($ss) { $jsFileConfig =& $tsfe->pSetup['includeJSFooterlibs.'][$key . '.']; $type = $jsFileConfig['type']; if (!$type) { $type = 'text/javascript'; } $pageRenderer->addJsFooterLibrary($key, $ss, $type, empty($jsFileConfig['disableCompression']), (bool) $jsFileConfig['forceOnTop'], $jsFileConfig['allWrap'], (bool) $jsFileConfig['excludeFromConcatenation'], $jsFileConfig['allWrap.']['splitChar'], (bool) $jsFileConfig['async'], $jsFileConfig['integrity']); unset($jsFileConfig); } } } } // JavaScript files if (is_array($tsfe->pSetup['includeJS.'])) { foreach ($tsfe->pSetup['includeJS.'] as $key => $JSfile) { if (!is_array($JSfile)) { if (isset($tsfe->pSetup['includeJS.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJS.'][$key . '.']['if.'])) { continue; } $ss = $tsfe->pSetup['includeJS.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile); if ($ss) { $jsConfig =& $tsfe->pSetup['includeJS.'][$key . '.']; $type = $jsConfig['type']; if (!$type) { $type = 'text/javascript'; } $pageRenderer->addJsFile($ss, $type, empty($jsConfig['disableCompression']), (bool) $jsConfig['forceOnTop'], $jsConfig['allWrap'], (bool) $jsConfig['excludeFromConcatenation'], $jsConfig['allWrap.']['splitChar'], (bool) $jsConfig['async'], $jsConfig['integrity']); unset($jsConfig); } } } } if (is_array($tsfe->pSetup['includeJSFooter.'])) { foreach ($tsfe->pSetup['includeJSFooter.'] as $key => $JSfile) { if (!is_array($JSfile)) { if (isset($tsfe->pSetup['includeJSFooter.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJSFooter.'][$key . '.']['if.'])) { continue; } $ss = $tsfe->pSetup['includeJSFooter.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile); if ($ss) { $jsConfig =& $tsfe->pSetup['includeJSFooter.'][$key . '.']; $type = $jsConfig['type']; if (!$type) { $type = 'text/javascript'; } $pageRenderer->addJsFooterFile($ss, $type, empty($jsConfig['disableCompression']), (bool) $jsConfig['forceOnTop'], $jsConfig['allWrap'], (bool) $jsConfig['excludeFromConcatenation'], $jsConfig['allWrap.']['splitChar'], (bool) $jsConfig['async'], $jsConfig['integrity']); unset($jsConfig); } } } } // Headerdata if (is_array($tsfe->pSetup['headerData.'])) { $pageRenderer->addHeaderData($tsfe->cObj->cObjGet($tsfe->pSetup['headerData.'], 'headerData.')); } // Footerdata if (is_array($tsfe->pSetup['footerData.'])) { $pageRenderer->addFooterData($tsfe->cObj->cObjGet($tsfe->pSetup['footerData.'], 'footerData.')); } static::generatePageTitle(); $metaTagsHtml = static::generateMetaTagHtml(isset($tsfe->pSetup['meta.']) ? $tsfe->pSetup['meta.'] : array(), $tsfe->xhtmlVersion, $tsfe->cObj); foreach ($metaTagsHtml as $metaTag) { $pageRenderer->addMetaTag($metaTag); } unset($tsfe->additionalHeaderData['JSCode']); if (is_array($tsfe->config['INTincScript'])) { $tsfe->additionalHeaderData['JSCode'] = $tsfe->JSCode; // Storing the JSCode vars... $tsfe->config['INTincScript_ext']['divKey'] = $tsfe->uniqueHash(); $tsfe->config['INTincScript_ext']['additionalHeaderData'] = $tsfe->additionalHeaderData; // Storing the header-data array $tsfe->config['INTincScript_ext']['additionalFooterData'] = $tsfe->additionalFooterData; // Storing the footer-data array $tsfe->config['INTincScript_ext']['additionalJavaScript'] = $tsfe->additionalJavaScript; // Storing the JS-data array $tsfe->config['INTincScript_ext']['additionalCSS'] = $tsfe->additionalCSS; // Storing the Style-data array $tsfe->additionalHeaderData = array('<!--HD_' . $tsfe->config['INTincScript_ext']['divKey'] . '-->'); // Clearing the array $tsfe->additionalFooterData = array('<!--FD_' . $tsfe->config['INTincScript_ext']['divKey'] . '-->'); // Clearing the array $tsfe->divSection .= '<!--TDS_' . $tsfe->config['INTincScript_ext']['divKey'] . '-->'; } else { $tsfe->INTincScript_loadJSCode(); } $scriptJsCode = ''; if ($tsfe->spamProtectEmailAddresses && $tsfe->spamProtectEmailAddresses !== 'ascii') { $scriptJsCode = ' // decrypt helper function function decryptCharcode(n,start,end,offset) { n = n + offset; if (offset > 0 && n > end) { n = start + (n - end - 1); } else if (offset < 0 && n < start) { n = end - (start - n - 1); } return String.fromCharCode(n); } // decrypt string function decryptString(enc,offset) { var dec = ""; var len = enc.length; for(var i=0; i < len; i++) { var n = enc.charCodeAt(i); if (n >= 0x2B && n <= 0x3A) { dec += decryptCharcode(n,0x2B,0x3A,offset); // 0-9 . , - + / : } else if (n >= 0x40 && n <= 0x5A) { dec += decryptCharcode(n,0x40,0x5A,offset); // A-Z @ } else if (n >= 0x61 && n <= 0x7A) { dec += decryptCharcode(n,0x61,0x7A,offset); // a-z } else { dec += enc.charAt(i); } } return dec; } // decrypt spam-protected emails function linkTo_UnCryptMailto(s) { location.href = decryptString(s,' . $tsfe->spamProtectEmailAddresses * -1 . '); } '; } // Add inline JS $inlineJS = ''; // defined in php if (is_array($tsfe->inlineJS)) { foreach ($tsfe->inlineJS as $key => $val) { if (!is_array($val)) { $inlineJS .= LF . $val . LF; } } } // defined in TS with page.inlineJS // Javascript inline code $inline = $tsfe->cObj->cObjGet($tsfe->pSetup['jsInline.'], 'jsInline.'); if ($inline) { $inlineJS .= LF . $inline . LF; } // Javascript inline code for Footer $inlineFooterJs = $tsfe->cObj->cObjGet($tsfe->pSetup['jsFooterInline.'], 'jsFooterInline.'); // Should minify? if ($tsfe->config['config']['compressJs']) { $pageRenderer->enableCompressJavascript(); $minifyErrorScript = $minifyErrorInline = ''; $scriptJsCode = GeneralUtility::minifyJavaScript($scriptJsCode, $minifyErrorScript); if ($minifyErrorScript) { $timeTracker->setTSlogMessage($minifyErrorScript, 3); } if ($inlineJS) { $inlineJS = GeneralUtility::minifyJavaScript($inlineJS, $minifyErrorInline); if ($minifyErrorInline) { $timeTracker->setTSlogMessage($minifyErrorInline, 3); } } if ($inlineFooterJs) { $inlineFooterJs = GeneralUtility::minifyJavaScript($inlineFooterJs, $minifyErrorInline); if ($minifyErrorInline) { $timeTracker->setTSlogMessage($minifyErrorInline, 3); } } } if (!$tsfe->config['config']['removeDefaultJS']) { // inlude default and inlineJS if ($scriptJsCode) { $pageRenderer->addJsInlineCode('_scriptCode', $scriptJsCode, $tsfe->config['config']['compressJs']); } if ($inlineJS) { $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $tsfe->config['config']['compressJs']); } if ($inlineFooterJs) { $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $tsfe->config['config']['compressJs']); } } elseif ($tsfe->config['config']['removeDefaultJS'] === 'external') { /* * This keeps inlineJS from *_INT Objects from being moved to external files. * At this point in frontend rendering *_INT Objects only have placeholders instead * of actual content so moving these placeholders to external files would * a) break the JS file (syntax errors due to the placeholders) * b) the needed JS would never get included to the page * Therefore inlineJS from *_INT Objects must not be moved to external files but * kept internal. */ $inlineJSint = ''; self::stripIntObjectPlaceholder($inlineJS, $inlineJSint); if ($inlineJSint) { $pageRenderer->addJsInlineCode('TS_inlineJSint', $inlineJSint, $tsfe->config['config']['compressJs']); } if (trim($scriptJsCode . $inlineJS)) { $pageRenderer->addJsFile(self::inline2TempFile($scriptJsCode . $inlineJS, 'js'), 'text/javascript', $tsfe->config['config']['compressJs']); } if ($inlineFooterJs) { $inlineFooterJSint = ''; self::stripIntObjectPlaceholder($inlineFooterJs, $inlineFooterJSint); if ($inlineFooterJSint) { $pageRenderer->addJsFooterInlineCode('TS_inlineFooterJSint', $inlineFooterJSint, $tsfe->config['config']['compressJs']); } $pageRenderer->addJsFooterFile(self::inline2TempFile($inlineFooterJs, 'js'), 'text/javascript', $tsfe->config['config']['compressJs']); } } else { // Include only inlineJS if ($inlineJS) { $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $tsfe->config['config']['compressJs']); } if ($inlineFooterJs) { $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $tsfe->config['config']['compressJs']); } } if (is_array($tsfe->pSetup['inlineLanguageLabelFiles.'])) { foreach ($tsfe->pSetup['inlineLanguageLabelFiles.'] as $key => $languageFile) { if (is_array($languageFile)) { continue; } $languageFileConfig =& $tsfe->pSetup['inlineLanguageLabelFiles.'][$key . '.']; if (isset($languageFileConfig['if.']) && !$tsfe->cObj->checkIf($languageFileConfig['if.'])) { continue; } $pageRenderer->addInlineLanguageLabelFile($languageFile, $languageFileConfig['selectionPrefix'] ?: '', $languageFileConfig['stripFromSelectionName'] ?: '', $languageFileConfig['errorMode'] ? (int) $languageFileConfig['errorMode'] : 0); } } // ExtJS specific code if (is_array($tsfe->pSetup['inlineLanguageLabel.'])) { $pageRenderer->addInlineLanguageLabelArray($tsfe->pSetup['inlineLanguageLabel.'], true); } if (is_array($tsfe->pSetup['inlineSettings.'])) { $pageRenderer->addInlineSettingArray('TS', $tsfe->pSetup['inlineSettings.']); } if (is_array($tsfe->pSetup['extOnReady.'])) { $pageRenderer->addExtOnReadyCode($tsfe->cObj->cObjGet($tsfe->pSetup['extOnReady.'], 'extOnReady.')); } // Compression and concatenate settings if ($tsfe->config['config']['compressCss']) { $pageRenderer->enableCompressCss(); } if ($tsfe->config['config']['compressJs']) { $pageRenderer->enableCompressJavascript(); } if ($tsfe->config['config']['concatenateCss']) { $pageRenderer->enableConcatenateCss(); } if ($tsfe->config['config']['concatenateJs']) { $pageRenderer->enableConcatenateJavascript(); } // Backward compatibility for old configuration if ($tsfe->config['config']['concatenateJsAndCss']) { $pageRenderer->enableConcatenateFiles(); } // Add header data block if ($tsfe->additionalHeaderData) { $pageRenderer->addHeaderData(implode(LF, $tsfe->additionalHeaderData)); } // Add footer data block if ($tsfe->additionalFooterData) { $pageRenderer->addFooterData(implode(LF, $tsfe->additionalFooterData)); } // Header complete, now add content if ($tsfe->pSetup['frameSet.']) { $fs = GeneralUtility::makeInstance(FramesetRenderer::class); $pageRenderer->addBodyContent($fs->make($tsfe->pSetup['frameSet.'])); $pageRenderer->addBodyContent(LF . '<noframes>' . LF); } // Bodytag: if ($tsfe->config['config']['disableBodyTag']) { $bodyTag = ''; } else { $defBT = $tsfe->pSetup['bodyTagCObject'] ? $tsfe->cObj->cObjGetSingle($tsfe->pSetup['bodyTagCObject'], $tsfe->pSetup['bodyTagCObject.'], 'bodyTagCObject') : ''; if (!$defBT) { $defBT = $tsfe->defaultBodyTag; } $bodyTag = $tsfe->pSetup['bodyTag'] ? $tsfe->pSetup['bodyTag'] : $defBT; if (isset($tsfe->pSetup['bodyTagMargins'])) { $margins = (int) $tsfe->pSetup['bodyTagMargins']; if ($tsfe->pSetup['bodyTagMargins.']['useCSS']) { } else { $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' leftmargin="' . $margins . '" topmargin="' . $margins . '" marginwidth="' . $margins . '" marginheight="' . $margins . '">'; } } if (trim($tsfe->pSetup['bodyTagAdd'])) { $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' ' . trim($tsfe->pSetup['bodyTagAdd']) . '>'; } } $pageRenderer->addBodyContent(LF . $bodyTag); // Div-sections if ($tsfe->divSection) { $pageRenderer->addBodyContent(LF . $tsfe->divSection); } // Page content $pageRenderer->addBodyContent(LF . $pageContent); if (!empty($tsfe->config['INTincScript']) && is_array($tsfe->config['INTincScript'])) { // Store the serialized pageRenderer in configuration $tsfe->config['INTincScript_ext']['pageRenderer'] = serialize($pageRenderer); // Render complete page, keep placeholders for JavaScript and CSS $tsfe->content = $pageRenderer->renderPageWithUncachedObjects($tsfe->config['INTincScript_ext']['divKey']); } else { // Render complete page $tsfe->content = $pageRenderer->render(); } // Ending page if ($tsfe->pSetup['frameSet.']) { $tsfe->content .= LF . '</noframes>'; } }
/** * Basically makes sure that the workspace preview is rendered. * The preview itself consists of three frames, so there are * only the frames-urls we've to generate here * * @param int $previewWS * @return void */ public function indexAction($previewWS = null) { $backendUser = $this->getBackendUser(); // Get all the GET parameters to pass them on to the frames $queryParameters = GeneralUtility::_GET(); // Remove the GET parameters related to the workspaces module and the page id unset($queryParameters['tx_workspaces_web_workspacesworkspaces']); unset($queryParameters['M']); unset($queryParameters['id']); // Assemble a query string from the retrieved parameters $queryString = GeneralUtility::implodeArrayForUrl('', $queryParameters); // fetch the next and previous stage $workspaceItemsArray = $this->workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), $filter = 1, $stage = -99, $this->pageId, $recursionLevel = 0, $selectionType = 'tables_modify'); list(, $nextStage) = $this->stageService->getNextStageForElementCollection($workspaceItemsArray); list(, $previousStage) = $this->stageService->getPreviousStageForElementCollection($workspaceItemsArray); /** @var $wsService WorkspaceService */ $wsService = GeneralUtility::makeInstance(WorkspaceService::class); $wsList = $wsService->getAvailableWorkspaces(); $activeWorkspace = $backendUser->workspace; if (!is_null($previewWS)) { if (in_array($previewWS, array_keys($wsList)) && $activeWorkspace != $previewWS) { $activeWorkspace = $previewWS; $backendUser->setWorkspace($activeWorkspace); BackendUtility::setUpdateSignal('updatePageTree'); } } /** @var $uriBuilder UriBuilder */ $uriBuilder = $this->objectManager->get(UriBuilder::class); $wsSettingsPath = GeneralUtility::getIndpEnv('TYPO3_SITE_URL'); $wsSettingsUri = $uriBuilder->uriFor('singleIndex', array(), ReviewController::class, 'workspaces', 'web_workspacesworkspaces'); $wsSettingsParams = '&tx_workspaces_web_workspacesworkspaces[controller]=Review'; $wsSettingsUrl = $wsSettingsPath . $wsSettingsUri . $wsSettingsParams; $viewDomain = BackendUtility::getViewDomain($this->pageId); $wsBaseUrl = $viewDomain . '/index.php?id=' . $this->pageId . $queryString; // @todo - handle new pages here // branchpoints are not handled anymore because this feature is not supposed anymore if (WorkspaceService::isNewPage($this->pageId)) { $wsNewPageUri = $uriBuilder->uriFor('newPage', array(), PreviewController::class, 'workspaces', 'web_workspacesworkspaces'); $wsNewPageParams = '&tx_workspaces_web_workspacesworkspaces[controller]=Preview'; $liveUrl = $wsSettingsPath . $wsNewPageUri . $wsNewPageParams . '&ADMCMD_prev=IGNORE'; } else { $liveUrl = $wsBaseUrl . '&ADMCMD_noBeUser=1&ADMCMD_prev=IGNORE'; } $wsUrl = $wsBaseUrl . '&ADMCMD_prev=IGNORE&ADMCMD_view=1&ADMCMD_editIcons=1&ADMCMD_previewWS=' . $backendUser->workspace; $backendDomain = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'); $splitPreviewTsConfig = BackendUtility::getModTSconfig($this->pageId, 'workspaces.splitPreviewModes'); $splitPreviewModes = GeneralUtility::trimExplode(',', $splitPreviewTsConfig['value']); $allPreviewModes = array('slider', 'vbox', 'hbox'); if (!array_intersect($splitPreviewModes, $allPreviewModes)) { $splitPreviewModes = $allPreviewModes; } $wsList = $wsService->getAvailableWorkspaces(); $activeWorkspace = $backendUser->workspace; $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Workspaces/Preview'); $this->pageRenderer->addInlineSetting('Workspaces', 'SplitPreviewModes', $splitPreviewModes); $this->pageRenderer->addInlineSetting('Workspaces', 'token', FormProtectionFactory::get('backend')->generateToken('extDirect')); $cssFile = 'EXT:workspaces/Resources/Public/Css/preview.css'; $cssFile = GeneralUtility::getFileAbsFileName($cssFile); $this->pageRenderer->addCssFile(PathUtility::getAbsoluteWebPath($cssFile)); $backendUser->setAndSaveSessionData('workspaces.backend_domain', GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY')); $logoPath = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/Images/typo3-topbar@2x.png'); list($logoWidth, $logoHeight) = @getimagesize($logoPath); // High-resolution? $logoWidth = $logoWidth / 2; $logoHeight = $logoHeight / 2; $this->view->assignMultiple(['logoUrl' => PathUtility::getAbsoluteWebPath($logoPath), 'logoLink' => TYPO3_URL_GENERAL, 'logoWidth' => $logoWidth, 'logoHeight' => $logoHeight, 'liveUrl' => $liveUrl, 'wsUrl' => $wsUrl, 'wsSettingsUrl' => $wsSettingsUrl, 'backendDomain' => $backendDomain, 'activeWorkspace' => $wsList[$activeWorkspace], 'splitPreviewModes' => $splitPreviewModes, 'firstPreviewMode' => current($splitPreviewModes), 'enablePreviousStageButton' => !$this->isInvalidStage($previousStage), 'enableNextStageButton' => !$this->isInvalidStage($nextStage), 'enableDiscardStageButton' => !$this->isInvalidStage($nextStage) || !$this->isInvalidStage($previousStage), 'nextStage' => $nextStage['title'], 'nextStageId' => $nextStage['uid'], 'prevStage' => $previousStage['title'], 'prevStageId' => $previousStage['uid']]); foreach ($this->getAdditionalResourceService()->getLocalizationResources() as $localizationResource) { $this->pageRenderer->addInlineLanguageLabelFile($localizationResource); } }
/** * Get configuration of external/additional plugins * * @return array */ protected function getExternalPlugins() : array { // todo: find new name for this option (do we still need this?) // Initializing additional attributes $additionalAttributes = []; if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rte_ckeditor']['plugins']['TYPO3Link']['additionalAttributes']) { $additionalAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rte_ckeditor']['plugins']['TYPO3Link']['additionalAttributes'], true); } $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); // todo: add api for this https://forge.typo3.org/issues/78929 $pluginPath = PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('rte_ckeditor', 'Resources/Public/JavaScript/Plugins/typo3link.js')); $externalPlugins = ['typo3link' => ['path' => $pluginPath, 'config' => ['routeUrl' => (string) $uriBuilder->buildUriFromRoute('rteckeditor_wizard_browse_links'), 'additionalAttributes' => $additionalAttributes]]]; return $externalPlugins; }
/** * Add hooks from the additional backend items to load certain things for the main backend. * This was previously called from the global scope from backend.php. */ protected function includeLegacyBackendItems() { $TYPO3backend = $this; // Include extensions which may add css, javascript or toolbar items if (is_array($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'] as $additionalBackendItem) { include_once $additionalBackendItem; } } // Process ExtJS module js and css if (is_array($GLOBALS['TBE_MODULES']['_configuration'])) { foreach ($GLOBALS['TBE_MODULES']['_configuration'] as $moduleConfig) { if (is_array($moduleConfig['cssFiles'])) { foreach ($moduleConfig['cssFiles'] as $cssFileName => $cssFile) { $cssFile = GeneralUtility::getFileAbsFileName($cssFile); $cssFile = PathUtility::getAbsoluteWebPath($cssFile); $TYPO3backend->addCssFile($cssFileName, $cssFile); } } if (is_array($moduleConfig['jsFiles'])) { foreach ($moduleConfig['jsFiles'] as $jsFile) { $jsFile = GeneralUtility::getFileAbsFileName($jsFile); $jsFile = PathUtility::getAbsoluteWebPath($jsFile); $TYPO3backend->addJavascriptFile($jsFile); } } } } }
/** * Renders the $icon, supports a filename for skinImg or sprite-icon-name * * @param string $icon The icon passed, could be a file-reference or a sprite Icon name * @param string $alt Alt attribute of the icon returned * @param string $title Title attribute of the icon return * @return string A tag representing to show the asked icon * @internal */ public static function getIconHtml($icon, $alt = '', $title = '') { $icon = (string) $icon; $absoluteFilePath = GeneralUtility::getFileAbsFileName($icon); if (!empty($absoluteFilePath) && is_file($absoluteFilePath)) { $iconInfo = StringUtility::endsWith($absoluteFilePath, '.svg') ? true : getimagesize($absoluteFilePath); if ($iconInfo !== false) { return '<img' . ' src="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($absoluteFilePath)) . '"' . ' alt="' . htmlspecialchars($alt) . '" ' . ($title ? 'title="' . htmlspecialchars($title) . '"' : '') . ' />'; } } $iconFactory = GeneralUtility::makeInstance(IconFactory::class); return '<span alt="' . htmlspecialchars($alt) . '" title="' . htmlspecialchars($title) . '">' . $iconFactory->getIcon($icon, Icon::SIZE_SMALL)->render() . '</span>'; }
/** * Call function if you need the requireJS library * this automatically adds the JavaScript path of all loaded extensions in the requireJS path option * so it resolves names like TYPO3/CMS/MyExtension/MyJsFile to EXT:MyExtension/Resources/Public/JavaScript/MyJsFile.js * when using requireJS * * @return void */ public function loadRequireJs() { // load all paths to map to package names / namespaces if (empty($this->requireJsConfig)) { // In order to avoid browser caching of JS files, adding a GET parameter to the files loaded via requireJS if (GeneralUtility::getApplicationContext()->isDevelopment()) { $this->requireJsConfig['urlArgs'] = 'bust=' . $GLOBALS['EXEC_TIME']; } else { $this->requireJsConfig['urlArgs'] = 'bust=' . GeneralUtility::hmac(TYPO3_version . PATH_site); } $corePath = ExtensionManagementUtility::extPath('core', 'Resources/Public/JavaScript/Contrib/'); $corePath = PathUtility::getAbsoluteWebPath($corePath); // first, load all paths for the namespaces, and configure contrib libs. $this->requireJsConfig['paths'] = array('jquery-ui' => $corePath . 'jquery-ui', 'datatables' => $corePath . 'jquery.dataTables', 'nprogress' => $corePath . 'nprogress', 'moment' => $corePath . 'moment', 'cropper' => $corePath . 'cropper.min', 'imagesloaded' => $corePath . 'imagesloaded.pkgd.min', 'bootstrap' => $corePath . 'bootstrap/bootstrap', 'twbs/bootstrap-datetimepicker' => $corePath . 'bootstrap-datetimepicker', 'autosize' => $corePath . 'autosize', 'taboverride' => $corePath . 'taboverride.min', 'twbs/bootstrap-slider' => $corePath . 'bootstrap-slider.min', 'jquery/autocomplete' => $corePath . 'jquery.autocomplete'); // get all extensions that are loaded $loadedExtensions = ExtensionManagementUtility::getLoadedExtensionListArray(); foreach ($loadedExtensions as $packageName) { $fullJsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/'; $fullJsPath = GeneralUtility::getFileAbsFileName($fullJsPath); $fullJsPath = PathUtility::getAbsoluteWebPath($fullJsPath); $fullJsPath = rtrim($fullJsPath, '/'); if ($fullJsPath) { $this->requireJsConfig['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $fullJsPath; } } // check if additional AMD modules need to be loaded if a single AMD module is initialized if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'])) { $this->addInlineSettingArray('RequireJS.PostInitializationModules', $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules']); } } $this->addRequireJs = true; }
/** * Render a list of items as a nicely formated definition list including a * link, icon, title and description. * The keys of a single item are: * - title: Title of the item * - link: Link to the task * - icon: Path to the icon or Icon as HTML if it begins with <img * - description: Description of the task, using htmlspecialchars() * - descriptionHtml: Description allowing HTML tags which will override the * description * * @param array $items List of items to be displayed in the definition list. * @param bool $mainMenu Set it to TRUE to render the main menu * @return string Fefinition list */ public function renderListMenu($items, $mainMenu = false) { $content = $section = ''; $count = 0; // Change the sorting of items to the user's one if ($mainMenu) { $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Taskcenter/Taskcenter'); $userSorting = unserialize($this->getBackendUser()->uc['taskcenter']['sorting']); if (is_array($userSorting)) { $newSorting = array(); foreach ($userSorting as $item) { if (isset($items[$item])) { $newSorting[] = $items[$item]; unset($items[$item]); } } $items = $newSorting + $items; } } if (is_array($items) && !empty($items)) { foreach ($items as $itemKey => $item) { $title = htmlspecialchars($item['title']); $icon = $additionalClass = $collapsedStyle = ''; // Check for custom icon if (!empty($item['icon'])) { if (strpos($item['icon'], '<img ') === false) { $absIconPath = GeneralUtility::getFileAbsFileName($item['icon']); // If the file indeed exists, assemble relative path to it if (file_exists($absIconPath)) { $icon = '../' . str_replace(PATH_site, '', $absIconPath); $icon = '<img src="' . $icon . '" title="' . $title . '" alt="' . $title . '" />'; } if (@is_file($icon)) { $icon = '<img src="' . PathUtility::getAbsoluteWebPath($icon) . '" width="16" height="16" title="' . $title . '" alt="' . $title . '" />'; } } else { $icon = $item['icon']; } } $description = $item['descriptionHtml'] ?: '<p>' . nl2br(htmlspecialchars($item['description'])) . '</p>'; $id = $this->getUniqueKey($item['uid']); $contentId = strtolower(str_replace('\\', '-', $id)); // Collapsed & expanded menu items if (isset($this->getBackendUser()->uc['taskcenter']['states'][$id]) && $this->getBackendUser()->uc['taskcenter']['states'][$id]) { $collapsed = true; $collapseIcon = $this->moduleTemplate->getIconFactory()->getIcon('actions-view-list-expand', Icon::SIZE_SMALL)->render('inline'); } else { $collapsed = false; $collapseIcon = $this->moduleTemplate->getIconFactory()->getIcon('actions-view-list-collapse', Icon::SIZE_SMALL)->render('inline'); } // Active menu item $panelState = (string) $this->MOD_SETTINGS['function'] == $item['uid'] ? 'panel-active' : 'panel-default'; $content .= '<li id="el_' . $id . '"> <div id="' . $contentId . '" data-taskcenter-id="' . $id . '" class="panel ' . $panelState . '"> <div class="panel-heading"> <div class="panel-heading-right"> <a href="#task_content_' . $contentId . '" class="panel-header-collapse t3js-taskcenter-header-collapse" role="button" data-toggle="collapse" data-uid="' . $contentId . '" aria-expanded="' . ($collapsed ? 'false' : 'true') . '"> ' . $collapseIcon . ' </a> </div> <div class="panel-heading-left"> <a href="' . $item['link'] . '" class="panel-title"> ' . ($icon ? '<span class="panel-title-icon">' . $icon . '</span>' : '') . ' <span class="panel-title-name">' . $title . ' ' . $this->moduleTemplate->getIconFactory()->getIcon('actions-view-table-expand', Icon::SIZE_SMALL)->render('inline') . '</span> </a> </div> </div> <div id="task_content_' . $contentId . '" class="panel-collapse collapse t3js-taskcenter-collapse ' . ($collapsed ? '' : 'in') . '" aria-expanded="true"> <div class="panel-body"> ' . $description . ' </div> </div> </div> </li>'; $count++; } $navigationId = $mainMenu ? 'id="task-list"' : ''; $content = '<ul ' . $navigationId . ' class="list-unstyled">' . $content . '</ul>'; } return $content; }
/** * Load the necessary css * * This will only be done when the referenced record is available * * @return void */ protected function loadCss() { $cssFiles = array('Wizard/Form.css', 'Wizard/Wizard.css'); $baseUrl = ExtensionManagementUtility::extPath('form') . 'Resources/Public/CSS/'; // Load the wizards css foreach ($cssFiles as $cssFile) { $this->getPageRenderer()->addCssFile(PathUtility::getAbsoluteWebPath($baseUrl . $cssFile)); } }
/** * Creates a color image selector * * @return string */ public function colorImage() { // Handling color-picker image if any: if (!$this->imageError) { if ($this->pickerImage) { if (GeneralUtility::_POST('coords_x')) { /** @var $image \TYPO3\CMS\Core\Imaging\GraphicalFunctions */ $image = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\GraphicalFunctions::class); $this->colorValue = '#' . $this->getIndex($image->imageCreateFromFile($this->pickerImage), GeneralUtility::_POST('coords_x'), GeneralUtility::_POST('coords_y')); } $pickerFormImage = ' <p class="c-head">' . $this->getLanguageService()->getLL('colorpicker_fromImage', true) . '</p> <input type="image" src="' . PathUtility::getAbsoluteWebPath($this->pickerImage) . '" name="coords" style="cursor:crosshair;" /><br />'; } else { $pickerFormImage = ''; } } else { $pickerFormImage = ' <p class="c-head">' . htmlspecialchars($this->imageError) . '</p>'; } return $pickerFormImage; }
/** * Check and update reference index! * * @return void */ public function func_refindex() { $readmeLocation = ExtensionManagementUtility::extPath('lowlevel', 'README.rst'); $this->view->assign('ReadmeLink', PathUtility::getAbsoluteWebPath($readmeLocation)); $this->view->assign('ReadmeLocation', $readmeLocation); $this->view->assign('binaryPath', ExtensionManagementUtility::extPath('core', 'bin/typo3')); if (GeneralUtility::_GP('_update') || GeneralUtility::_GP('_check')) { $testOnly = (bool) GeneralUtility::_GP('_check'); // Call the functionality $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class); list(, $bodyContent) = $refIndexObj->updateIndex($testOnly); $this->view->assign('content', str_replace('##LF##', '<br />', $bodyContent)); } }
/** * Creates a link to a script (eg. EditDocumentController or NewRecordController) which either opens in the current frame OR in a pop-up window. * * @param string $string The string to wrap in a link, typ. and image used as button in the edit panel. * @param string $url The URL of the link. Should be absolute if supposed to work with <base> path set. * @param string $additionalClasses Additional CSS classes * @return string A <a> tag wrapped string. * @see editPanelLinkWrap() */ protected function editPanelLinkWrap_doWrap($string, $url, $additionalClasses = '') { $width = MathUtility::forceIntegerInRange($this->backendUser->getTSConfigVal('options.feedit.popupWidth'), 690, 5000, 690); $height = MathUtility::forceIntegerInRange($this->backendUser->getTSConfigVal('options.feedit.popupHeight'), 500, 5000, 500); $onclick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url . '&returnUrl=' . PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::siteRelPath('backend') . 'Resources/Private/Templates/Close.html')) . ',\'FEquickEditWindow\',\'width=' . $width . ',height=' . $height . ',status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;'; return '<a href="#" class="btn btn-default btn-sm ' . htmlspecialchars($additionalClasses) . '" onclick="' . htmlspecialchars($onclick) . '" class="frontEndEditIconLinks">' . $string . '</a>'; }
/** * Main function generating the BE scaffolding * * @return void */ public function render() { $this->executeHook('renderPreProcess'); // Prepare the scaffolding, at this point extension may still add javascript and css $view = $this->getFluidTemplateObject($this->templatePath . 'Backend/Main.html'); // Extension Configuration to find the TYPO3 logo in the left corner $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['backend']); $logoPath = ''; if (!empty($extConf['backendLogo'])) { $customBackendLogo = GeneralUtility::getFileAbsFileName($extConf['backendLogo']); if (!empty($customBackendLogo)) { $logoPath = $customBackendLogo; } } // if no custom logo was set or the path is invalid, use the original one if (empty($logoPath)) { $logoPath = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/Images/typo3-topbar@2x.png'); } list($logoWidth, $logoHeight) = @getimagesize($logoPath); // High-resolution? if (strpos($logoPath, '@2x.') !== false) { $logoWidth = $logoWidth / 2; $logoHeight = $logoHeight / 2; } $view->assign('logoUrl', PathUtility::getAbsoluteWebPath($logoPath)); $view->assign('logoWidth', $logoWidth); $view->assign('logoHeight', $logoHeight); $view->assign('logoLink', TYPO3_URL_GENERAL); $view->assign('applicationVersion', TYPO3_version); $view->assign('siteName', $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']); $view->assign('moduleMenu', $this->generateModuleMenu()); $view->assign('toolbar', $this->renderToolbar()); /****************************************************** * Now put the complete backend document together ******************************************************/ foreach ($this->cssFiles as $cssFileName => $cssFile) { $this->pageRenderer->addCssFile($cssFile); // Load additional css files to overwrite existing core styles if (!empty($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName])) { $this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName]); } } if (!empty($this->css)) { $this->pageRenderer->addCssInlineBlock('BackendInlineCSS', $this->css); } foreach ($this->jsFiles as $jsFile) { $this->pageRenderer->addJsFile($jsFile); } $this->generateJavascript(); $this->pageRenderer->addJsInlineCode('BackendInlineJavascript', $this->js, false); $this->loadResourcesForRegisteredNavigationComponents(); // Add state provider $this->getDocumentTemplate()->setExtDirectStateProvider(); $states = $this->getBackendUser()->uc['BackendComponents']['States']; // Save states in BE_USER->uc $extOnReadyCode = ' Ext.state.Manager.setProvider(new TYPO3.state.ExtDirectProvider({ key: "BackendComponents.States", autoRead: false })); '; if ($states) { $extOnReadyCode .= 'Ext.state.Manager.getProvider().initState(' . json_encode($states) . ');'; } $extOnReadyCode .= ' TYPO3.Backend = new TYPO3.Viewport(TYPO3.Viewport.configuration)'; $this->pageRenderer->addExtOnReadyCode($extOnReadyCode); // Set document title: $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version; // Renders the module page $this->content = $this->getDocumentTemplate()->render($title, $view->render()); $hookConfiguration = array('content' => &$this->content); $this->executeHook('renderPostProcess', $hookConfiguration); }
/** * Writes contents in a file in typo3temp and returns the file name * * @param string $label: A label to insert at the beginning of the name of the file * @param string $fileExtension: The file extension of the file, defaulting to 'js' * @param string $contents: The contents to write into the file * @return string The name of the file written to typo3temp * @throws \RuntimeException If writing to file failed */ protected function writeTemporaryFile($label, $fileExtension = 'js', $contents = '') { $relativeFilename = 'typo3temp/assets/js/rte_' . str_replace('-', '_', $label) . '_' . GeneralUtility::shortMD5($contents, 20) . '.' . $fileExtension; $destination = PATH_site . $relativeFilename; if (!file_exists($destination)) { $minifiedJavaScript = ''; if ($fileExtension === 'js' && $contents !== '') { $minifiedJavaScript = GeneralUtility::minifyJavaScript($contents); } $failure = GeneralUtility::writeFileToTypo3tempDir($destination, $minifiedJavaScript ? $minifiedJavaScript : $contents); if ($failure) { throw new \RuntimeException($failure, 1294585668); } } return PathUtility::getAbsoluteWebPath($destination); }
/** * This function acts as a wrapper to allow relative and paths starting with EXT: to be dealt with * in this very case to always return the absolute web path to be included directly before output. * * This is mainly added so the EXT: syntax can be resolved for PageRenderer in one central place, * and hopefully removed in the future by one standard API call. * * @param string $file the filename to process * @param bool $prepareForOutput whether the file should be prepared as version numbered file and prefixed as absolute webpath * @return string * @internal */ protected function getStreamlinedFileName($file, $prepareForOutput = true) { if (strpos($file, 'EXT:') === 0) { $file = GeneralUtility::getFileAbsFileName($file); // as the path is now absolute, make it "relative" to the current script to stay compatible $file = PathUtility::getRelativePathTo($file); $file = rtrim($file, '/'); } else { $file = GeneralUtility::resolveBackPath($file); } if ($prepareForOutput) { $file = GeneralUtility::createVersionNumberedFilename($file); $file = PathUtility::getAbsoluteWebPath($file); } return $file; }
/** * Render a list of items as a nicely formated definition list including a * link, icon, title and description. * The keys of a single item are: * - title: Title of the item * - link: Link to the task * - icon: Path to the icon or Icon as HTML if it begins with <img * - description: Description of the task, using htmlspecialchars() * - descriptionHtml: Description allowing HTML tags which will override the * description * * @param array $items List of items to be displayed in the definition list. * @param bool $mainMenu Set it to TRUE to render the main menu * @return string Fefinition list */ public function renderListMenu($items, $mainMenu = false) { $content = $section = ''; $count = 0; // Change the sorting of items to the user's one if ($mainMenu) { $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Taskcenter/Taskcenter'); $userSorting = unserialize($this->getBackendUser()->uc['taskcenter']['sorting']); if (is_array($userSorting)) { $newSorting = array(); foreach ($userSorting as $item) { if (isset($items[$item])) { $newSorting[] = $items[$item]; unset($items[$item]); } } $items = $newSorting + $items; } } if (is_array($items) && !empty($items)) { foreach ($items as $item) { $title = htmlspecialchars($item['title']); $icon = $additionalClass = $collapsedStyle = ''; // Check for custom icon if (!empty($item['icon'])) { if (strpos($item['icon'], '<img ') === false) { $absIconPath = GeneralUtility::getFileAbsFileName($item['icon']); // If the file indeed exists, assemble relative path to it if (file_exists($absIconPath)) { $icon = '../' . str_replace(PATH_site, '', $absIconPath); $icon = '<img src="' . $icon . '" title="' . $title . '" alt="' . $title . '" />'; } if (@is_file($icon)) { $icon = '<img src="' . PathUtility::getAbsoluteWebPath($icon) . '" width="16" height="16" title="' . $title . '" alt="' . $title . '" />'; } } else { $icon = $item['icon']; } } $description = $item['descriptionHtml'] ?: '<p>' . nl2br(htmlspecialchars($item['description'])) . '</p>'; $id = $this->getUniqueKey($item['uid']); // Collapsed & expanded menu items if ($mainMenu && isset($this->getBackendUser()->uc['taskcenter']['states'][$id]) && $this->getBackendUser()->uc['taskcenter']['states'][$id]) { $collapsedStyle = 'style="display:none"'; $additionalClass = 'collapsed'; } else { $additionalClass = 'expanded'; } // First & last menu item if ($count == 0) { $additionalClass .= ' first-item'; } elseif ($count + 1 === count($items)) { $additionalClass .= ' last-item'; } // Active menu item $active = (string) $this->MOD_SETTINGS['function'] == $item['uid'] ? ' active-task' : ''; // Main menu: Render additional syntax to sort tasks if ($mainMenu) { $section = '<div class="down"><i class="fa fa-caret-down fa-fw"></i></div> <div class="drag"><i class="fa fa-arrows"></i></div>'; $backgroundClass = 't3-row-header '; } else { $backgroundClass = ''; } $content .= '<li class="' . $additionalClass . $active . '" id="el_' . $id . '"> ' . $section . ' <div class="image">' . $icon . '</div> <div class="' . $backgroundClass . 'link"><a href="' . $item['link'] . '">' . $title . '</a></div> <div class="content " ' . $collapsedStyle . '>' . $description . '</div> </li>'; $count++; } $navigationId = $mainMenu ? 'id="task-list"' : ''; $content = '<ul ' . $navigationId . ' class="task-list">' . $content . '</ul>'; } return $content; }