TYPO3 CMS  TYPO3_7-6
BackendController.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
30 
35 {
39  protected $content = '';
40 
44  protected $css = '';
45 
49  protected $cssFiles = [];
50 
54  protected $js = '';
55 
59  protected $jsFiles = [];
60 
64  protected $toolbarItems = [];
65 
69  protected $menuWidth = 190;
70 
74  protected $debug;
75 
79  protected $templatePath = 'EXT:backend/Resources/Private/Templates/';
80 
85 
89  protected $moduleLoader;
90 
94  protected $pageRenderer;
95 
100  public function getPageRenderer()
101  {
103  return $this->pageRenderer;
104  }
105 
109  public function __construct()
110  {
111  $this->getLanguageService()->includeLLFile('EXT:lang/locallang_misc.xlf');
112  $this->backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
113 
114  // Set debug flag for BE development only
115  $this->debug = (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] === 1;
116  // Initializes the backend modules structure for use later.
117  $this->moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
118  $this->moduleLoader->load($GLOBALS['TBE_MODULES']);
119  $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
120  $this->pageRenderer->loadExtJS();
121  // included for the module menu JavaScript, please note that this is subject to change
122  $this->pageRenderer->loadJquery();
123  $this->pageRenderer->addJsInlineCode('consoleOverrideWithDebugPanel', '//already done', false);
124  $this->pageRenderer->addExtDirectCode();
125  // Add default BE javascript
126  $backendRelPath = ExtensionManagementUtility::extRelPath('backend');
127  $this->jsFiles = [
128  'locallang' => $this->getLocalLangFileName(),
129  'md5' => $backendRelPath . 'Resources/Public/JavaScript/md5.js',
130  'modulemenu' => $backendRelPath . 'Resources/Public/JavaScript/modulemenu.js',
131  'evalfield' => $backendRelPath . 'Resources/Public/JavaScript/jsfunc.evalfield.js',
132  'notifications' => $backendRelPath . 'Resources/Public/JavaScript/notifications.js',
133  'backend' => $backendRelPath . 'Resources/Public/JavaScript/backend.js',
134  'viewport' => $backendRelPath . 'Resources/Public/JavaScript/extjs/viewport.js',
135  'iframepanel' => $backendRelPath . 'Resources/Public/JavaScript/iframepanel.js',
136  'backendcontentiframe' => $backendRelPath . 'Resources/Public/JavaScript/extjs/backendcontentiframe.js',
137  'viewportConfiguration' => $backendRelPath . 'Resources/Public/JavaScript/extjs/viewportConfiguration.js',
138  ];
139  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LoginRefresh', 'function(LoginRefresh) {
140  LoginRefresh.setIntervalTime(' . MathUtility::forceIntegerInRange((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['sessionTimeout'] - 60, 60) . ');
141  LoginRefresh.setLoginFramesetUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('login_frameset')) . ');
142  LoginRefresh.setLogoutUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('logout')) . ');
143  LoginRefresh.initialize();
144  }');
145 
146  // load Utility class
147  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Utility');
148 
149  // load Notification functionality
150  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Notification');
151 
152  // load Modals
153  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
154 
155  // load Legacy CSS Support
156  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LegacyCssClasses');
157 
158  // load the storage API and fill the UC into the PersistentStorage, so no additional AJAX call is needed
159  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Storage', 'function(Storage) {
160  Storage.Persistent.load(' . json_encode($this->getBackendUser()->uc) . ');
161  }');
162 
163  // load debug console
164  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DebugConsole');
165 
166  // Load RSA encryption
167  $rsaEncryptionEncoder = GeneralUtility::makeInstance(RsaEncryptionEncoder::class);
168  $rsaEncryptionEncoder->enableRsaEncryption(true);
169 
170  $this->pageRenderer->addInlineSetting('ShowItem', 'moduleUrl', BackendUtility::getModuleUrl('show_item'));
171 
172  $this->css = '';
173 
174  $this->initializeToolbarItems();
175  if (isset($GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'])) {
176  $this->menuWidth = (int)$GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'];
177  }
178  $this->executeHook('constructPostProcess');
179  $this->includeLegacyBackendItems();
180  }
181 
186  protected function includeLegacyBackendItems()
187  {
188  $TYPO3backend = $this;
189  // Include extensions which may add css, javascript or toolbar items
190  if (is_array($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'])) {
191  foreach ($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'] as $additionalBackendItem) {
192  include_once $additionalBackendItem;
193  }
194  }
195 
196  // Process ExtJS module js and css
197  if (is_array($GLOBALS['TBE_MODULES']['_configuration'])) {
198  foreach ($GLOBALS['TBE_MODULES']['_configuration'] as $moduleConfig) {
199  if (is_array($moduleConfig['cssFiles'])) {
200  foreach ($moduleConfig['cssFiles'] as $cssFileName => $cssFile) {
203  $TYPO3backend->addCssFile($cssFileName, '../' . $files[0]);
204  }
205  }
206  if (is_array($moduleConfig['jsFiles'])) {
207  foreach ($moduleConfig['jsFiles'] as $jsFile) {
210  $TYPO3backend->addJavascriptFile('../' . $files[0]);
211  }
212  }
213  }
214  }
215  }
216 
223  protected function initializeToolbarItems()
224  {
225  $toolbarItemInstances = [];
226  $classNameRegistry = $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'];
227  foreach ($classNameRegistry as $className) {
228  $toolbarItemInstance = GeneralUtility::makeInstance($className);
229  if (!$toolbarItemInstance instanceof ToolbarItemInterface) {
230  throw new \RuntimeException(
231  'class ' . $className . ' is registered as toolbar item but does not implement'
232  . ToolbarItemInterface::class,
233  1415958218
234  );
235  }
236  $index = (int)$toolbarItemInstance->getIndex();
237  if ($index < 0 || $index > 100) {
238  throw new \RuntimeException(
239  'getIndex() must return an integer between 0 and 100',
240  1415968498
241  );
242  }
243  // Find next free position in array
244  while (array_key_exists($index, $toolbarItemInstances)) {
245  $index++;
246  }
247  $toolbarItemInstances[$index] = $toolbarItemInstance;
248  }
249  ksort($toolbarItemInstances);
250  $this->toolbarItems = $toolbarItemInstances;
251  }
252 
261  public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
262  {
263  $this->render();
264  $response->getBody()->write($this->content);
265  return $response;
266  }
267 
273  public function render()
274  {
275  $this->executeHook('renderPreProcess');
276 
277  // Prepare the scaffolding, at this point extension may still add javascript and css
278  $view = $this->getFluidTemplateObject($this->templatePath . 'Backend/Main.html');
279 
280  // Render the TYPO3 logo in the left corner
281  $logoUrl = $GLOBALS['TBE_STYLES']['logo'] ?: ExtensionManagementUtility::extRelPath('backend') . 'Resources/Public/Images/typo3-topbar@2x.png';
282  $logoPath = GeneralUtility::resolveBackPath(PATH_typo3 . $logoUrl);
283 
284  // set width/height for custom logo
285  $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $logoPath);
286  $logoWidth = $imageInfo->getWidth() ?: '22';
287  $logoHeight = $imageInfo->getHeight() ?: '22';
288 
289  // High-resolution?
290  if (strpos($logoUrl, '@2x.') !== false) {
291  $logoWidth = $logoWidth/2;
292  $logoHeight = $logoHeight/2;
293  }
294 
295  $view->assign('logoUrl', $logoUrl);
296  $view->assign('logoWidth', $logoWidth);
297  $view->assign('logoHeight', $logoHeight);
298  $view->assign('logoLink', TYPO3_URL_GENERAL);
299  $view->assign('applicationVersion', TYPO3_version);
300  $view->assign('siteName', $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']);
301  $view->assign('moduleMenu', $this->generateModuleMenu());
302  $view->assign('toolbar', $this->renderToolbar());
303 
304  /******************************************************
305  * Now put the complete backend document together
306  ******************************************************/
307  foreach ($this->cssFiles as $cssFileName => $cssFile) {
308  $this->pageRenderer->addCssFile($cssFile);
309  // Load additional css files to overwrite existing core styles
310  if (!empty($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName])) {
311  $this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName]);
312  }
313  }
314  if (!empty($this->css)) {
315  $this->pageRenderer->addCssInlineBlock('BackendInlineCSS', $this->css);
316  }
317  foreach ($this->jsFiles as $jsFile) {
318  $this->pageRenderer->addJsFile($jsFile);
319  }
320  $this->generateJavascript();
321  $this->pageRenderer->addJsInlineCode('BackendInlineJavascript', $this->js, false);
323 
324  // Add state provider
325  $this->getDocumentTemplate()->setExtDirectStateProvider();
326  $states = $this->getBackendUser()->uc['BackendComponents']['States'];
327  // Save states in BE_USER->uc
328  $extOnReadyCode = '
329  Ext.state.Manager.setProvider(new TYPO3.state.ExtDirectProvider({
330  key: "BackendComponents.States",
331  autoRead: false
332  }));
333  ';
334 
335  if ($states) {
336  $extOnReadyCode .= 'Ext.state.Manager.getProvider().initState(' . json_encode($states) . ');';
337  }
338 
339  $extOnReadyCode .= '
340  TYPO3.Backend = new TYPO3.Viewport(TYPO3.Viewport.configuration)';
341  $this->pageRenderer->addExtOnReadyCode($extOnReadyCode);
342  // Set document title:
343  $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version;
344  // Renders the module page
345  $this->content = $this->getDocumentTemplate()->render($title, $view->render());
346  $hookConfiguration = ['content' => &$this->content];
347  $this->executeHook('renderPostProcess', $hookConfiguration);
348  }
349 
356  {
357  if (!is_array($GLOBALS['TBE_MODULES']['_navigationComponents'])) {
358  return;
359  }
360  $loadedComponents = [];
361  foreach ($GLOBALS['TBE_MODULES']['_navigationComponents'] as $module => $info) {
362  if (in_array($info['componentId'], $loadedComponents)) {
363  continue;
364  }
365  $loadedComponents[] = $info['componentId'];
366  $component = strtolower(substr($info['componentId'], strrpos($info['componentId'], '-') + 1));
367  $componentDirectory = 'components/' . $component . '/';
368  if ($info['isCoreComponent']) {
369  $componentDirectory = 'Resources/Public/JavaScript/extjs/' . $componentDirectory;
370  $info['extKey'] = 'backend';
371  }
372  $absoluteComponentPath = ExtensionManagementUtility::extPath($info['extKey']) . $componentDirectory;
373  $relativeComponentPath = ExtensionManagementUtility::extRelPath($info['extKey']) . $componentDirectory;
374  $cssFiles = GeneralUtility::getFilesInDir($absoluteComponentPath . 'css/', 'css');
375  if (file_exists($absoluteComponentPath . 'css/loadorder.txt')) {
376  // Don't allow inclusion outside directory
377  $loadOrder = str_replace('../', '', GeneralUtility::getUrl($absoluteComponentPath . 'css/loadorder.txt'));
378  $cssFilesOrdered = GeneralUtility::trimExplode(LF, $loadOrder, true);
379  $cssFiles = array_merge($cssFilesOrdered, $cssFiles);
380  }
381  foreach ($cssFiles as $cssFile) {
382  $this->pageRenderer->addCssFile($relativeComponentPath . 'css/' . $cssFile);
383  }
384  $jsFiles = GeneralUtility::getFilesInDir($absoluteComponentPath . 'javascript/', 'js');
385  if (file_exists($absoluteComponentPath . 'javascript/loadorder.txt')) {
386  // Don't allow inclusion outside directory
387  $loadOrder = str_replace('../', '', GeneralUtility::getUrl($absoluteComponentPath . 'javascript/loadorder.txt'));
388  $jsFilesOrdered = GeneralUtility::trimExplode(LF, $loadOrder, true);
389  $jsFiles = array_merge($jsFilesOrdered, $jsFiles);
390  }
391  foreach ($jsFiles as $jsFile) {
392  $this->pageRenderer->addJsFile($relativeComponentPath . 'javascript/' . $jsFile);
393  }
394  $this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', BackendUtility::getModuleUrl('record_history'));
395  $this->pageRenderer->addInlineSetting('NewRecord', 'moduleUrl', BackendUtility::getModuleUrl('db_new'));
396  $this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', BackendUtility::getModuleUrl('record_edit'));
397  }
398  }
399 
405  protected function renderToolbar()
406  {
407  $toolbar = [];
408  foreach ($this->toolbarItems as $toolbarItem) {
410  if ($toolbarItem->checkAccess()) {
411  $hasDropDown = (bool)$toolbarItem->hasDropDown();
412  $additionalAttributes = (array)$toolbarItem->getAdditionalAttributes();
413 
414  $liAttributes = [];
415 
416  // Merge class: Add dropdown class if hasDropDown, add classes from additonal attributes
417  $classes = [];
418  if ($hasDropDown) {
419  $classes[] = 'dropdown';
420  }
421  if (isset($additionalAttributes['class'])) {
422  $classes[] = $additionalAttributes['class'];
423  unset($additionalAttributes['class']);
424  }
425  $liAttributes[] = 'class="' . implode(' ', $classes) . '"';
426 
427  // Add further attributes
428  foreach ($additionalAttributes as $name => $value) {
429  $liAttributes[] = $name . '="' . $value . '"';
430  }
431 
432  // Create a unique id from class name
433  $className = get_class($toolbarItem);
434  $className = GeneralUtility::underscoredToLowerCamelCase($className);
435  $className = GeneralUtility::camelCaseToLowerCaseUnderscored($className);
436  $className = str_replace(['_', '\\'], '-', $className);
437  $liAttributes[] = 'id="' . $className . '"';
438 
439  $toolbar[] = '<li ' . implode(' ', $liAttributes) . '>';
440 
441  if ($hasDropDown) {
442  $toolbar[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">';
443  $toolbar[] = $toolbarItem->getItem();
444  $toolbar[] = '</a>';
445  $toolbar[] = '<div class="dropdown-menu" role="menu">';
446  $toolbar[] = $toolbarItem->getDropDown();
447  $toolbar[] = '</div>';
448  } else {
449  $toolbar[] = $toolbarItem->getItem();
450  }
451  $toolbar[] = '</li>';
452  }
453  }
454  return implode(LF, $toolbar);
455  }
456 
464  protected function getLocalLangFileName()
465  {
466  $code = $this->generateLocalLang();
467  $filePath = 'typo3temp/Language/Backend-' . sha1($code) . '.js';
468  if (!file_exists(PATH_site . $filePath)) {
469  // writeFileToTypo3tempDir() returns NULL on success (please double-read!)
470  $error = GeneralUtility::writeFileToTypo3tempDir(PATH_site . $filePath, $code);
471  if ($error !== null) {
472  throw new \RuntimeException('Locallang JS file could not be written to ' . $filePath . '. Reason: ' . $error, 1295193026);
473  }
474  }
475  return '../' . $filePath;
476  }
477 
484  protected function generateLocalLang()
485  {
486  $lang = $this->getLanguageService();
487  $coreLabels = [
488  'waitTitle' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_logging_in'),
489  'refresh_login_failed' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_failed'),
490  'refresh_login_failed_message' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_failed_message'),
491  'refresh_login_title' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_title'),
492  'login_expired' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_expired'),
493  'refresh_login_username' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_username'),
494  'refresh_login_password' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_password'),
495  'refresh_login_emptyPassword' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_emptyPassword'),
496  'refresh_login_button' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_button'),
497  'refresh_logout_button' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_logout_button'),
498  'refresh_exit_button' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_exit_button'),
499  'please_wait' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.please_wait'),
500  'loadingIndicator' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:loadingIndicator'),
501  'be_locked' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.be_locked'),
502  'refresh_login_countdown_singular' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_countdown_singular'),
503  'refresh_login_countdown' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_countdown'),
504  'login_about_to_expire' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_about_to_expire'),
505  'login_about_to_expire_title' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_about_to_expire_title'),
506  'refresh_login_logout_button' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_logout_button'),
507  'refresh_login_refresh_button' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_refresh_button'),
508  'tabs_closeAll' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:tabs.closeAll'),
509  'tabs_closeOther' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:tabs.closeOther'),
510  'tabs_close' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:tabs.close'),
511  'tabs_openInBrowserWindow' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:tabs.openInBrowserWindow'),
512  'csh_tooltip_loading' => $lang->sL('LLL:EXT:lang/locallang_core.xlf:csh_tooltip_loading')
513  ];
514  $labels = [
515  'fileUpload' => [
516  'windowTitle',
517  'buttonSelectFiles',
518  'buttonCancelAll',
519  'infoComponentMaxFileSize',
520  'infoComponentFileUploadLimit',
521  'infoComponentFileTypeLimit',
522  'infoComponentOverrideFiles',
523  'processRunning',
524  'uploadWait',
525  'uploadStarting',
526  'uploadProgress',
527  'uploadSuccess',
528  'errorQueueLimitExceeded',
529  'errorQueueFileSizeLimit',
530  'errorQueueZeroByteFile',
531  'errorQueueInvalidFiletype',
532  'errorUploadHttp',
533  'errorUploadMissingUrl',
534  'errorUploadIO',
535  'errorUploadSecurityError',
536  'errorUploadLimit',
537  'errorUploadFailed',
538  'errorUploadFileIDNotFound',
539  'errorUploadFileValidation',
540  'errorUploadFileCancelled',
541  'errorUploadStopped',
542  'allErrorMessageTitle',
543  'allErrorMessageText',
544  'allError401',
545  'allError2038'
546  ],
547  'liveSearch' => [
548  'title',
549  'helpTitle',
550  'emptyText',
551  'loadingText',
552  'listEmptyText',
553  'showAllResults',
554  'helpDescription',
555  'helpDescriptionPages',
556  'helpDescriptionContent'
557  ],
558  'viewPort' => [
559  'tooltipModuleMenuSplit',
560  'tooltipNavigationContainerSplitDrag',
561  'tooltipNavigationContainerSplitClick',
562  'tooltipDebugPanelSplitDrag'
563  ]
564  ];
565  $generatedLabels = [];
566  $generatedLabels['core'] = $coreLabels;
567  // First loop over all categories (fileUpload, liveSearch, ..)
568  foreach ($labels as $categoryName => $categoryLabels) {
569  // Then loop over every single label
570  foreach ($categoryLabels as $label) {
571  // LLL identifier must be called $categoryName_$label, e.g. liveSearch_loadingText
572  $generatedLabels[$categoryName][$label] = $this->getLanguageService()->getLL($categoryName . '_' . $label);
573  }
574  }
575  return 'TYPO3.LLL = ' . json_encode($generatedLabels) . ';';
576  }
577 
583  protected function generateJavascript()
584  {
585  $beUser = $this->getBackendUser();
586  // Needed for FormEngine manipulation (date picker)
587  $dateFormat = ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? ['MM-DD-YYYY', 'HH:mm MM-DD-YYYY'] : ['DD-MM-YYYY', 'HH:mm DD-MM-YYYY']);
588  $this->pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat);
589  // define the window size of the element browser etc.
590  $popupWindowWidth = 700;
591  $popupWindowHeight = 750;
592  $popupWindowSize = trim($beUser->getTSConfigVal('options.popupWindowSize'));
593  if (!empty($popupWindowSize)) {
594  list($popupWindowWidth, $popupWindowHeight) = GeneralUtility::intExplode('x', $popupWindowSize);
595  }
596 
597  // define the window size of the popups within the RTE
598  $rtePopupWindowSize = trim($beUser->getTSConfigVal('options.rte.popupWindowSize'));
599  if (!empty($rtePopupWindowSize)) {
600  list($rtePopupWindowWidth, $rtePopupWindowHeight) = GeneralUtility::trimExplode('x', $rtePopupWindowSize);
601  }
602  $rtePopupWindowWidth = !empty($rtePopupWindowWidth) ? (int)$rtePopupWindowWidth : ($popupWindowWidth-200);
603  $rtePopupWindowHeight = !empty($rtePopupWindowHeight) ? (int)$rtePopupWindowHeight : ($popupWindowHeight-250);
604 
605  $pathTYPO3 = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/';
606  // If another page module was specified, replace the default Page module with the new one
607  $newPageModule = trim($beUser->getTSConfigVal('options.overridePageModule'));
608  $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
609  if (!$beUser->check('modules', $pageModule)) {
610  $pageModule = '';
611  }
612  $t3Configuration = [
613  'siteUrl' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL'),
614  'PATH_typo3' => $pathTYPO3,
615  'PATH_typo3_enc' => rawurlencode($pathTYPO3),
616  'username' => htmlspecialchars($beUser->user['username']),
617  'userUid' => htmlspecialchars($beUser->user['uid']),
618  'uniqueID' => GeneralUtility::shortMD5(uniqid('', true)),
619  'securityLevel' => trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal',
620  'TYPO3_mainDir' => TYPO3_mainDir,
621  'pageModule' => $pageModule,
622  'inWorkspace' => $beUser->workspace !== 0,
623  'workspaceFrontendPreviewEnabled' => $beUser->user['workspace_preview'] ? 1 : 0,
624  'veriCode' => $beUser->veriCode(),
625  'denyFileTypes' => PHP_EXTENSIONS_DEFAULT,
626  'moduleMenuWidth' => $this->menuWidth - 1,
627  'topBarHeight' => isset($GLOBALS['TBE_STYLES']['dims']['topFrameH']) ? (int)$GLOBALS['TBE_STYLES']['dims']['topFrameH'] : 45,
628  'showRefreshLoginPopup' => isset($GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup']) ? (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup'] : false,
629  'debugInWindow' => $beUser->uc['debugInWindow'] ? 1 : 0,
630  'ContextHelpWindows' => [
631  'width' => 600,
632  'height' => 400
633  ],
634  'PopupWindow' => [
635  'width' => $popupWindowWidth,
636  'height' => $popupWindowHeight
637  ],
638  'RTEPopupWindow' => [
639  'width' => $rtePopupWindowWidth,
640  'height' => $rtePopupWindowHeight
641  ]
642  ];
643  $this->js .= '
644  TYPO3.configuration = ' . json_encode($t3Configuration) . ';
645 
649  function typoSetup() { //
650  this.PATH_typo3 = TYPO3.configuration.PATH_typo3;
651  this.PATH_typo3_enc = TYPO3.configuration.PATH_typo3_enc;
652  this.username = TYPO3.configuration.username;
653  this.uniqueID = TYPO3.configuration.uniqueID;
654  this.securityLevel = TYPO3.configuration.securityLevel;
655  this.veriCode = TYPO3.configuration.veriCode;
656  this.denyFileTypes = TYPO3.configuration.denyFileTypes;
657  }
658  var TS = new typoSetup();
659  //backwards compatibility
668  function fsModules() { //
669  this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
670  this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
671  this.currentMainLoaded="";
672  this.currentBank="0";
673  }
674  var fsMod = new fsModules();
675 
676  top.goToModule = function(modName, cMR_flag, addGetVars) {
677  TYPO3.ModuleMenu.App.showModule(modName, addGetVars);
678  }
679  ' . $this->setStartupModule();
680  // Check editing of page:
681  $this->handlePageEditing();
682  }
683 
689  protected function handlePageEditing()
690  {
691  $beUser = $this->getBackendUser();
692  // EDIT page:
693  $editId = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('edit'));
694  $editRecord = '';
695  if ($editId) {
696  // Looking up the page to edit, checking permissions:
697  $where = ' AND (' . $beUser->getPagePermsClause(2) . ' OR ' . $beUser->getPagePermsClause(16) . ')';
699  $editRecord = BackendUtility::getRecordWSOL('pages', $editId, '*', $where);
700  } else {
701  $records = BackendUtility::getRecordsByField('pages', 'alias', $editId, $where);
702  if (is_array($records)) {
703  $editRecord = reset($records);
704  BackendUtility::workspaceOL('pages', $editRecord);
705  }
706  }
707  // If the page was accessible, then let the user edit it.
708  if (is_array($editRecord) && $beUser->isInWebMount($editRecord['uid'])) {
709  // Setting JS code to open editing:
710  $this->js .= '
711  // Load page to edit:
712  window.setTimeout("top.loadEditId(' . (int)$editRecord['uid'] . ');", 500);
713  ';
714  // Checking page edit parameter:
715  if (!$beUser->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) {
716  $bookmarkKeepExpanded = $beUser->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded');
717  // Expanding page tree:
718  BackendUtility::openPageTree((int)$editRecord['pid'], !$bookmarkKeepExpanded);
719  }
720  } else {
721  $this->js .= '
722  // Warning about page editing:
723  alert(' . GeneralUtility::quoteJSvalue(sprintf($this->getLanguageService()->getLL('noEditPage'), $editId)) . ');
724  ';
725  }
726  }
727  }
728 
734  protected function setStartupModule()
735  {
736  $startModule = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('module'));
737  $startModuleParameters = '';
738  if (!$startModule) {
739  $beUser = $this->getBackendUser();
740  // start module on first login, will be removed once used the first time
741  if (isset($beUser->uc['startModuleOnFirstLogin'])) {
742  $startModule = $beUser->uc['startModuleOnFirstLogin'];
743  unset($beUser->uc['startModuleOnFirstLogin']);
744  $beUser->writeUC();
745  } elseif ($beUser->uc['startModule']) {
746  $startModule = $beUser->uc['startModule'];
747  } elseif ($beUser->uc['startInTaskCenter']) {
748  $startModule = 'user_task';
749  }
750 
751  // check if the start module has additional parameters, so a redirect to a specific
752  // action is possible
753  if (strpos($startModule, '->') !== false) {
754  list($startModule, $startModuleParameters) = explode('->', $startModule, 2);
755  }
756  }
757 
758  $moduleParameters = GeneralUtility::_GET('modParams');
759  // if no GET parameters are set, check if there are parameters given from the UC
760  if (!$moduleParameters && $startModuleParameters) {
761  $moduleParameters = $startModuleParameters;
762  }
763 
764  if ($startModule) {
765  return '
766  // start in module:
767  top.startInModule = [' . GeneralUtility::quoteJSvalue($startModule) . ', ' . GeneralUtility::quoteJSvalue($moduleParameters) . '];
768  ';
769  } else {
770  return '';
771  }
772  }
773 
781  public function addJavascript($javascript)
782  {
783  // @todo do we need more checks?
784  if (!is_string($javascript)) {
785  throw new \InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
786  }
787  $this->js .= $javascript;
788  }
789 
796  public function addJavascriptFile($javascriptFile)
797  {
798  $jsFileAdded = false;
799  // @todo add more checks if necessary
800  if (file_exists(GeneralUtility::resolveBackPath(PATH_typo3 . $javascriptFile))) {
801  $this->jsFiles[] = $javascriptFile;
802  $jsFileAdded = true;
803  }
804  return $jsFileAdded;
805  }
806 
814  public function addCss($css)
815  {
816  if (!is_string($css)) {
817  throw new \InvalidArgumentException('parameter $css must be of type string', 1195129642);
818  }
819  $this->css .= $css;
820  }
821 
829  public function addCssFile($cssFileName, $cssFile)
830  {
831  $cssFileAdded = false;
832  if (empty($this->cssFiles[$cssFileName])) {
833  $this->cssFiles[$cssFileName] = $cssFile;
834  $cssFileAdded = true;
835  }
836  return $cssFileAdded;
837  }
838 
848  public function addToolbarItem($toolbarItemName, $toolbarItemClassName)
849  {
851  }
852 
865  protected function executeHook($identifier, array $hookConfiguration = [])
866  {
867  $options = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php'];
868  if (isset($options[$identifier]) && is_array($options[$identifier])) {
869  foreach ($options[$identifier] as $hookFunction) {
870  GeneralUtility::callUserFunction($hookFunction, $hookConfiguration, $this);
871  }
872  }
873  }
874 
881  protected function generateModuleMenu()
882  {
883  // get all modules except the user modules for the side menu
884  $moduleStorage = $this->backendModuleRepository->loadAllowedModules(['user', 'help']);
885 
886  $view = $this->getFluidTemplateObject($this->templatePath . 'ModuleMenu/Main.html');
887  $view->assign('modules', $moduleStorage);
888  return $view->render();
889  }
890 
898  public function getModuleMenu(ServerRequestInterface $request, ResponseInterface $response)
899  {
900  $content = $this->generateModuleMenu();
901 
902  $response->getBody()->write(json_encode(['menu' => $content]));
903  return $response;
904  }
905 
912  protected function getFluidTemplateObject($templatePathAndFileName = null)
913  {
914  $view = GeneralUtility::makeInstance(StandaloneView::class);
915  if ($templatePathAndFileName) {
916  $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFileName));
917  }
918  return $view;
919  }
920 
926  protected function getLanguageService()
927  {
928  return $GLOBALS['LANG'];
929  }
930 
936  protected function getBackendUser()
937  {
938  return $GLOBALS['BE_USER'];
939  }
940 
946  protected function getDocumentTemplate()
947  {
948  return $GLOBALS['TBE_TEMPLATE'];
949  }
950 }
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
mainAction(ServerRequestInterface $request, ResponseInterface $response)
static getFilesInDir($path, $extensionList='', $prependPath=false, $order='', $excludePattern='')
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel='E_DEBUG')
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
static getRecordsByField($theTable, $theField, $theValue, $whereClause='', $groupBy='', $orderBy='', $limit='', $useDeleteClause=true)
static openPageTree($pid, $clearExpansion)
static writeFileToTypo3tempDir($filepath, $content)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
addToolbarItem($toolbarItemName, $toolbarItemClassName)
executeHook($identifier, array $hookConfiguration=[])
getFluidTemplateObject($templatePathAndFileName=null)
static getUrl($url, $includeHeader=0, $requestHeaders=false, &$report=null)
static getFileAbsFileName($filename, $onlyRelative=true, $relToTYPO3_mainDir=false)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static removePrefixPathFromList(array $fileArr, $prefixToRemove)
static getRecordWSOL($table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
getModuleMenu(ServerRequestInterface $request, ResponseInterface $response)