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