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