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