[TASK] Make login_frameset.php dispatched
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / BackendController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller;
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
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Class for rendering the TYPO3 backend
23 *
24 * @author Ingo Renner <ingo@typo3.org>
25 */
26 class BackendController {
27
28 /**
29 * @var string
30 */
31 protected $content = '';
32
33 /**
34 * @var string
35 */
36 protected $css = '';
37
38 /**
39 * @var array
40 */
41 protected $cssFiles = array();
42
43 /**
44 * @var string
45 */
46 protected $js = '';
47
48 /**
49 * @var array
50 */
51 protected $jsFiles = array();
52
53 /**
54 * @var array
55 */
56 protected $toolbarItems = array();
57
58 /**
59 * @var int
60 */
61 protected $menuWidth = 190;
62
63 /**
64 * @var bool
65 */
66 protected $debug;
67
68 /**
69 * @var string
70 */
71 protected $templatePath = 'EXT:backend/Resources/Private/Templates/';
72
73 /**
74 * @var \TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository
75 */
76 protected $backendModuleRepository;
77
78 /**
79 * @var \TYPO3\CMS\Backend\Module\ModuleLoader Object for loading backend modules
80 */
81 protected $moduleLoader;
82
83 /**
84 * @var \TYPO3\CMS\Core\Page\PageRenderer
85 */
86 protected $pageRenderer;
87
88 /**
89 * @return \TYPO3\CMS\Core\Page\PageRenderer
90 */
91 public function getPageRenderer() {
92 return $this->pageRenderer;
93 }
94
95 /**
96 * Constructor
97 */
98 public function __construct() {
99 $this->backendModuleRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository::class);
100
101 // Set debug flag for BE development only
102 $this->debug = (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] === 1;
103 // Initializes the backend modules structure for use later.
104 $this->moduleLoader = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleLoader::class);
105 $this->moduleLoader->load($GLOBALS['TBE_MODULES']);
106 $this->pageRenderer = $GLOBALS['TBE_TEMPLATE']->getPageRenderer();
107 $this->pageRenderer->loadExtJS();
108 // included for the module menu JavaScript, please note that this is subject to change
109 $this->pageRenderer->loadJquery();
110 $this->pageRenderer->enableExtJSQuickTips();
111 $this->pageRenderer->addJsInlineCode('consoleOverrideWithDebugPanel', '//already done', FALSE);
112 $this->pageRenderer->addExtDirectCode();
113 // Add default BE javascript
114 $this->jsFiles = array(
115 'locallang' => $this->getLocalLangFileName(),
116 'modernizr' => 'contrib/modernizr/modernizr.min.js',
117 'md5' => 'sysext/backend/Resources/Public/JavaScript/md5.js',
118 'modulemenu' => 'sysext/backend/Resources/Public/JavaScript/modulemenu.js',
119 'evalfield' => 'sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js',
120 'tabclosemenu' => 'js/extjs/ux/ext.ux.tabclosemenu.js',
121 'notifications' => 'sysext/backend/Resources/Public/JavaScript/notifications.js',
122 'backend' => 'sysext/backend/Resources/Public/JavaScript/backend.js',
123 'debugPanel' => 'js/extjs/debugPanel.js',
124 'viewport' => 'js/extjs/viewport.js',
125 'iframepanel' => 'sysext/backend/Resources/Public/JavaScript/iframepanel.js',
126 'backendcontentiframe' => 'js/extjs/backendcontentiframe.js',
127 'viewportConfiguration' => 'js/extjs/viewportConfiguration.js',
128 'util' => 'sysext/backend/Resources/Public/JavaScript/util.js'
129 );
130 if (!$this->debug) {
131 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LoginRefresh', 'function(LoginRefresh) {
132 LoginRefresh.setLoginFramesetUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('login_frameset')) . ');
133 }');
134 }
135
136 // load FlashMessages functionality
137 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/FlashMessages');
138
139 // load Modals
140 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
141
142 // load Legacy CSS Support
143 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LegacyCssClasses');
144
145 // load the storage API and fill the UC into the PersistentStorage, so no additional AJAX call is needed
146 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Storage', 'function(Storage) {
147 Storage.Persistent.load(' . json_encode($GLOBALS['BE_USER']->uc) . ');
148 }');
149 $this->css = '';
150
151 $this->initializeToolbarItems();
152 if (isset($GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'])) {
153 $this->menuWidth = (int)$GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'];
154 }
155 $this->executeHook('constructPostProcess');
156 }
157
158 /**
159 * Initialize toolbar item objects
160 *
161 * @throws \RuntimeException
162 * @return void
163 */
164 protected function initializeToolbarItems() {
165 $toolbarItemInstances = array();
166 $classNameRegistry = $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'];
167 foreach ($classNameRegistry as $className) {
168 $toolbarItemInstance = GeneralUtility::makeInstance($className);
169 if (!$toolbarItemInstance instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface) {
170 throw new \RuntimeException(
171 'class ' . $className . ' is registered as toolbar item but does not implement'
172 . \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface::class,
173 1415958218
174 );
175 }
176 $index = (int)$toolbarItemInstance->getIndex();
177 if ($index < 0 || $index > 100) {
178 throw new \RuntimeException(
179 'getIndex() must return an integer between 0 and 100',
180 1415968498
181 );
182 }
183 // Find next free position in array
184 while(array_key_exists($index, $toolbarItemInstances)) {
185 $index++;
186 }
187 $toolbarItemInstances[$index] = $toolbarItemInstance;
188 }
189 ksort($toolbarItemInstances);
190 $this->toolbarItems = $toolbarItemInstances;
191 }
192
193 /**
194 * Main function generating the BE scaffolding
195 *
196 * @return void
197 */
198 public function render() {
199 $this->executeHook('renderPreProcess');
200
201 // Prepare the scaffolding, at this point extension may still add javascript and css
202 $view = $this->getFluidTemplateObject($this->templatePath . 'Backend/Main.html');
203 // @todo: kick logo view class and move all logic to Fluid
204 $view->assign('logo', GeneralUtility::makeInstance(\TYPO3\CMS\Backend\View\LogoView::class)->render());
205 $view->assign('moduleMenu', $this->generateModuleMenu());
206 $view->assign('toolbar', $this->renderToolbar());
207
208 /******************************************************
209 * Now put the complete backend document together
210 ******************************************************/
211 foreach ($this->cssFiles as $cssFileName => $cssFile) {
212 $this->pageRenderer->addCssFile($cssFile);
213 // Load additional css files to overwrite existing core styles
214 if (!empty($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName])) {
215 $this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName]);
216 }
217 }
218 if (!empty($this->css)) {
219 $this->pageRenderer->addCssInlineBlock('BackendInlineCSS', $this->css);
220 }
221 foreach ($this->jsFiles as $jsFile) {
222 $this->pageRenderer->addJsFile($jsFile);
223 }
224 $this->generateJavascript();
225 $this->pageRenderer->addJsInlineCode('BackendInlineJavascript', $this->js, FALSE);
226 $this->loadResourcesForRegisteredNavigationComponents();
227
228 // Add state provider
229 $GLOBALS['TBE_TEMPLATE']->setExtDirectStateProvider();
230 $states = $GLOBALS['BE_USER']->uc['BackendComponents']['States'];
231 // Save states in BE_USER->uc
232 $extOnReadyCode = '
233 Ext.state.Manager.setProvider(new TYPO3.state.ExtDirectProvider({
234 key: "BackendComponents.States",
235 autoRead: false
236 }));
237 ';
238
239 if ($states) {
240 $extOnReadyCode .= 'Ext.state.Manager.getProvider().initState(' . json_encode($states) . ');';
241 }
242
243 $extOnReadyCode .= '
244 TYPO3.Backend = new TYPO3.Viewport(TYPO3.Viewport.configuration);
245 if (typeof console === "undefined") {
246 console = TYPO3.Backend.DebugConsole;
247 }
248 TYPO3.ContextHelpWindow.init(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('help_cshmanual')) . ');';
249 $this->pageRenderer->addExtOnReadyCode($extOnReadyCode);
250 // Set document title:
251 $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version;
252 // Renders the module page
253 $this->content = $GLOBALS['TBE_TEMPLATE']->render($title, $view->render());
254 $hookConfiguration = array('content' => &$this->content);
255 $this->executeHook('renderPostProcess', $hookConfiguration);
256 echo $this->content;
257 }
258
259 /**
260 * Loads the css and javascript files of all registered navigation widgets
261 *
262 * @return void
263 */
264 protected function loadResourcesForRegisteredNavigationComponents() {
265 if (!is_array($GLOBALS['TBE_MODULES']['_navigationComponents'])) {
266 return;
267 }
268 $loadedComponents = array();
269 foreach ($GLOBALS['TBE_MODULES']['_navigationComponents'] as $module => $info) {
270 if (in_array($info['componentId'], $loadedComponents)) {
271 continue;
272 }
273 $loadedComponents[] = $info['componentId'];
274 $component = strtolower(substr($info['componentId'], strrpos($info['componentId'], '-') + 1));
275 $componentDirectory = 'components/' . $component . '/';
276 if ($info['isCoreComponent']) {
277 $absoluteComponentPath = PATH_site . 'typo3/js/extjs/' . $componentDirectory;
278 $relativeComponentPath = '../' . str_replace(PATH_site, '', $absoluteComponentPath);
279 } else {
280 $absoluteComponentPath = ExtensionManagementUtility::extPath($info['extKey']) . $componentDirectory;
281 $relativeComponentPath = ExtensionManagementUtility::extRelPath($info['extKey']) . $componentDirectory;
282 }
283 $cssFiles = GeneralUtility::getFilesInDir($absoluteComponentPath . 'css/', 'css');
284 if (file_exists($absoluteComponentPath . 'css/loadorder.txt')) {
285 // Don't allow inclusion outside directory
286 $loadOrder = str_replace('../', '', GeneralUtility::getUrl($absoluteComponentPath . 'css/loadorder.txt'));
287 $cssFilesOrdered = GeneralUtility::trimExplode(LF, $loadOrder, TRUE);
288 $cssFiles = array_merge($cssFilesOrdered, $cssFiles);
289 }
290 foreach ($cssFiles as $cssFile) {
291 $this->pageRenderer->addCssFile($relativeComponentPath . 'css/' . $cssFile);
292 }
293 $jsFiles = GeneralUtility::getFilesInDir($absoluteComponentPath . 'javascript/', 'js');
294 if (file_exists($absoluteComponentPath . 'javascript/loadorder.txt')) {
295 // Don't allow inclusion outside directory
296 $loadOrder = str_replace('../', '', GeneralUtility::getUrl($absoluteComponentPath . 'javascript/loadorder.txt'));
297 $jsFilesOrdered = GeneralUtility::trimExplode(LF, $loadOrder, TRUE);
298 $jsFiles = array_merge($jsFilesOrdered, $jsFiles);
299 }
300 foreach ($jsFiles as $jsFile) {
301 $this->pageRenderer->addJsFile($relativeComponentPath . 'javascript/' . $jsFile);
302 }
303 $this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', BackendUtility::getModuleUrl('record_history'));
304 }
305 }
306
307 /**
308 * Renders the items in the top toolbar
309 *
310 * @return string top toolbar elements as HTML
311 */
312 protected function renderToolbar() {
313 $toolbar = array();
314 foreach ($this->toolbarItems as $toolbarItem) {
315 /** @var \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface $toolbarItem */
316 if ($toolbarItem->checkAccess()) {
317 $hasDropDown = (bool)$toolbarItem->hasDropDown();
318 $additionalAttributes = (array)$toolbarItem->getAdditionalAttributes();
319
320 $liAttributes = array();
321
322 // Merge class: Add dropdown class if hasDropDown, add classes from additonal attributes
323 $classes = array();
324 if ($hasDropDown) {
325 $classes[] = 'dropdown';
326 }
327 if (isset($additionalAttributes['class'])) {
328 $classes[] = $additionalAttributes['class'];
329 unset($additionalAttributes['class']);
330 }
331 $liAttributes[] = 'class="' . implode(' ', $classes) . '"';
332
333 // Add further attributes
334 foreach($additionalAttributes as $name => $value) {
335 $liAttributes[] = $name . '="' . $value . '"';
336 }
337
338 // Create a unique id from class name
339 $className = get_class($toolbarItem);
340 $className = GeneralUtility::underscoredToLowerCamelCase($className);
341 $className = GeneralUtility::camelCaseToLowerCaseUnderscored($className);
342 $className = str_replace(array('_', '\\'), '-', $className);
343 $liAttributes[] = 'id="' . $className . '"';
344
345 $toolbar[] = '<li ' . implode(' ', $liAttributes) . '>';
346
347 if ($hasDropDown) {
348 $toolbar[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">';
349 $toolbar[] = $toolbarItem->getItem();
350 $toolbar[] = '</a>';
351 $toolbar[] = '<div class="dropdown-menu" role="menu">';
352 $toolbar[] = $toolbarItem->getDropDown();
353 $toolbar[] = '</div>';
354 } else {
355 $toolbar[] = $toolbarItem->getItem();
356 }
357 $toolbar[] = '</li>';
358 }
359 }
360 return implode(LF, $toolbar);
361 }
362
363 /**
364 * Returns the file name to the LLL JavaScript, containing the localized labels,
365 * which can be used in JavaScript code.
366 *
367 * @return string File name of the JS file, relative to TYPO3_mainDir
368 */
369 protected function getLocalLangFileName() {
370 $code = $this->generateLocalLang();
371 $filePath = 'typo3temp/locallang-BE-' . sha1($code) . '.js';
372 if (!file_exists((PATH_site . $filePath))) {
373 // writeFileToTypo3tempDir() returns NULL on success (please double-read!)
374 if (GeneralUtility::writeFileToTypo3tempDir(PATH_site . $filePath, $code) !== NULL) {
375 throw new \RuntimeException('LocalLangFile could not be written to ' . $filePath, 1295193026);
376 }
377 }
378 return '../' . $filePath;
379 }
380
381 /**
382 * Reads labels required in JavaScript code from the localization system and returns them as JSON
383 * array in TYPO3.LLL.
384 *
385 * @return string JavaScript code containing the LLL labels in TYPO3.LLL
386 */
387 protected function generateLocalLang() {
388 $coreLabels = array(
389 'waitTitle' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_logging_in'),
390 'refresh_login_failed' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_failed'),
391 'refresh_login_failed_message' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_failed_message'),
392 'refresh_login_title' => sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_title'), htmlspecialchars($GLOBALS['BE_USER']->user['username'])),
393 'login_expired' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_expired'),
394 'refresh_login_username' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_username'),
395 'refresh_login_password' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_password'),
396 'refresh_login_emptyPassword' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_emptyPassword'),
397 'refresh_login_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_button'),
398 'refresh_logout_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_logout_button'),
399 'please_wait' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.please_wait'),
400 'loadingIndicator' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:loadingIndicator'),
401 'be_locked' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.be_locked'),
402 'refresh_login_countdown_singular' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_countdown_singular'),
403 'refresh_login_countdown' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_countdown'),
404 'login_about_to_expire' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_about_to_expire'),
405 'login_about_to_expire_title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_about_to_expire_title'),
406 'refresh_login_refresh_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_refresh_button'),
407 'refresh_direct_logout_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_direct_logout_button'),
408 'tabs_closeAll' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.closeAll'),
409 'tabs_closeOther' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.closeOther'),
410 'tabs_close' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.close'),
411 'tabs_openInBrowserWindow' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.openInBrowserWindow'),
412 'csh_tooltip_loading' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:csh_tooltip_loading')
413 );
414 $labels = array(
415 'fileUpload' => array(
416 'windowTitle',
417 'buttonSelectFiles',
418 'buttonCancelAll',
419 'infoComponentMaxFileSize',
420 'infoComponentFileUploadLimit',
421 'infoComponentFileTypeLimit',
422 'infoComponentOverrideFiles',
423 'processRunning',
424 'uploadWait',
425 'uploadStarting',
426 'uploadProgress',
427 'uploadSuccess',
428 'errorQueueLimitExceeded',
429 'errorQueueFileSizeLimit',
430 'errorQueueZeroByteFile',
431 'errorQueueInvalidFiletype',
432 'errorUploadHttp',
433 'errorUploadMissingUrl',
434 'errorUploadIO',
435 'errorUploadSecurityError',
436 'errorUploadLimit',
437 'errorUploadFailed',
438 'errorUploadFileIDNotFound',
439 'errorUploadFileValidation',
440 'errorUploadFileCancelled',
441 'errorUploadStopped',
442 'allErrorMessageTitle',
443 'allErrorMessageText',
444 'allError401',
445 'allError2038'
446 ),
447 'liveSearch' => array(
448 'title',
449 'helpTitle',
450 'emptyText',
451 'loadingText',
452 'listEmptyText',
453 'showAllResults',
454 'helpDescription',
455 'helpDescriptionPages',
456 'helpDescriptionContent'
457 ),
458 'viewPort' => array(
459 'tooltipModuleMenuSplit',
460 'tooltipNavigationContainerSplitDrag',
461 'tooltipDebugPanelSplitDrag'
462 )
463 );
464 $generatedLabels = array();
465 $generatedLabels['core'] = $coreLabels;
466 // First loop over all categories (fileUpload, liveSearch, ..)
467 foreach ($labels as $categoryName => $categoryLabels) {
468 // Then loop over every single label
469 foreach ($categoryLabels as $label) {
470 // LLL identifier must be called $categoryName_$label, e.g. liveSearch_loadingText
471 $generatedLabels[$categoryName][$label] = $GLOBALS['LANG']->getLL($categoryName . '_' . $label);
472 }
473 }
474 return 'TYPO3.LLL = ' . json_encode($generatedLabels) . ';';
475 }
476
477 /**
478 * Generates the JavaScript code for the backend.
479 *
480 * @return void
481 */
482 protected function generateJavascript() {
483
484 // Needed for FormEngine manipulation (date picker)
485 $dateFormat = ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? array('MM-DD-YYYY', 'HH:mm MM-DD-YYYY') : array('DD-MM-YYYY', 'HH:mm DD-MM-YYYY'));
486 $this->pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat);
487 // define the window size of the element browser etc.
488 $popupWindowSize = trim($GLOBALS['BE_USER']->getTSConfigVal('options.popupWindowSize'));
489 if (!empty($popupWindowSize)) {
490 list($popupWindowWidth, $popupWindowHeight) = GeneralUtility::trimExplode('x', $popupWindowSize);
491 }
492 $popupWindowWidth = !empty($popupWindowWidth) ? (int)$popupWindowWidth : 700;
493 $popupWindowHeight = !empty($popupWindowHeight) ? (int)$popupWindowHeight : 750;
494
495 // define the window size of the popups within the RTE
496 $rtePopupWindowSize = trim($GLOBALS['BE_USER']->getTSConfigVal('options.rte.popupWindowSize'));
497 if (!empty($rtePopupWindowSize)) {
498 list($rtePopupWindowWidth, $rtePopupWindowHeight) = GeneralUtility::trimExplode('x', $rtePopupWindowSize);
499 }
500 $rtePopupWindowWidth = !empty($rtePopupWindowWidth) ? (int)$rtePopupWindowWidth : ($popupWindowWidth-200);
501 $rtePopupWindowHeight = !empty($rtePopupWindowHeight) ? (int)$rtePopupWindowHeight : ($popupWindowHeight-250);
502
503 $pathTYPO3 = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/';
504 // If another page module was specified, replace the default Page module with the new one
505 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
506 $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
507 if (!$GLOBALS['BE_USER']->check('modules', $pageModule)) {
508 $pageModule = '';
509 }
510 // Determine security level from conf vars and default to super challenged
511 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) {
512 $this->loginSecurityLevel = $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'];
513 } else {
514 $this->loginSecurityLevel = 'superchallenged';
515 }
516 $t3Configuration = array(
517 'siteUrl' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL'),
518 'PATH_typo3' => $pathTYPO3,
519 'PATH_typo3_enc' => rawurlencode($pathTYPO3),
520 'username' => htmlspecialchars($GLOBALS['BE_USER']->user['username']),
521 'uniqueID' => GeneralUtility::shortMD5(uniqid('', TRUE)),
522 'securityLevel' => $this->loginSecurityLevel,
523 'TYPO3_mainDir' => TYPO3_mainDir,
524 'pageModule' => $pageModule,
525 'inWorkspace' => $GLOBALS['BE_USER']->workspace !== 0,
526 'workspaceFrontendPreviewEnabled' => $GLOBALS['BE_USER']->user['workspace_preview'] ? 1 : 0,
527 'veriCode' => $GLOBALS['BE_USER']->veriCode(),
528 'denyFileTypes' => PHP_EXTENSIONS_DEFAULT,
529 'moduleMenuWidth' => $this->menuWidth - 1,
530 'topBarHeight' => isset($GLOBALS['TBE_STYLES']['dims']['topFrameH']) ? (int)$GLOBALS['TBE_STYLES']['dims']['topFrameH'] : 30,
531 'showRefreshLoginPopup' => isset($GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup']) ? (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup'] : FALSE,
532 'listModulePath' => ExtensionManagementUtility::extRelPath('recordlist') . 'mod1/',
533 'debugInWindow' => $GLOBALS['BE_USER']->uc['debugInWindow'] ? 1 : 0,
534 'ContextHelpWindows' => array(
535 'width' => 600,
536 'height' => 400
537 ),
538 'PopupWindow' => array(
539 'width' => $popupWindowWidth,
540 'height' => $popupWindowHeight
541 ),
542 'RTEPopupWindow' => array(
543 'width' => $rtePopupWindowWidth,
544 'height' => $rtePopupWindowHeight
545 )
546 );
547 $this->js .= '
548 TYPO3.configuration = ' . json_encode($t3Configuration) . ';
549
550 /**
551 * TypoSetup object.
552 */
553 function typoSetup() { //
554 this.PATH_typo3 = TYPO3.configuration.PATH_typo3;
555 this.PATH_typo3_enc = TYPO3.configuration.PATH_typo3_enc;
556 this.username = TYPO3.configuration.username;
557 this.uniqueID = TYPO3.configuration.uniqueID;
558 this.navFrameWidth = 0;
559 this.securityLevel = TYPO3.configuration.securityLevel;
560 this.veriCode = TYPO3.configuration.veriCode;
561 this.denyFileTypes = TYPO3.configuration.denyFileTypes;
562 }
563 var TS = new typoSetup();
564 //backwards compatibility
565 /**
566 * Frameset Module object
567 *
568 * Used in main modules with a frameset for submodules to keep the ID between modules
569 * Typically that is set by something like this in a Web>* sub module:
570 * if (top.fsMod) top.fsMod.recentIds["web"] = "\'.(int)$this->id.\'";
571 * if (top.fsMod) top.fsMod.recentIds["file"] = "...(file reference/string)...";
572 */
573 function fsModules() { //
574 this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
575 this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
576 this.currentMainLoaded="";
577 this.currentBank="0";
578 }
579 var fsMod = new fsModules();
580
581 top.goToModule = function(modName, cMR_flag, addGetVars) {
582 TYPO3.ModuleMenu.App.showModule(modName, addGetVars);
583 }
584 ' . $this->setStartupModule();
585 // Check editing of page:
586 $this->handlePageEditing();
587 }
588
589 /**
590 * Checking if the "&edit" variable was sent so we can open it for editing the page.
591 *
592 * @return void
593 */
594 protected function handlePageEditing() {
595 // EDIT page:
596 $editId = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('edit'));
597 $editRecord = '';
598 if ($editId) {
599 // Looking up the page to edit, checking permissions:
600 $where = ' AND (' . $GLOBALS['BE_USER']->getPagePermsClause(2) . ' OR ' . $GLOBALS['BE_USER']->getPagePermsClause(16) . ')';
601 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($editId)) {
602 $editRecord = BackendUtility::getRecordWSOL('pages', $editId, '*', $where);
603 } else {
604 $records = BackendUtility::getRecordsByField('pages', 'alias', $editId, $where);
605 if (is_array($records)) {
606 $editRecord = reset($records);
607 BackendUtility::workspaceOL('pages', $editRecord);
608 }
609 }
610 // If the page was accessible, then let the user edit it.
611 if (is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) {
612 // Setting JS code to open editing:
613 $this->js .= '
614 // Load page to edit:
615 window.setTimeout("top.loadEditId(' . (int)$editRecord['uid'] . ');", 500);
616 ';
617 // Checking page edit parameter:
618 if (!$GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) {
619 $bookmarkKeepExpanded = $GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded');
620 // Expanding page tree:
621 BackendUtility::openPageTree((int)$editRecord['pid'], !$bookmarkKeepExpanded);
622 }
623 } else {
624 $this->js .= '
625 // Warning about page editing:
626 alert(' . GeneralUtility::quoteJSvalue(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)) . ');
627 ';
628 }
629 }
630 }
631
632 /**
633 * Sets the startup module from either GETvars module and modParams or user configuration.
634 *
635 * @return string the JavaScript code for the startup module
636 */
637 protected function setStartupModule() {
638 $startModule = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('module'));
639 if (!$startModule) {
640 // start module on first login, will be removed once used the first time
641 if (isset($GLOBALS['BE_USER']->uc['startModuleOnFirstLogin'])) {
642 $startModule = $GLOBALS['BE_USER']->uc['startModuleOnFirstLogin'];
643 unset($GLOBALS['BE_USER']->uc['startModuleOnFirstLogin']);
644 $GLOBALS['BE_USER']->writeUC();
645 } elseif ($GLOBALS['BE_USER']->uc['startModule']) {
646 $startModule = $GLOBALS['BE_USER']->uc['startModule'];
647 } elseif ($GLOBALS['BE_USER']->uc['startInTaskCenter']) {
648 $startModule = 'user_task';
649 }
650
651 // check if the start module has additional parameters, so a redirect to a specific
652 // action is possible
653 if (strpos($startModule, '->') !== FALSE) {
654 list($startModule, $startModuleParameters) = explode('->', $startModule, 2);
655 }
656 }
657
658 $moduleParameters = GeneralUtility::_GET('modParams');
659 // if no GET parameters are set, check if there are parameters given from the UC
660 if (!$moduleParameters && $startModuleParameters) {
661 $moduleParameters = $startModuleParameters;
662 }
663
664 if ($startModule) {
665 return '
666 // start in module:
667 top.startInModule = [\'' . $startModule . '\', ' . GeneralUtility::quoteJSvalue($moduleParameters) . '];
668 ';
669 } else {
670 return '';
671 }
672 }
673
674 /**
675 * Adds a javascript snippet to the backend
676 *
677 * @param string $javascript Javascript snippet
678 * @return void
679 * @throws \InvalidArgumentException
680 */
681 public function addJavascript($javascript) {
682 // @todo do we need more checks?
683 if (!is_string($javascript)) {
684 throw new \InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
685 }
686 $this->js .= $javascript;
687 }
688
689 /**
690 * Adds a javscript file to the backend after it has been checked that it exists
691 *
692 * @param string $javascriptFile Javascript file reference
693 * @return bool TRUE if the javascript file was successfully added, FALSE otherwise
694 */
695 public function addJavascriptFile($javascriptFile) {
696 $jsFileAdded = FALSE;
697 // @todo add more checks if necessary
698 if (file_exists(GeneralUtility::resolveBackPath(PATH_typo3 . $javascriptFile))) {
699 $this->jsFiles[] = $javascriptFile;
700 $jsFileAdded = TRUE;
701 }
702 return $jsFileAdded;
703 }
704
705 /**
706 * Adds a css snippet to the backend
707 *
708 * @param string $css Css snippet
709 * @return void
710 */
711 public function addCss($css) {
712 if (!is_string($css)) {
713 throw new \InvalidArgumentException('parameter $css must be of type string', 1195129642);
714 }
715 $this->css .= $css;
716 }
717
718 /**
719 * Adds a css file to the backend after it has been checked that it exists
720 *
721 * @param string $cssFileName The css file's name with out the .css ending
722 * @param string $cssFile Css file reference
723 * @return bool TRUE if the css file was added, FALSE otherwise
724 */
725 public function addCssFile($cssFileName, $cssFile) {
726 $cssFileAdded = FALSE;
727 if (empty($this->cssFiles[$cssFileName])) {
728 $this->cssFiles[$cssFileName] = $cssFile;
729 $cssFileAdded = TRUE;
730 }
731 return $cssFileAdded;
732 }
733
734 /**
735 * Adds an item to the toolbar, the class file for the toolbar item must be loaded at this point
736 *
737 * @param string $toolbarItemName Toolbar item name, f.e. tx_toolbarExtension_coolItem
738 * @param string $toolbarItemClassName Toolbar item class name, f.e. tx_toolbarExtension_coolItem
739 * @return void
740 * @throws \UnexpectedValueException
741 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8. Toolbar items are registered in $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'] now.
742 */
743 public function addToolbarItem($toolbarItemName, $toolbarItemClassName) {
744 GeneralUtility::logDeprecatedFunction();
745 }
746
747 /**
748 * Executes defined hooks functions for the given identifier.
749 *
750 * These hook identifiers are valid:
751 * + constructPostProcess
752 * + renderPreProcess
753 * + renderPostProcess
754 *
755 * @param string $identifier Specific hook identifier
756 * @param array $hookConfiguration Additional configuration passed to hook functions
757 * @return void
758 */
759 protected function executeHook($identifier, array $hookConfiguration = array()) {
760 $options = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php'];
761 if (isset($options[$identifier]) && is_array($options[$identifier])) {
762 foreach ($options[$identifier] as $hookFunction) {
763 GeneralUtility::callUserFunction($hookFunction, $hookConfiguration, $this);
764 }
765 }
766 }
767
768 /**
769 * loads all modules from the repository
770 * and renders it with a template
771 *
772 * @return string
773 */
774 protected function generateModuleMenu() {
775 // get all modules except the user modules for the side menu
776 $moduleStorage = $this->backendModuleRepository->loadAllowedModules(array('user', 'help'));
777
778 $view = $this->getFluidTemplateObject($this->templatePath . 'ModuleMenu/Main.html');
779 $view->assign('modules', $moduleStorage);
780 return $view->render();
781 }
782
783 /**
784 * Returns the Module menu for the AJAX API
785 *
786 * @param array $params
787 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxRequestHandler
788 * @return void
789 */
790 public function getModuleMenuForReload($params, $ajaxRequestHandler) {
791 $content = $this->generateModuleMenu();
792 $ajaxRequestHandler->addContent('menu', $content);
793 $ajaxRequestHandler->setContentFormat('json');
794 }
795
796 /**
797 * returns a new standalone view, shorthand function
798 *
799 * @param string $templatePathAndFileName optional the path to set the template path and filename
800 * @return \TYPO3\CMS\Fluid\View\StandaloneView
801 */
802 protected function getFluidTemplateObject($templatePathAndFileName = NULL) {
803 $view = GeneralUtility::makeInstance(\TYPO3\CMS\Fluid\View\StandaloneView::class);
804 if ($templatePathAndFileName) {
805 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFileName));
806 }
807 return $view;
808 }
809
810 }