[TASK] Redirect to distributions after first login
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / BackendController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2007-2013 Ingo Renner <ingo@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
32 use TYPO3\CMS\Core\Utility\GeneralUtility;
33
34 /**
35 * Class for rendering the TYPO3 backend version 4.2+
36 *
37 * @author Ingo Renner <ingo@typo3.org>
38 */
39 class BackendController {
40
41 protected $content;
42
43 protected $css;
44
45 protected $cssFiles;
46
47 protected $js;
48
49 protected $jsFiles;
50
51 protected $jsFilesAfterInline;
52
53 protected $toolbarItems;
54
55 // intentionally private as nobody should modify defaults
56 private $menuWidthDefault = 190;
57
58 protected $menuWidth;
59
60 protected $debug;
61
62 /**
63 * Object for loading backend modules
64 *
65 * @var \TYPO3\CMS\Backend\Module\ModuleLoader
66 */
67 protected $moduleLoader;
68
69 /**
70 * module menu generating object
71 *
72 * @var \TYPO3\CMS\Backend\View\ModuleMenuView
73 */
74 protected $moduleMenu;
75
76 /**
77 * Pagerenderer
78 *
79 * @var \TYPO3\CMS\Core\Page\PageRenderer
80 */
81 protected $pageRenderer;
82
83 /**
84 * @return \TYPO3\CMS\Core\Page\PageRenderer
85 */
86 public function getPageRenderer() {
87 return $this->pageRenderer;
88 }
89
90 /**
91 * Constructor
92 */
93 public function __construct() {
94 // Set debug flag for BE development only
95 $this->debug = (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] === 1;
96 // Initializes the backend modules structure for use later.
97 $this->moduleLoader = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Module\\ModuleLoader');
98 $this->moduleLoader->load($GLOBALS['TBE_MODULES']);
99 $this->moduleMenu = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\View\\ModuleMenuView');
100 $this->pageRenderer = $GLOBALS['TBE_TEMPLATE']->getPageRenderer();
101 $this->pageRenderer->loadScriptaculous('builder,effects,controls,dragdrop');
102 $this->pageRenderer->loadExtJS();
103 $this->pageRenderer->enableExtJSQuickTips();
104 $this->pageRenderer->addJsInlineCode('consoleOverrideWithDebugPanel', '//already done', FALSE);
105 $this->pageRenderer->addExtDirectCode();
106 $this->pageRenderer->addInlineSetting('ModuleMenu.getData', 'ajaxUrl', BackendUtility::getAjaxUrl('ModuleMenu::getData'));
107 $this->pageRenderer->addInlineSetting('ModuleMenu.saveMenuState', 'ajaxUrl', BackendUtility::getAjaxUrl('ModuleMenu::saveMenuState'));
108 $this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::login', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::login'));
109 $this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::logout', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::logout'));
110 $this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::refreshLogin', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::refreshLogin'));
111 $this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::isTimedOut', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::isTimedOut'));
112 $this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::getChallenge', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::getChallenge'));
113 $this->pageRenderer->addInlineSetting('ImportExport', 'moduleUrl', BackendUtility::getModuleUrl('xMOD_tximpexp'));
114 // Add default BE javascript
115 $this->js = '';
116 $this->jsFiles = array(
117 'common' => 'sysext/backend/Resources/Public/JavaScript/common.js',
118 'locallang' => $this->getLocalLangFileName(),
119 'modernizr' => 'contrib/modernizr/modernizr.min.js',
120 'md5' => 'sysext/backend/Resources/Public/JavaScript/md5.js',
121 'toolbarmanager' => 'sysext/backend/Resources/Public/JavaScript/toolbarmanager.js',
122 'modulemenu' => 'sysext/backend/Resources/Public/JavaScript/modulemenu.js',
123 'iecompatibility' => 'sysext/backend/Resources/Public/JavaScript/iecompatibility.js',
124 'evalfield' => 'sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js',
125 'flashmessages' => 'sysext/backend/Resources/Public/JavaScript/flashmessages.js',
126 'tabclosemenu' => 'js/extjs/ux/ext.ux.tabclosemenu.js',
127 'notifications' => 'sysext/backend/Resources/Public/JavaScript/notifications.js',
128 'backend' => 'sysext/backend/Resources/Public/JavaScript/backend.js',
129 'loginrefresh' => 'sysext/backend/Resources/Public/JavaScript/loginrefresh.js',
130 'debugPanel' => 'js/extjs/debugPanel.js',
131 'viewport' => 'js/extjs/viewport.js',
132 'iframepanel' => 'sysext/backend/Resources/Public/JavaScript/iframepanel.js',
133 'backendcontentiframe' => 'js/extjs/backendcontentiframe.js',
134 'modulepanel' => 'js/extjs/modulepanel.js',
135 'viewportConfiguration' => 'js/extjs/viewportConfiguration.js',
136 'util' => 'sysext/backend/Resources/Public/JavaScript/util.js'
137 );
138 if ($this->debug) {
139 unset($this->jsFiles['loginrefresh']);
140 }
141 // Add default BE css
142 $this->pageRenderer->addCssLibrary('contrib/normalize/normalize.css', 'stylesheet', 'all', '', TRUE, TRUE);
143 $this->css = '';
144 $this->cssFiles = array();
145 $this->toolbarItems = array();
146 $this->initializeCoreToolbarItems();
147 $this->menuWidth = $this->menuWidthDefault;
148 if (isset($GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW']) && (int)$GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'] != (int)$this->menuWidth) {
149 $this->menuWidth = (int)$GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'];
150 }
151 $this->executeHook('constructPostProcess');
152 }
153
154 /**
155 * Initializes the core toolbar items
156 *
157 * @return void
158 */
159 protected function initializeCoreToolbarItems() {
160 $coreToolbarItems = array(
161 'shortcuts' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem',
162 'clearCacheActions' => 'TYPO3\\CMS\\Backend\\Toolbar\\ClearCacheToolbarItem',
163 'liveSearch' => '\\TYPO3\\CMS\\Backend\\Toolbar\\LiveSearchToolbarItem'
164 );
165 foreach ($coreToolbarItems as $toolbarItemName => $toolbarItemClassName) {
166 $toolbarItem = GeneralUtility::makeInstance($toolbarItemClassName, $this);
167 if (!$toolbarItem instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemHookInterface) {
168 throw new \UnexpectedValueException('$toolbarItem "' . $toolbarItemName . '" must implement interface TYPO3\\CMS\\Backend\\Toolbar\\ToolbarItemHookInterface', 1195126772);
169 }
170 if ($toolbarItem->checkAccess()) {
171 $this->toolbarItems[$toolbarItemName] = $toolbarItem;
172 } else {
173 unset($toolbarItem);
174 }
175 }
176 }
177
178 /**
179 * Main function generating the BE scaffolding
180 *
181 * @return void
182 */
183 public function render() {
184 $this->executeHook('renderPreProcess');
185
186 // Prepare the scaffolding, at this point extension may still add javascript and css
187 $logo = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\View\\LogoView');
188
189 // Create backend scaffolding
190 $backendScaffolding = '
191 <div id="typo3-top-container" class="x-hide-display">
192 <div id="typo3-logo">' . $logo->render() . '</div>
193 <div id="typo3-top" class="typo3-top-toolbar">' . $this->renderToolbar() . '</div>
194 </div>';
195 /******************************************************
196 * Now put the complete backend document together
197 ******************************************************/
198 foreach ($this->cssFiles as $cssFileName => $cssFile) {
199 $this->pageRenderer->addCssFile($cssFile);
200 // Load additional css files to overwrite existing core styles
201 if (!empty($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName])) {
202 $this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName]);
203 }
204 }
205 if (!empty($this->css)) {
206 $this->pageRenderer->addCssInlineBlock('BackendInlineCSS', $this->css);
207 }
208 foreach ($this->jsFiles as $jsFile) {
209 $this->pageRenderer->addJsFile($jsFile);
210 }
211 $this->generateJavascript();
212 $this->pageRenderer->addJsInlineCode('BackendInlineJavascript', $this->js, FALSE);
213 $this->loadResourcesForRegisteredNavigationComponents();
214 // Add state provider
215 $GLOBALS['TBE_TEMPLATE']->setExtDirectStateProvider();
216 $states = $GLOBALS['BE_USER']->uc['BackendComponents']['States'];
217 // Save states in BE_USER->uc
218 $extOnReadyCode = '
219 Ext.state.Manager.setProvider(new TYPO3.state.ExtDirectProvider({
220 key: "BackendComponents.States",
221 autoRead: false
222 }));
223 ';
224 if ($states) {
225 $extOnReadyCode .= 'Ext.state.Manager.getProvider().initState(' . json_encode($states) . ');';
226 }
227 $extOnReadyCode .= '
228 TYPO3.Backend = new TYPO3.Viewport(TYPO3.Viewport.configuration);
229 if (typeof console === "undefined") {
230 console = TYPO3.Backend.DebugConsole;
231 }
232 TYPO3.ContextHelpWindow.init(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('help_cshmanual')) . ');';
233 $this->pageRenderer->addExtOnReadyCode($extOnReadyCode);
234 // Set document title:
235 $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version;
236 $this->content = $backendScaffolding;
237 // Renders the module page
238 $this->content = $GLOBALS['TBE_TEMPLATE']->render($title, $this->content);
239 $hookConfiguration = array('content' => &$this->content);
240 $this->executeHook('renderPostProcess', $hookConfiguration);
241 echo $this->content;
242 }
243
244 /**
245 * Loads the css and javascript files of all registered navigation widgets
246 *
247 * @return void
248 */
249 protected function loadResourcesForRegisteredNavigationComponents() {
250 if (!is_array($GLOBALS['TBE_MODULES']['_navigationComponents'])) {
251 return;
252 }
253 $loadedComponents = array();
254 foreach ($GLOBALS['TBE_MODULES']['_navigationComponents'] as $module => $info) {
255 if (in_array($info['componentId'], $loadedComponents)) {
256 continue;
257 }
258 $loadedComponents[] = $info['componentId'];
259 $component = strtolower(substr($info['componentId'], strrpos($info['componentId'], '-') + 1));
260 $componentDirectory = 'components/' . $component . '/';
261 if ($info['isCoreComponent']) {
262 $absoluteComponentPath = PATH_site . 'typo3/js/extjs/' . $componentDirectory;
263 $relativeComponentPath = '../' . str_replace(PATH_site, '', $absoluteComponentPath);
264 } else {
265 $absoluteComponentPath = ExtensionManagementUtility::extPath($info['extKey']) . $componentDirectory;
266 $relativeComponentPath = ExtensionManagementUtility::extRelPath($info['extKey']) . $componentDirectory;
267 }
268 $cssFiles = GeneralUtility::getFilesInDir($absoluteComponentPath . 'css/', 'css');
269 if (file_exists($absoluteComponentPath . 'css/loadorder.txt')) {
270 // Don't allow inclusion outside directory
271 $loadOrder = str_replace('../', '', GeneralUtility::getUrl($absoluteComponentPath . 'css/loadorder.txt'));
272 $cssFilesOrdered = GeneralUtility::trimExplode(LF, $loadOrder, TRUE);
273 $cssFiles = array_merge($cssFilesOrdered, $cssFiles);
274 }
275 foreach ($cssFiles as $cssFile) {
276 $this->pageRenderer->addCssFile($relativeComponentPath . 'css/' . $cssFile);
277 }
278 $jsFiles = GeneralUtility::getFilesInDir($absoluteComponentPath . 'javascript/', 'js');
279 if (file_exists($absoluteComponentPath . 'javascript/loadorder.txt')) {
280 // Don't allow inclusion outside directory
281 $loadOrder = str_replace('../', '', GeneralUtility::getUrl($absoluteComponentPath . 'javascript/loadorder.txt'));
282 $jsFilesOrdered = GeneralUtility::trimExplode(LF, $loadOrder, TRUE);
283 $jsFiles = array_merge($jsFilesOrdered, $jsFiles);
284 }
285 foreach ($jsFiles as $jsFile) {
286 $this->pageRenderer->addJsFile($relativeComponentPath . 'javascript/' . $jsFile);
287 }
288 }
289 }
290
291 /**
292 * Renders the items in the top toolbar
293 *
294 * @return string top toolbar elements as HTML
295 */
296 protected function renderToolbar() {
297 // Move search to last position
298 if (array_key_exists('liveSearch', $this->toolbarItems)) {
299 $search = $this->toolbarItems['liveSearch'];
300 unset($this->toolbarItems['liveSearch']);
301 $this->toolbarItems['liveSearch'] = $search;
302 }
303 $toolbar = '<ul id="typo3-toolbar">';
304 $toolbar .= '<li>' . $this->getLoggedInUserLabel() . '</li>';
305 $toolbar .= '<li class="separator"><div id="logout-button" class="toolbar-item no-separator">' . $this->moduleMenu->renderLogoutButton() . '</div></li>';
306 $i = 0;
307 foreach ($this->toolbarItems as $key => $toolbarItem) {
308 $i++;
309 $menu = $toolbarItem->render();
310 if ($menu) {
311 $additionalAttributes = $toolbarItem->getAdditionalAttributes();
312 if (sizeof($this->toolbarItems) > 1 && $i == sizeof($this->toolbarItems) - 1) {
313 if (strpos($additionalAttributes, 'class="')) {
314 str_replace('class="', 'class="separator ', $additionalAttributes);
315 } else {
316 $additionalAttributes .= 'class="separator"';
317 }
318 }
319 $toolbar .= '<li ' . $additionalAttributes . '>' . $menu . '</li>';
320 }
321 }
322 return $toolbar . '</ul>';
323 }
324
325 /**
326 * Gets the label of the BE user currently logged in
327 *
328 * @return string Html code snippet displaying the currently logged in user
329 */
330 protected function getLoggedInUserLabel() {
331 $css = 'toolbar-item';
332 $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-user-' . ($GLOBALS['BE_USER']->isAdmin() ? 'admin' : 'backend'));
333 $realName = $GLOBALS['BE_USER']->user['realName'];
334 $username = $GLOBALS['BE_USER']->user['username'];
335 $label = $realName ?: $username;
336 $title = $username;
337 // Link to user setup if it's loaded and user has access
338 $link = '';
339 if (ExtensionManagementUtility::isLoaded('setup') && $GLOBALS['BE_USER']->check('modules', 'user_setup')) {
340 $link = '<a href="#" onclick="top.goToModule(\'user_setup\'); this.blur(); return false;">';
341 }
342 // Superuser mode
343 if ($GLOBALS['BE_USER']->user['ses_backuserid']) {
344 $css .= ' su-user';
345 $title = $GLOBALS['LANG']->getLL('switchtouser') . ': ' . $username;
346 $label = $GLOBALS['LANG']->getLL('switchtousershort') . ' ' . ($realName ? $realName . ' (' . $username . ')' : $username);
347 }
348 return '<div id="username" class="' . $css . '">' . $link . $icon . '<span title="' . htmlspecialchars($title) . '">' . htmlspecialchars($label) . '</span>' . ($link ? '</a>' : '') . '</div>';
349 }
350
351 /**
352 * Returns the file name to the LLL JavaScript, containing the localized labels,
353 * which can be used in JavaScript code.
354 *
355 * @return string File name of the JS file, relative to TYPO3_mainDir
356 */
357 protected function getLocalLangFileName() {
358 $code = $this->generateLocalLang();
359 $filePath = 'typo3temp/locallang-BE-' . sha1($code) . '.js';
360 if (!file_exists((PATH_site . $filePath))) {
361 // writeFileToTypo3tempDir() returns NULL on success (please double-read!)
362 if (GeneralUtility::writeFileToTypo3tempDir(PATH_site . $filePath, $code) !== NULL) {
363 throw new \RuntimeException('LocalLangFile could not be written to ' . $filePath, 1295193026);
364 }
365 }
366 return '../' . $filePath;
367 }
368
369 /**
370 * Reads labels required in JavaScript code from the localization system and returns them as JSON
371 * array in TYPO3.LLL.
372 *
373 * @return string JavaScript code containing the LLL labels in TYPO3.LLL
374 */
375 protected function generateLocalLang() {
376 $coreLabels = array(
377 'waitTitle' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_logging_in'),
378 'refresh_login_failed' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_failed'),
379 'refresh_login_failed_message' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_failed_message'),
380 'refresh_login_title' => sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_title'), htmlspecialchars($GLOBALS['BE_USER']->user['username'])),
381 'login_expired' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_expired'),
382 'refresh_login_username' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_username'),
383 'refresh_login_password' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_password'),
384 'refresh_login_emptyPassword' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_emptyPassword'),
385 'refresh_login_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_button'),
386 'refresh_logout_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_logout_button'),
387 'please_wait' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.please_wait'),
388 'loadingIndicator' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:loadingIndicator'),
389 'be_locked' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.be_locked'),
390 'refresh_login_countdown_singular' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_countdown_singular'),
391 'refresh_login_countdown' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_countdown'),
392 'login_about_to_expire' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_about_to_expire'),
393 'login_about_to_expire_title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.login_about_to_expire_title'),
394 'refresh_login_refresh_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_login_refresh_button'),
395 'refresh_direct_logout_button' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.refresh_direct_logout_button'),
396 'tabs_closeAll' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.closeAll'),
397 'tabs_closeOther' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.closeOther'),
398 'tabs_close' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.close'),
399 'tabs_openInBrowserWindow' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tabs.openInBrowserWindow'),
400 'csh_tooltip_loading' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:csh_tooltip_loading')
401 );
402 $labels = array(
403 'fileUpload' => array(
404 'windowTitle',
405 'buttonSelectFiles',
406 'buttonCancelAll',
407 'infoComponentMaxFileSize',
408 'infoComponentFileUploadLimit',
409 'infoComponentFileTypeLimit',
410 'infoComponentOverrideFiles',
411 'processRunning',
412 'uploadWait',
413 'uploadStarting',
414 'uploadProgress',
415 'uploadSuccess',
416 'errorQueueLimitExceeded',
417 'errorQueueFileSizeLimit',
418 'errorQueueZeroByteFile',
419 'errorQueueInvalidFiletype',
420 'errorUploadHttp',
421 'errorUploadMissingUrl',
422 'errorUploadIO',
423 'errorUploadSecurityError',
424 'errorUploadLimit',
425 'errorUploadFailed',
426 'errorUploadFileIDNotFound',
427 'errorUploadFileValidation',
428 'errorUploadFileCancelled',
429 'errorUploadStopped',
430 'allErrorMessageTitle',
431 'allErrorMessageText',
432 'allError401',
433 'allError2038'
434 ),
435 'liveSearch' => array(
436 'title',
437 'helpTitle',
438 'emptyText',
439 'loadingText',
440 'listEmptyText',
441 'showAllResults',
442 'helpDescription',
443 'helpDescriptionPages',
444 'helpDescriptionContent'
445 ),
446 'viewPort' => array(
447 'tooltipModuleMenuSplit',
448 'tooltipNavigationContainerSplitDrag',
449 'tooltipDebugPanelSplitDrag'
450 )
451 );
452 $generatedLabels = array();
453 $generatedLabels['core'] = $coreLabels;
454 // First loop over all categories (fileUpload, liveSearch, ..)
455 foreach ($labels as $categoryName => $categoryLabels) {
456 // Then loop over every single label
457 foreach ($categoryLabels as $label) {
458 // LLL identifier must be called $categoryName_$label, e.g. liveSearch_loadingText
459 $generatedLabels[$categoryName][$label] = $GLOBALS['LANG']->getLL($categoryName . '_' . $label);
460 }
461 }
462 return 'TYPO3.LLL = ' . json_encode($generatedLabels) . ';';
463 }
464
465 /**
466 * Generates the JavaScript code for the backend.
467 *
468 * @return void
469 */
470 protected function generateJavascript() {
471 $pathTYPO3 = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/';
472 // If another page module was specified, replace the default Page module with the new one
473 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
474 $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
475 if (!$GLOBALS['BE_USER']->check('modules', $pageModule)) {
476 $pageModule = '';
477 }
478 $menuFrameName = 'menu';
479 if ($GLOBALS['BE_USER']->uc['noMenuMode'] === 'icons') {
480 $menuFrameName = 'topmenuFrame';
481 }
482 // Determine security level from conf vars and default to super challenged
483 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) {
484 $this->loginSecurityLevel = $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'];
485 } else {
486 $this->loginSecurityLevel = 'superchallenged';
487 }
488 $t3Configuration = array(
489 'siteUrl' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL'),
490 'PATH_typo3' => $pathTYPO3,
491 'PATH_typo3_enc' => rawurlencode($pathTYPO3),
492 'username' => htmlspecialchars($GLOBALS['BE_USER']->user['username']),
493 'uniqueID' => GeneralUtility::shortMD5(uniqid('')),
494 'securityLevel' => $this->loginSecurityLevel,
495 'TYPO3_mainDir' => TYPO3_mainDir,
496 'pageModule' => $pageModule,
497 'inWorkspace' => $GLOBALS['BE_USER']->workspace !== 0 ? 1 : 0,
498 'workspaceFrontendPreviewEnabled' => $GLOBALS['BE_USER']->user['workspace_preview'] ? 1 : 0,
499 'veriCode' => $GLOBALS['BE_USER']->veriCode(),
500 'denyFileTypes' => PHP_EXTENSIONS_DEFAULT,
501 'moduleMenuWidth' => $this->menuWidth - 1,
502 'topBarHeight' => isset($GLOBALS['TBE_STYLES']['dims']['topFrameH']) ? (int)$GLOBALS['TBE_STYLES']['dims']['topFrameH'] : 30,
503 'showRefreshLoginPopup' => isset($GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup']) ? (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup'] : FALSE,
504 'listModulePath' => ExtensionManagementUtility::isLoaded('recordlist') ? ExtensionManagementUtility::extRelPath('recordlist') . 'mod1/' : '',
505 'debugInWindow' => $GLOBALS['BE_USER']->uc['debugInWindow'] ? 1 : 0,
506 'ContextHelpWindows' => array(
507 'width' => 600,
508 'height' => 400
509 ),
510 );
511 $this->js .= '
512 TYPO3.configuration = ' . json_encode($t3Configuration) . ';
513
514 /**
515 * TypoSetup object.
516 */
517 function typoSetup() { //
518 this.PATH_typo3 = TYPO3.configuration.PATH_typo3;
519 this.PATH_typo3_enc = TYPO3.configuration.PATH_typo3_enc;
520 this.username = TYPO3.configuration.username;
521 this.uniqueID = TYPO3.configuration.uniqueID;
522 this.navFrameWidth = 0;
523 this.securityLevel = TYPO3.configuration.securityLevel;
524 this.veriCode = TYPO3.configuration.veriCode;
525 this.denyFileTypes = TYPO3.configuration.denyFileTypes;
526 }
527 var TS = new typoSetup();
528 //backwards compatibility
529 /**
530 * Frameset Module object
531 *
532 * Used in main modules with a frameset for submodules to keep the ID between modules
533 * Typically that is set by something like this in a Web>* sub module:
534 * if (top.fsMod) top.fsMod.recentIds["web"] = "\'.(int)$this->id.\'";
535 * if (top.fsMod) top.fsMod.recentIds["file"] = "...(file reference/string)...";
536 */
537 function fsModules() { //
538 this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
539 this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
540 this.currentMainLoaded="";
541 this.currentBank="0";
542 }
543 var fsMod = new fsModules();
544
545 top.goToModule = function(modName, cMR_flag, addGetVars) {
546 TYPO3.ModuleMenu.App.showModule(modName, addGetVars);
547 }
548 ' . $this->setStartupModule();
549 // Check editing of page:
550 $this->handlePageEditing();
551 }
552
553 /**
554 * Checking if the "&edit" variable was sent so we can open it for editing the page.
555 *
556 * @return void
557 */
558 protected function handlePageEditing() {
559 if (!ExtensionManagementUtility::isLoaded('cms')) {
560 return;
561 }
562 // EDIT page:
563 $editId = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('edit'));
564 $editRecord = '';
565 if ($editId) {
566 // Looking up the page to edit, checking permissions:
567 $where = ' AND (' . $GLOBALS['BE_USER']->getPagePermsClause(2) . ' OR ' . $GLOBALS['BE_USER']->getPagePermsClause(16) . ')';
568 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($editId)) {
569 $editRecord = BackendUtility::getRecordWSOL('pages', $editId, '*', $where);
570 } else {
571 $records = BackendUtility::getRecordsByField('pages', 'alias', $editId, $where);
572 if (is_array($records)) {
573 $editRecord = reset($records);
574 BackendUtility::workspaceOL('pages', $editRecord);
575 }
576 }
577 // If the page was accessible, then let the user edit it.
578 if (is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) {
579 // Setting JS code to open editing:
580 $this->js .= '
581 // Load page to edit:
582 window.setTimeout("top.loadEditId(' . (int)$editRecord['uid'] . ');", 500);
583 ';
584 // Checking page edit parameter:
585 if (!$GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) {
586 $bookmarkKeepExpanded = $GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded');
587 // Expanding page tree:
588 BackendUtility::openPageTree((int)$editRecord['pid'], !$bookmarkKeepExpanded);
589 }
590 } else {
591 $this->js .= '
592 // Warning about page editing:
593 alert(' . GeneralUtility::quoteJSvalue(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)) . ');
594 ';
595 }
596 }
597 }
598
599 /**
600 * Sets the startup module from either GETvars module and modParams or user configuration.
601 *
602 * @return string the JavaScript code for the startup module
603 */
604 protected function setStartupModule() {
605 $startModule = preg_replace('/[^[:alnum:]_]/', '', GeneralUtility::_GET('module'));
606 if (!$startModule) {
607 // start module on first login, will be removed once used the first time
608 if (isset($GLOBALS['BE_USER']->uc['startModuleOnFirstLogin'])) {
609 $startModule = $GLOBALS['BE_USER']->uc['startModuleOnFirstLogin'];
610 unset($GLOBALS['BE_USER']->uc['startModuleOnFirstLogin']);
611 $GLOBALS['BE_USER']->writeUC();
612 } elseif ($GLOBALS['BE_USER']->uc['startModule']) {
613 $startModule = $GLOBALS['BE_USER']->uc['startModule'];
614 } elseif ($GLOBALS['BE_USER']->uc['startInTaskCenter']) {
615 $startModule = 'user_task';
616 }
617
618 // check if the start module has additional parameters, so a redirect to a specific
619 // action is possible
620 if (strpos($startModule, '->') !== FALSE) {
621 list($startModule, $startModuleParameters) = explode('->', $startModule, 2);
622 }
623 }
624
625 $moduleParameters = GeneralUtility::_GET('modParams');
626 // if no GET parameters are set, check if there are parameters given from the UC
627 if (!$moduleParameters && $startModuleParameters) {
628 $moduleParameters = $startModuleParameters;
629 }
630
631 if ($startModule) {
632 return '
633 // start in module:
634 top.startInModule = [\'' . $startModule . '\', ' . GeneralUtility::quoteJSvalue($moduleParameters) . '];
635 ';
636 } else {
637 return '';
638 }
639 }
640
641 /**
642 * Adds a javascript snippet to the backend
643 *
644 * @param string $javascript Javascript snippet
645 * @return void
646 * @throws \InvalidArgumentException
647 */
648 public function addJavascript($javascript) {
649 // TODO do we need more checks?
650 if (!is_string($javascript)) {
651 throw new \InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
652 }
653 $this->js .= $javascript;
654 }
655
656 /**
657 * Adds a javscript file to the backend after it has been checked that it exists
658 *
659 * @param string $javascriptFile Javascript file reference
660 * @return boolean TRUE if the javascript file was successfully added, FALSE otherwise
661 */
662 public function addJavascriptFile($javascriptFile) {
663 $jsFileAdded = FALSE;
664 //TODO add more checks if necessary
665 if (file_exists(GeneralUtility::resolveBackPath(PATH_typo3 . $javascriptFile))) {
666 $this->jsFiles[] = $javascriptFile;
667 $jsFileAdded = TRUE;
668 }
669 return $jsFileAdded;
670 }
671
672 /**
673 * Adds a css snippet to the backend
674 *
675 * @param string $css Css snippet
676 * @return void
677 */
678 public function addCss($css) {
679 if (!is_string($css)) {
680 throw new \InvalidArgumentException('parameter $css must be of type string', 1195129642);
681 }
682 $this->css .= $css;
683 }
684
685 /**
686 * Adds a css file to the backend after it has been checked that it exists
687 *
688 * @param string $cssFileName The css file's name with out the .css ending
689 * @param string $cssFile Css file reference
690 * @return boolean TRUE if the css file was added, FALSE otherwise
691 */
692 public function addCssFile($cssFileName, $cssFile) {
693 $cssFileAdded = FALSE;
694 if (empty($this->cssFiles[$cssFileName])) {
695 $this->cssFiles[$cssFileName] = $cssFile;
696 $cssFileAdded = TRUE;
697 }
698 return $cssFileAdded;
699 }
700
701 /**
702 * Adds an item to the toolbar, the class file for the toolbar item must be loaded at this point
703 *
704 * @param string $toolbarItemName Toolbar item name, f.e. tx_toolbarExtension_coolItem
705 * @param string $toolbarItemClassName Toolbar item class name, f.e. tx_toolbarExtension_coolItem
706 * @return void
707 * @throws \UnexpectedValueException
708 */
709 public function addToolbarItem($toolbarItemName, $toolbarItemClassName) {
710 $toolbarItem = GeneralUtility::makeInstance($toolbarItemClassName, $this);
711 if (!$toolbarItem instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemHookInterface) {
712 throw new \UnexpectedValueException('$toolbarItem "' . $toolbarItemName . '" must implement interface TYPO3\\CMS\\Backend\\Toolbar\\ToolbarItemHookInterface', 1195125501);
713 }
714 if ($toolbarItem->checkAccess()) {
715 $this->toolbarItems[$toolbarItemName] = $toolbarItem;
716 } else {
717 unset($toolbarItem);
718 }
719 }
720
721 /**
722 * Executes defined hooks functions for the given identifier.
723 *
724 * These hook identifiers are valid:
725 * + constructPostProcess
726 * + renderPreProcess
727 * + renderPostProcess
728 *
729 * @param string $identifier Specific hook identifier
730 * @param array $hookConfiguration Additional configuration passed to hook functions
731 * @return void
732 */
733 protected function executeHook($identifier, array $hookConfiguration = array()) {
734 $options = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php'];
735 if (isset($options[$identifier]) && is_array($options[$identifier])) {
736 foreach ($options[$identifier] as $hookFunction) {
737 GeneralUtility::callUserFunction($hookFunction, $hookConfiguration, $this);
738 }
739 }
740 }
741
742 }