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