fixed: backend.php closed body and html elements twice
[Packages/TYPO3.CMS.git] / typo3 / backend.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2007 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
35 // core toolbar items
36 require('classes/class.workspaceselector.php');
37 require('classes/class.clearcachemenu.php');
38 require('classes/class.shortcutmenu.php');
39 require('classes/class.backendsearchmenu.php');
40
41 require_once(PATH_t3lib.'class.t3lib_loadmodules.php');
42 require_once(PATH_t3lib.'class.t3lib_basicfilefunc.php');
43 require_once('class.alt_menu_functions.inc');
44 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_misc.xml');
45
46
47 /**
48 * Class for rendering the TYPO3 backend version 4.2+
49 *
50 * @author Ingo Renner <ingo@typo3.org>
51 * @package TYPO3
52 * @subpackage core
53 */
54 class TYPO3backend {
55
56 private $content;
57 private $css;
58 private $cssFiles;
59 private $js;
60 private $jsFiles;
61
62 /**
63 * Object for loading backend modules
64 *
65 * @var t3lib_loadModules
66 */
67 private $moduleLoader;
68
69 /**
70 * module menu generating object
71 *
72 * @var ModuleMenu
73 */
74 private $moduleMenu;
75
76 private $leftMenuWidth;
77 private $topHeight;
78 private $selectMenu;
79 private $toolbarItems;
80
81 /**
82 * constructor
83 *
84 * @return void
85 */
86 public function __construct() {
87 // Initializes the backend modules structure for use later.
88 $this->moduleLoader = t3lib_div::makeInstance('t3lib_loadModules');
89 $this->moduleLoader->load($GLOBALS['TBE_MODULES']);
90
91 $this->moduleMenu = t3lib_div::makeInstance('ModuleMenu');
92
93 // Check for distances defined in the styles array:
94 if ($TBE_STYLES['dims']['leftMenuFrameW']) {
95 $this->leftMenuWidth = $TBE_STYLES['dims']['leftMenuFrameW'];
96 }
97 if ($TBE_STYLES['dims']['topFrameH']) {
98 $this->topHeight = $TBE_STYLES['dims']['topFrameH'];
99 }
100 if ($TBE_STYLES['dims']['selMenuFrame']) {
101 $this->selectMenu = $TBE_STYLES['dims']['selMenuFrame'];
102 }
103
104 // add default BE javascript
105 $this->js = '';
106 $this->jsFiles = array(
107 'contrib/prototype/prototype.js',
108 'contrib/scriptaculous/scriptaculous.js?load=builder,effects,controls,dragdrop',
109 'md5.js',
110 'js/backend.js',
111 'js/common.js',
112 'js/sizemanager.js',
113 'js/toolbarmanager.js',
114 'js/modulemenu.js',
115 '../t3lib/jsfunc.evalfield.js'
116 );
117
118 // add default BE css
119 $this->css = '';
120 $this->cssFiles = array(
121 'backend-scaffolding' => 'css/backend-scaffolding.css',
122 'backend-style' => 'css/backend-style.css',
123 'modulemenu' => 'css/modulemenu.css'
124 );
125
126 $this->toolbarItems = array();
127 $this->initializeCoreToolbarItems();
128 }
129
130 /**
131 * initializes the core toolbar items
132 *
133 * @return void
134 */
135 private function initializeCoreToolbarItems() {
136
137 $coreToolbarItems = array(
138 'workspaceSelector' => 'WorkspaceSelector',
139 'clearCacheActions' => 'ClearCacheMenu',
140 'shortcuts' => 'ShortcutMenu',
141 'backendSearch' => 'BackendSearchMenu'
142 );
143
144 foreach($coreToolbarItems as $toolbarItemName => $toolbarItemClass) {
145 $toolbarItem = t3lib_div::makeInstance($toolbarItemClass);
146
147 if(!($toolbarItem instanceof backend_toolbarItem)) {
148 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195126772);
149 }
150
151 $toolbarItem->setBackend($this);
152 $this->toolbarItems[$toolbarItemName] = $toolbarItem;
153 }
154 }
155
156 /**
157 * main function generating the BE scaffolding
158 *
159 * @return void
160 */
161 public function render() {
162
163 // prepare the scaffolding, at this point extension may still add javascript and css
164 $logo = t3lib_div::makeInstance('TYPO3Logo');
165 $logo->setLogo('gfx/typo3logo_mini.png');
166
167 $menu = $this->moduleMenu->render();
168
169
170 // create backend scaffolding
171 $backendScaffolding = '
172 <div id="typo3-backend">
173 <div id="typo3-top-container">
174 <div id="typo3-logo">'.$logo->render().'</div>
175 <div id="typo3-top" class="typo3-top-toolbar">'
176 .$this->renderToolbar()
177 .'</div>
178 </div>
179 <div id="typo3-main-container">
180 <div id="typo3-side-menu">
181 '.$menu.'
182 </div>
183 <div id="typo3-content">
184 <iframe src="alt_intro.php" name="content" id="content" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" noresize="noresize"></iframe>
185 </div>
186 </div>
187 </div>
188 ';
189
190 /******************************************************
191 * now put the complete backend document together
192 ******************************************************/
193
194 // set doctype
195 $GLOBALS['TBE_TEMPLATE']->docType = 'xhtml_trans';
196
197 // add javascript
198 foreach($this->jsFiles as $jsFile) {
199 $GLOBALS['TBE_TEMPLATE']->JScode .= '
200 <script type="text/javascript" src="'.$jsFile.'"></script>';
201 }
202 $GLOBALS['TBE_TEMPLATE']->JScode .= chr(10);
203 $this->generateJavascript();
204 $GLOBALS['TBE_TEMPLATE']->JScode .= $GLOBALS['TBE_TEMPLATE']->wrapScriptTags($this->js);
205
206 // FIXME abusing the JS container to add CSS, need to fix template.php
207 foreach($this->cssFiles as $cssFileName => $cssFile) {
208 $GLOBALS['TBE_TEMPLATE']->JScode .= '
209 <link rel="stylesheet" type="text/css" href="'.$cssFile.'" />
210 ';
211
212 // load addditional css files to overwrite existing core styles
213 if(!empty($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName])) {
214 $GLOBALS['TBE_TEMPLATE']->JScode .= '
215 <link rel="stylesheet" type="text/css" href="'.$GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName].'" />
216 ';
217 }
218 }
219
220 if(!empty($this->css)) {
221 $GLOBALS['TBE_TEMPLATE']->JScode .= '
222 <style type="text/css" id="internalStyle">
223 '.$this->css.'
224 </style>';
225 }
226
227 // set document title
228 $title = $TYPO3_CONF_VARS['SYS']['sitename'] ?
229 $TYPO3_CONF_VARS['SYS']['sitename'].' [TYPO3 '.TYPO3_version.']'
230 : 'TYPO3 '.TYPO3_version;
231
232 // start page header:
233 $this->content .= $GLOBALS['TBE_TEMPLATE']->startPage($title);
234 $this->content .= $backendScaffolding;
235 $this->content .= $GLOBALS['TBE_TEMPLATE']->endPage();
236
237 echo $this->content;
238 }
239
240 /**
241 * renders the items in the top toolbar
242 *
243 * @return string top toolbar elements as HTML
244 */
245 private function renderToolbar() {
246 $toolbar = '<ul id="typo3-toolbar">';
247 $toolbar.= '<li>'.$this->getLoggedInUserLabel().'</li>
248 <li><div id="logout-button" class="toolbar-item no-separator">'.$this->moduleMenu->renderLogoutButton().'</div></li>';
249
250 foreach($this->toolbarItems as $toolbarItem) {
251 $additionalAttributes = $toolbarItem->getAdditionalAttributes();
252
253 $toolbar .= '<li'.$additionalAttributes.'>'.$toolbarItem->render().'</li>';
254 }
255
256 return $toolbar.'</ul>';
257 }
258
259 /**
260 * gets the label of the currently loged in BE user
261 *
262 * @return string html code snippet displaying the currently logged in user
263 */
264 private function getLoggedInUserLabel() {
265 global $BE_USER, $BACK_PATH;
266
267 $icon = '<img'.t3lib_iconWorks::skinImg(
268 '',
269 $BE_USER->isAdmin() ?
270 'gfx/i/be_users_admin.gif' :
271 'gfx/i/be_users.gif',
272 'width="18" height="16"'
273 )
274 .' title="" alt="" />';
275
276 $label = $GLOBALS['BE_USER']->user['realName'] ?
277 $BE_USER->user['realName'].' ['.$BE_USER->user['username'].']' :
278 '['.$BE_USER->user['username'].']';
279
280 // Link to user setup if it's loaded and user has access
281 $link = '';
282 if (t3lib_extMgm::isLoaded('setup') && $BE_USER->check('modules','user_setup')) {
283 $link = '<a href="#" onclick="top.goToModule(\'user_setup\');this.blur();return false;">';
284 }
285
286 $username = '">'.$link.$icon.'<span>'.htmlspecialchars($label).'</span>'.($link?'</a>':'');
287
288 // superuser mode
289 if($BE_USER->user['ses_backuserid']) {
290 $username = ' su-user">SU: '.$icon.'<span>'.htmlspecialchars($label).'</span>';
291 }
292
293 return '<div id="username" class="toolbar-item no-separator'.$username.'</div>';
294 }
295
296 /**
297 * Generates the JavaScript code for the backend.
298 *
299 * @return void
300 */
301 private function generateJavascript() {
302
303 $pathTYPO3 = t3lib_div::dirname(t3lib_div::getIndpEnv('SCRIPT_NAME')).'/';
304 $goToModuleSwitch = $this->moduleMenu->getGotoModuleJavascript();
305 $moduleFramesHelper = implode(chr(10), $this->moduleMenu->getFsMod());
306
307 // If another page module was specified, replace the default Page module with the new one
308 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
309 $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
310
311 $menuFrameName = 'menu';
312 if($GLOBALS['BE_USER']->uc['noMenuMode'] === 'icons') {
313 $menuFrameName = 'topmenuFrame';
314 }
315
316 $this->js .= '
317 /**
318 * Function similar to PHPs rawurlencode();
319 */
320 function rawurlencode(str) { //
321 var output = escape(str);
322 output = str_replace("*","%2A", output);
323 output = str_replace("+","%2B", output);
324 output = str_replace("/","%2F", output);
325 output = str_replace("@","%40", output);
326 return output;
327 }
328
329 /**
330 * String-replace function
331 */
332 function str_replace(match,replace,string) { //
333 var input = ""+string;
334 var matchStr = ""+match;
335 if (!matchStr) {return string;}
336 var output = "";
337 var pointer=0;
338 var pos = input.indexOf(matchStr);
339 while (pos!=-1) {
340 output+=""+input.substr(pointer, pos-pointer)+replace;
341 pointer=pos+matchStr.length;
342 pos = input.indexOf(match,pos+1);
343 }
344 output+=""+input.substr(pointer);
345 return output;
346 }
347
348 /**
349 * TypoSetup object.
350 */
351 function typoSetup() { //
352 this.PATH_typo3 = "'.$pathTYPO3.'";
353 this.PATH_typo3_enc = "'.rawurlencode($pathTYPO3).'";
354 this.username = "'.$GLOBALS['BE_USER']->user['username'].'";
355 this.uniqueID = "'.t3lib_div::shortMD5(uniqid('')).'";
356 this.navFrameWidth = 0;
357 }
358 var TS = new typoSetup();
359
360 /**
361 * Functions for session-expiry detection:
362 */
363 function busy() { //
364 this.loginRefreshed = busy_loginRefreshed;
365 this.checkLoginTimeout = busy_checkLoginTimeout;
366 this.openRefreshWindow = busy_OpenRefreshWindow;
367 this.busyloadTime=0;
368 this.openRefreshW=0;
369 this.reloginCancelled=0;
370 }
371 function busy_loginRefreshed() { //
372 var date = new Date();
373 this.busyloadTime = Math.floor(date.getTime()/1000);
374 this.openRefreshW=0;
375 }
376 function busy_checkLoginTimeout() { //
377 var date = new Date();
378 var theTime = Math.floor(date.getTime()/1000);
379 if (theTime > this.busyloadTime+'.intval($GLOBALS['BE_USER']->auth_timeout_field).'-30) {
380 return true;
381 }
382 }
383 function busy_OpenRefreshWindow() { //
384 vHWin=window.open("login_frameset.php","relogin_"+TS.uniqueID,"height=350,width=700,status=0,menubar=0,location=1");
385 vHWin.focus();
386 this.openRefreshW=1;
387 }
388 function busy_checkLoginTimeout_timer() { //
389 if (busy.checkLoginTimeout() && !busy.reloginCancelled && !busy.openRefreshW) {
390 if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.refresh_login')).')) {
391 busy.openRefreshWindow();
392 } else {
393 busy.reloginCancelled = 1;
394 }
395 }
396 window.setTimeout("busy_checkLoginTimeout_timer();",2*1000); // Each 2nd second is enough for checking. The popup will be triggered 10 seconds before the login expires (see above, busy_checkLoginTimeout())
397
398 // Detecting the frameset module navigation frame widths (do this AFTER setting new timeout so that any errors in the code below does not prevent another time to be set!)
399 if (top && top.content && top.content.nav_frame && top.content.nav_frame.document && top.content.nav_frame.document.body) {
400 TS.navFrameWidth = (top.content.nav_frame.document.documentElement && top.content.nav_frame.document.documentElement.clientWidth) ? top.content.nav_frame.document.documentElement.clientWidth : top.content.nav_frame.document.body.clientWidth;
401 }
402 }
403
404 /**
405 * Launcing information window for records/files (fileref as "table" argument)
406 */
407 function launchView(table,uid,bP) { //
408 var backPath= bP ? bP : "";
409 var thePreviewWindow="";
410 thePreviewWindow = window.open(TS.PATH_typo3+"show_item.php?table="+encodeURIComponent(table)+"&uid="+encodeURIComponent(uid),"ShowItem"+TS.uniqueID,"height=400,width=550,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
411 if (thePreviewWindow && thePreviewWindow.focus) {
412 thePreviewWindow.focus();
413 }
414 }
415
416 /**
417 * Opens plain window with url
418 */
419 function openUrlInWindow(url,windowName) { //
420 regularWindow = window.open(url,windowName,"status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1");
421 regularWindow.focus();
422 return false;
423 }
424
425 /**
426 * Loads a URL in the topmenuFrame
427 */
428 function loadTopMenu(url) { //
429 top.topmenuFrame.location = url;
430 }
431
432 /**
433 * Loads a page id for editing in the page edit module:
434 */
435 function loadEditId(id,addGetVars) { //
436 top.fsMod.recentIds["web"]=id;
437 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_0"; // For highlighting
438
439 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
440 top.content.nav_frame.refresh_nav();
441 }
442
443 top.goToModule("'.$pageModule.'", 0, addGetVars?addGetVars:"");
444 }
445
446 /**
447 * Returns incoming URL (to a module) unless nextLoadModuleUrl is set. If that is the case nextLoadModuleUrl is returned (and cleared)
448 * Used by the shortcut frame to set a "intermediate URL"
449 */
450 var nextLoadModuleUrl="";
451 function getModuleUrl(inUrl) { //
452 var nMU;
453 if (top.nextLoadModuleUrl) {
454 nMU=top.nextLoadModuleUrl;
455 top.nextLoadModuleUrl="";
456 return nMU;
457 } else {
458 return inUrl;
459 }
460 }
461
462 /**
463 * Print properties of an object
464 */
465 function debugObj(obj,name) { //
466 var acc;
467 for (i in obj) {
468 if (obj[i]) {
469 acc+=i+": "+obj[i]+"\n";
470 }
471 }
472 alert("Object: "+name+"\n\n"+acc);
473 }
474
475 /**
476 * Initialize login expiration warning object
477 */
478 var busy = new busy();
479 busy.loginRefreshed();
480 busy_checkLoginTimeout_timer();
481
482 /**
483 * Function used to switch modules
484 */
485 var currentModuleLoaded = "";
486 var goToModule = '.$goToModuleSwitch.'
487
488 /**
489 * Frameset Module object
490 *
491 * Used in main modules with a frameset for submodules to keep the ID between modules
492 * Typically that is set by something like this in a Web>* sub module:
493 * if (top.fsMod) top.fsMod.recentIds["web"] = "\'.intval($this->id).\'";
494 * if (top.fsMod) top.fsMod.recentIds["file"] = "...(file reference/string)...";
495 */
496 function fsModules() { //
497 this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
498 this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
499 this.currentMainLoaded="";
500 this.currentBank="0";
501 }
502 var fsMod = new fsModules();
503 '.$moduleFramesHelper.'
504
505 // Used by Frameset Modules
506 var condensedMode = '.($GLOBALS['BE_USER']->uc['condensedMode']?1:0).';
507 var currentSubScript = "";
508 var currentSubNavScript = "";
509
510 // Used for tab-panels:
511 var DTM_currentTabs = new Array();
512 ';
513
514 // Check editing of page:
515 $this->handlePageEditing();
516 $this->setStartupModule();
517 }
518
519 /**
520 * Checking if the "&edit" variable was sent so we can open it for editing the page.
521 * Code based on code from "alt_shortcut.php"
522 *
523 * @return void
524 */
525 private function handlePageEditing() {
526
527 if(!t3lib_extMgm::isLoaded('cms')) {
528 return;
529 }
530
531 // EDIT page:
532 $editId = preg_replace('/[^[:alnum:]_]/', '', t3lib_div::_GET('edit'));
533 $editRecord = '';
534
535 if($editId) {
536
537 // Looking up the page to edit, checking permissions:
538 $where = ' AND ('.$GLOBALS['BE_USER']->getPagePermsClause(2)
539 .' OR '.$GLOBALS['BE_USER']->getPagePermsClause(16).')';
540
541 if(t3lib_div::testInt($editId)) {
542 $editRecord = t3lib_BEfunc::getRecordWSOL('pages', $editId, '*', $where);
543 } else {
544 $records = t3lib_BEfunc::getRecordsByField('pages', 'alias', $editId, $where);
545
546 if(is_array($records)) {
547 reset($records);
548 $editRecord = current($records);
549 t3lib_BEfunc::workspaceOL('pages', $editRecord);
550 }
551 }
552
553 // If the page was accessible, then let the user edit it.
554 if(is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) {
555 // Setting JS code to open editing:
556 $this->js .= '
557 // Load page to edit:
558 window.setTimeout("top.loadEditId('.intval($editRecord['uid']).');", 500);
559 ';
560 // Checking page edit parameter:
561 if(!$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_dontSetPageTree')) {
562
563 // Expanding page tree:
564 t3lib_BEfunc::openPageTree(intval($editRecord['pid']), !$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_keepExistingExpanded'));
565 }
566 } else {
567 $this->js .= '
568 // Warning about page editing:
569 alert('.$GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)).');
570 ';
571 }
572 }
573 }
574
575 /**
576 * Sets the startup module from either GETvars module and mpdParams or user configuration.
577 *
578 * @return void
579 */
580 private function setStartupModule() {
581 $startModule = preg_replace('/[^[:alnum:]_]/', '', t3lib_div::_GET('module'));
582
583 if(!$startModule) {
584 if ($GLOBALS['BE_USER']->uc['startModule']) {
585 $startModule = $GLOBALS['BE_USER']->uc['startModule'];
586 } else if($GLOBALS['BE_USER']->uc['startInTaskCenter']) {
587 $startModule = 'user_task';
588 }
589 }
590
591 $moduleParameters = t3lib_div::_GET('modParams');
592 if($startModule) {
593 $this->js .= '
594 // start in module:
595 function startInModule(modName, cMR_flag, addGetVars) {
596 Event.observe(document, \'dom:loaded\', function() {
597 top.goToModule(modName, cMR_flag, addGetVars);
598 });
599 }
600
601 startInModule(\''.$startModule.'\', false, \''.$moduleParameters.'\');
602 ';
603 }
604 }
605
606 /**
607 * generates the code for the TYPO3 logo, either the default TYPO3 logo or a custom one
608 *
609 * @return string HTML code snippet to display the TYPO3 logo
610 */
611 private function getLogo() {
612 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
613 '<img'.t3lib_iconWorks::skinImg('','gfx/alt_backend_logo.gif','width="117" height="32"').' title="TYPO3 Content Management Framework" alt="" />'.
614 '</a>';
615
616 // overwrite with custom logo
617 if($GLOBALS['TBE_STYLES']['logo']) {
618 if(substr($GLOBALS['TBE_STYLES']['logo'], 0, 3) == '../') {
619 $imgInfo = @getimagesize(PATH_site.substr($GLOBALS['TBE_STYLES']['logo'], 3));
620 }
621 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
622 '<img src="'.$GLOBALS['TBE_STYLES']['logo'].'" '.$imgInfo[3].' title="TYPO3 Content Management Framework" alt="" />'.
623 '</a>';
624 }
625
626 return $logo;
627 }
628
629 /**
630 * adds a javascript snippet to the backend
631 *
632 * @param string javascript snippet
633 * @return void
634 */
635 public function addJavascript($javascript) {
636 // TODO do we need more checks?
637 if(!is_string($javascript)) {
638 throw new InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
639 }
640
641 $this->js .= $javascript;
642 }
643
644 /**
645 * adds a javscript file to the backend after it has been checked that it exists
646 *
647 * @param string javascript file reference
648 * @return boolean true if the javascript file was successfully added, false otherwise
649 */
650 public function addJavascriptFile($javascriptFile) {
651 $jsFileAdded = false;
652
653 //TODO add more checks if neccessary
654 if(file_exists(t3lib_div::resolveBackPath(PATH_typo3.$javascriptFile))) {
655 $this->jsFiles[] = $javascriptFile;
656 $jsFileAdded = true;
657 }
658
659 return $jsFileAdded;
660 }
661
662 /**
663 * adds a css snippet to the backend
664 *
665 * @param string css snippet
666 * @return void
667 */
668 public function addCss($css) {
669 if(!is_string($css)) {
670 throw new InvalidArgumentException('parameter $css must be of type string', 1195129642);
671 }
672
673 $this->css .= $css;
674 }
675
676 /**
677 * adds a css file to the backend after it has been checked that it exists
678 *
679 * @param string the css file's name with out the .css ending
680 * @param string css file reference
681 * @return boolean true if the css file was added, false otherwise
682 */
683 public function addCssFile($cssFileName, $cssFile) {
684 $cssFileAdded = false;
685
686 //TODO add more checks if neccessary
687 if(file_exists(t3lib_div::resolveBackPath(PATH_typo3.$cssFile))) {
688 // prevent overwriting existing css files
689 if(empty($this->cssFiles[$cssFileName])) {
690 $this->cssFiles[$cssFileName] = $cssFile;
691 $cssFileAdded = true;
692 }
693 }
694
695 return $cssFileAdded;
696 }
697
698 /**
699 * adds an item to the toolbar
700 *
701 * @param string toolbar item class reference, f.e. EXT:toolbarextension/class.tx_toolbarextension_coolitem.php:tx_toolbarExtension_coolItem
702 * @param backend_toolbarItem object of an backend_toolbarItem implementation
703 * @return void
704 */
705 public function addToolbarItem($toolbarItemName, $toolbarItemClassReference) {
706 $toolbarItem = t3lib_div::getUserObj($toolbarItemClassReference);
707
708 if(!($toolbarItem instanceof backend_toolbarItem)) {
709 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195125501);
710 }
711
712 $toolbarItem->setBackend($this);
713 $this->toolbarItems[$toolbarItemName] = $toolbarItem;
714 }
715 }
716
717
718 // include XCLASS
719 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/backend.php']) {
720 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/backend.php']);
721 }
722
723
724 // document generation
725 $TYPO3backend = t3lib_div::makeInstance('TYPO3backend');
726
727 // include extensions which may add css, javascript or toolbar items
728 if(is_array($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'])) {
729 foreach($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'] as $additionalBackendItem) {
730 include_once($additionalBackendItem);
731 }
732 }
733
734 $TYPO3backend->render();
735
736 ?>