17 use Psr\Http\Message\ResponseInterface;
50 'render' =>
'Using BackendController::render() is deprecated and will not be possible anymore in TYPO3 v10.0.',
91 protected $templatePath =
'EXT:backend/Resources/Private/Templates/';
96 protected $partialPath =
'EXT:backend/Resources/Private/Partials/';
125 $this->backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
126 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
127 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
129 $this->
debug = (int)
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'debug'] === 1;
131 $this->moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
132 $this->moduleLoader->load(
$GLOBALS[
'TBE_MODULES']);
133 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
136 'md5' =>
'EXT:backend/Resources/Public/JavaScript/md5.js',
137 'evalfield' =>
'EXT:backend/Resources/Public/JavaScript/jsfunc.evalfield.js',
138 'backend' =>
'EXT:backend/Resources/Public/JavaScript/backend.js',
140 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/LoginRefresh',
'function(LoginRefresh) {
142 LoginRefresh.setLoginFramesetUrl(' . GeneralUtility::quoteJSvalue((
string)$uriBuilder->buildUriFromRoute(
'login_frameset')) .
');
143 LoginRefresh.setLogoutUrl(' . GeneralUtility::quoteJSvalue((
string)$uriBuilder->buildUriFromRoute(
'logout')) .
');
144 LoginRefresh.initialize();
148 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/ModuleMenu');
151 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Toolbar');
154 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Utility');
157 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Notification');
160 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Modal');
163 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/InfoWindow');
166 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/ContextMenu');
169 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Storage');
170 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Storage/Persistent',
'function(PersistentStorage) {
171 PersistentStorage.load(' . json_encode($this->
getBackendUser()->uc) .
');
175 $this->pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/DebugConsole');
177 $this->pageRenderer->addInlineLanguageLabelFile(
'EXT:core/Resources/Private/Language/locallang_core.xlf');
178 $this->pageRenderer->addInlineLanguageLabelFile(
'EXT:core/Resources/Private/Language/locallang_misc.xlf');
179 $this->pageRenderer->addInlineLanguageLabelFile(
'EXT:backend/Resources/Private/Language/locallang_layout.xlf');
180 $this->pageRenderer->addInlineLanguageLabelFile(
'EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
182 $this->pageRenderer->addInlineLanguageLabelFile(
'EXT:core/Resources/Private/Language/debugger.xlf');
183 $this->pageRenderer->addInlineLanguageLabelFile(
'EXT:core/Resources/Private/Language/wizard.xlf');
185 $this->pageRenderer->addInlineSetting(
'ShowItem',
'moduleUrl', (
string)$uriBuilder->buildUriFromRoute(
'show_item'));
186 $this->pageRenderer->addInlineSetting(
'RecordHistory',
'moduleUrl', (
string)$uriBuilder->buildUriFromRoute(
'record_history'));
187 $this->pageRenderer->addInlineSetting(
'NewRecord',
'moduleUrl', (
string)$uriBuilder->buildUriFromRoute(
'db_new'));
188 $this->pageRenderer->addInlineSetting(
'FormEngine',
'moduleUrl', (
string)$uriBuilder->buildUriFromRoute(
'record_edit'));
189 $this->pageRenderer->addInlineSetting(
'RecordCommit',
'moduleUrl', (
string)$uriBuilder->buildUriFromRoute(
'tce_db'));
190 $this->pageRenderer->addInlineSetting(
'WebLayout',
'moduleUrl', (
string)$uriBuilder->buildUriFromRoute(
'web_layout'));
205 $toolbarItemInstances = [];
206 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'toolbarItems'] ?? [] as $className) {
207 $toolbarItemInstance = GeneralUtility::makeInstance($className);
209 throw new \RuntimeException(
210 'class ' . $className .
' is registered as toolbar item but does not implement'
211 . ToolbarItemInterface::class,
215 $index = (int)$toolbarItemInstance->getIndex();
216 if ($index < 0 || $index > 100) {
217 throw new \RuntimeException(
218 'getIndex() must return an integer between 0 and 100',
223 while (array_key_exists($index, $toolbarItemInstances)) {
226 $toolbarItemInstances[$index] = $toolbarItemInstance;
228 ksort($toolbarItemInstances);
229 $this->toolbarItems = $toolbarItemInstances;
241 return new HtmlResponse($this->content);
261 foreach ($this->cssFiles as $cssFileName => $cssFile) {
262 $this->pageRenderer->addCssFile($cssFile);
264 if (!empty(
$GLOBALS[
'TBE_STYLES'][
'stylesheets'][$cssFileName])) {
265 $this->pageRenderer->addCssFile(
$GLOBALS[
'TBE_STYLES'][
'stylesheets'][$cssFileName]);
268 if (!empty($this->css)) {
269 $this->pageRenderer->addCssInlineBlock(
'BackendInlineCSS', $this->css);
271 foreach ($this->jsFiles as $jsFile) {
272 $this->pageRenderer->addJsFile($jsFile);
275 $this->pageRenderer->addJsInlineCode(
'BackendInlineJavascript', $this->js,
false);
278 $title =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename'] ?
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename'] .
' [TYPO3 CMS ' . TYPO3_version .
']' :
'TYPO3 CMS ' . TYPO3_version;
282 $this->
executeHook(
'renderPostProcess', $hookConfiguration);
295 $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(
'backend');
298 $customBackendLogo = GeneralUtility::getFileAbsFileName(ltrim(
$extConf[
'backendLogo'],
'/'));
299 if (!empty($customBackendLogo)) {
300 $logoPath = $customBackendLogo;
304 if (empty($logoPath) || !file_exists($logoPath)) {
305 $logoPath = GeneralUtility::getFileAbsFileName(
'EXT:backend/Resources/Public/Images/typo3_logo_orange.svg');
310 $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $logoPath);
311 $logoWidth = $imageInfo->getWidth() ??
'22';
312 $logoHeight = $imageInfo->getHeight() ??
'22';
315 if (strpos($logoPath,
'@2x.') !==
false) {
322 $view->assign(
'logoWidth', $logoWidth);
323 $view->assign(
'logoHeight', $logoHeight);
324 $view->assign(
'applicationVersion', TYPO3_version);
325 $view->assign(
'siteName',
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename']);
328 return $view->render();
339 foreach ($this->toolbarItems as $toolbarItem) {
341 if ($toolbarItem->checkAccess()) {
342 $hasDropDown = (bool)$toolbarItem->hasDropDown();
343 $additionalAttributes = (array)$toolbarItem->getAdditionalAttributes();
349 $classes[] =
'toolbar-item';
350 $classes[] =
't3js-toolbar-item';
351 if (isset($additionalAttributes[
'class'])) {
352 $classes[] = $additionalAttributes[
'class'];
353 unset($additionalAttributes[
'class']);
355 $liAttributes[
'class'] = implode(
' ', $classes);
358 foreach ($additionalAttributes as $name => $value) {
359 $liAttributes[$name] = $value;
363 $fullyQualifiedClassName = \get_class($toolbarItem);
364 $className = GeneralUtility::underscoredToLowerCamelCase($fullyQualifiedClassName);
365 $className = GeneralUtility::camelCaseToLowerCaseUnderscored($className);
366 $className = str_replace([
'_',
'\\'],
'-', $className);
367 $liAttributes[
'id'] = $className;
370 $shortName = substr($fullyQualifiedClassName, strrpos($fullyQualifiedClassName,
'\\') + 1);
371 $dataToolbarIdentifier = GeneralUtility::camelCaseToLowerCaseUnderscored($shortName);
372 $dataToolbarIdentifier = str_replace(
'_',
'-', $dataToolbarIdentifier);
373 $liAttributes[
'data-toolbar-identifier'] = $dataToolbarIdentifier;
375 $toolbar[] =
'<li ' . GeneralUtility::implodeAttributes($liAttributes,
true) .
'>';
378 $toolbar[] =
'<a href="#" class="toolbar-item-link dropdown-toggle" data-toggle="dropdown">';
379 $toolbar[] = $toolbarItem->getItem();
381 $toolbar[] =
'<div class="dropdown-menu" role="menu">';
382 $toolbar[] = $toolbarItem->getDropDown();
383 $toolbar[] =
'</div>';
385 $toolbar[] = $toolbarItem->getItem();
387 $toolbar[] =
'</li>';
390 return implode(LF, $toolbar);
400 $dateFormat = (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'USdateFormat'] ? [
'MM-DD-YYYY',
'HH:mm MM-DD-YYYY'] : [
'DD-MM-YYYY',
'HH:mm DD-MM-YYYY']);
401 $this->pageRenderer->addInlineSetting(
'DateTimePicker',
'DateFormat', $dateFormat);
404 $newPageModule = trim($beUser->getTSConfig()[
'options.'][
'overridePageModule'] ??
'');
407 if (!$beUser->check(
'modules', $pageModule)) {
410 $pageModuleUrl = (string)GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute($pageModule);
413 'username' => htmlspecialchars($beUser->user[
'username']),
414 'pageModule' => $pageModule,
415 'pageModuleUrl' => $pageModuleUrl,
416 'inWorkspace' => $beUser->workspace !== 0,
417 'showRefreshLoginPopup' => (bool)(
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'showRefreshLoginPopup'] ??
false)
420 TYPO3.configuration = ' . json_encode($t3Configuration) .
';
430 recentIds: [], // used by frameset modules to track the most recent used id for list frame.
431 navFrameHighlightedID: [], // used by navigation frames to track which row id was highlighted last time
435 top.goToModule = function(modName, cMR_flag, addGetVars) {
436 TYPO3.ModuleMenu.App.showModule(modName, addGetVars);
451 $editId = preg_replace(
'/[^[:alnum:]_]/',
'', GeneralUtility::_GET(
'edit'));
458 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages');
459 $queryBuilder->getRestrictions()
461 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
462 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
464 $editRecord = $queryBuilder->select(
'*')
467 $queryBuilder->expr()->eq(
469 $queryBuilder->createNamedParameter($editId, \PDO::PARAM_STR)
471 $queryBuilder->expr()->orX(
480 if ($editRecord !==
false) {
485 if (is_array($editRecord) && $beUser->isInWebMount($editRecord)) {
488 // Load page to edit:
489 window.setTimeout("top.loadEditId(' . (int)$editRecord[
'uid'] .
');", 500);
492 if (!($userTsConfig[
'options.'][
'bookmark_onEditId_dontSetPageTree'] ??
false)) {
493 $bookmarkKeepExpanded = (bool)($userTsConfig[
'options.'][
'bookmark_onEditId_keepExistingExpanded'] ??
false);
499 // Warning about page editing:
500 require(["TYPO3/CMS/Backend/Modal", "TYPO3/CMS/Backend/Severity"], function(Modal, Severity) {
501 Modal.show("", ' . GeneralUtility::quoteJSvalue(sprintf($this->
getLanguageService()->getLL(
'noEditPage'), $editId)) .
', Severity.notice, [{
502 text: ' . GeneralUtility::quoteJSvalue($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:close')) .
',
504 btnClass: "btn-info",
506 trigger: function () {
507 Modal.currentModal.trigger("modal-dismiss");
522 $startModule = preg_replace(
'/[^[:alnum:]_]/',
'', GeneralUtility::_GET(
'module'));
523 $startModuleParameters =
'';
527 if (isset($beUser->uc[
'startModuleOnFirstLogin'])) {
528 $startModule = $beUser->uc[
'startModuleOnFirstLogin'];
529 unset($beUser->uc[
'startModuleOnFirstLogin']);
531 } elseif ($beUser->uc[
'startModule']) {
532 $startModule = $beUser->uc[
'startModule'];
537 if (strpos($startModule,
'->') !==
false) {
538 list($startModule, $startModuleParameters) = explode(
'->', $startModule, 2);
542 $moduleParameters = GeneralUtility::_GET(
'modParams');
544 if (!$moduleParameters && $startModuleParameters) {
545 $moduleParameters = $startModuleParameters;
551 top.startInModule = [' . GeneralUtility::quoteJSvalue($startModule) .
', ' . GeneralUtility::quoteJSvalue($moduleParameters) .
'];
565 if (!is_string(
$css)) {
566 throw new \InvalidArgumentException(
'parameter $css must be of type string', 1195129642);
582 protected function executeHook($identifier, array $hookConfiguration = [])
584 $options = &
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/backend.php'];
585 foreach ($options[$identifier] ?? [] as $hookFunction) {
586 GeneralUtility::callUserFunction($hookFunction, $hookConfiguration, $this);
599 $moduleStorage = $this->backendModuleRepository->loadAllowedModules([
'user',
'help']);
602 $view->assign(
'modules', $moduleStorage);
603 return $view->render();
609 $collapseState = $uc[
'BackendComponents'][
'States'][
'typo3-module-menu'][
'collapsed'] ??
false;
611 return $collapseState ===
true || $collapseState ===
'true';
629 public function getTopbar(): ResponseInterface
631 return new JsonResponse([
'topbar' => $this->
renderTopbar()]);
642 $view = GeneralUtility::makeInstance(StandaloneView::class);
643 $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName(
'EXT:backend/Resources/Private/Partials')]);
644 if ($templatePathAndFileName) {
645 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFileName));