409a5ce4a0413f5ee11f603906aec5d92911fdb6
2 /***************************************************************
5 * (c) 2007 Ingo Renner <ingo@typo3.org>
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.
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.
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.
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
28 require_once('init.php');
29 require_once('template.php');
30 require_once('interfaces/interface.backend_toolbaritem.php');
32 require('classes/class.typo3logo.php');
33 require('classes/class.modulemenu.php');
36 require('classes/class.workspaceselector.php');
37 require('classes/class.clearcachemenu.php');
38 require('classes/class.shortcutmenu.php');
39 require('classes/class.backendsearchmenu.php');
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');
48 * Class for rendering the TYPO3 backend version 4.2+
50 * @author Ingo Renner <ingo@typo3.org>
62 * Object for loading backend modules
64 * @var t3lib_loadModules
66 private $moduleLoader;
69 * module menu generating object
75 private $leftMenuWidth;
78 private $toolbarItems;
85 public function __construct() {
86 // Initializes the backend modules structure for use later.
87 $this->moduleLoader
= t3lib_div
::makeInstance('t3lib_loadModules');
88 $this->moduleLoader
->load($GLOBALS['TBE_MODULES']);
90 $this->moduleMenu
= t3lib_div
::makeInstance('ModuleMenu');
92 // Check for distances defined in the styles array:
93 if ($TBE_STYLES['dims']['leftMenuFrameW']) {
94 $this->leftMenuWidth
= $TBE_STYLES['dims']['leftMenuFrameW'];
96 if ($TBE_STYLES['dims']['topFrameH']) {
97 $this->topHeight
= $TBE_STYLES['dims']['topFrameH'];
99 if ($TBE_STYLES['dims']['selMenuFrame']) {
100 $this->selectMenu
= $TBE_STYLES['dims']['selMenuFrame'];
103 // add default BE javascript
105 $this->jsFiles
= array(
106 'contrib/prototype/prototype.js',
107 'contrib/scriptaculous/scriptaculous.js?load=builder,effects,controls,dragdrop',
112 'js/toolbarmanager.js',
113 '../t3lib/jsfunc.evalfield.js'
116 // add default BE css
117 $this->cssFiles
= array(
118 'backend-scaffolding' => 'css/backend-scaffolding.css',
119 'backend-style' => 'css/backend-style.css',
120 'modulemenu' => 'css/modulemenu.css'
123 $this->toolbarItems
= array();
124 $this->initializeCoreToolbarItems();
128 * initializes the core toolbar items
132 private function initializeCoreToolbarItems() {
134 $coreToolbarItems = array(
135 'workspaceSelector' => 'WorkspaceSelector',
136 'clearCacheActions' => 'ClearCacheMenu',
137 'shortcuts' => 'ShortcutMenu',
138 'backendSearch' => 'BackendSearchMenu'
141 foreach($coreToolbarItems as $toolbarItemName => $toolbarItemClass) {
142 $toolbarItem = t3lib_div
::makeInstance($toolbarItemClass);
144 if(!($toolbarItem instanceof backend_toolbarItem
)) {
145 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195126772);
148 $toolbarItem->setBackend($this);
149 $this->toolbarItems
[$toolbarItemName] = $toolbarItem;
154 * main function generating the BE scaffolding
158 public function render() {
160 // prepare the scaffolding, at this point extension may still add javascript and css
161 $logo = t3lib_div
::makeInstance('TYPO3Logo');
162 $logo->setLogo('gfx/typo3logo_mini.png');
164 $menu = $this->moduleMenu
->render();
167 // create backend scaffolding
168 $backendScaffolding = '
169 <div id="typo3-backend">
170 <div id="typo3-top-container">
171 <div id="typo3-logo">'.$logo->render().'</div>
172 <div id="typo3-top" class="typo3-top-toolbar">'
173 .$this->renderToolbar()
176 <div id="typo3-main-container">
177 <div id="typo3-side-menu">
180 <div id="typo3-content">
181 <iframe src="alt_intro.php" name="content" id="content" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" noresize="noresize"></iframe>
188 /******************************************************
189 * now put the complete backend document together
190 ******************************************************/
193 $GLOBALS['TBE_TEMPLATE']->docType
= 'xhtml_trans';
196 foreach($this->jsFiles
as $jsFile) {
197 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
198 <script type="text/javascript" src="'.$jsFile.'"></script>';
200 $GLOBALS['TBE_TEMPLATE']->JScode
.= chr(10);
201 $this->generateJavascript();
202 $GLOBALS['TBE_TEMPLATE']->JScode
.= $GLOBALS['TBE_TEMPLATE']->wrapScriptTags($this->js
);
204 // abusing the JS container to add CSS
205 // TODO fix template.php
206 foreach($this->cssFiles
as $cssFileName => $cssFile) {
208 if(!empty($GLOBALS['TBE_STYLES'][$cssFileName])) {
209 $cssFile = $GLOBALS['TBE_STYLES'][$cssFileName];
212 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
213 <link rel="stylesheet" type="text/css" href="'.$cssFile.'" />
216 // TODO add CSS from $this->css
218 // set document title
219 $title = $TYPO3_CONF_VARS['SYS']['sitename'] ?
220 $TYPO3_CONF_VARS['SYS']['sitename'].' [TYPO3 '.TYPO3_version
.']'
221 : 'TYPO3 '.TYPO3_version
;
223 // start page header:
224 $this->content
.= $GLOBALS['TBE_TEMPLATE']->startPage($title);
225 $this->content
.= $GLOBALS['TBE_TEMPLATE']->endPage();
227 $this->content
.= $backendScaffolding;
233 * renders the items in the top toolbar
235 * @return string top toolbar elements as HTML
237 private function renderToolbar() {
238 $toolbar = '<ul id="typo3-toolbar">';
239 $toolbar.= '<li>'.$this->getLoggedInUserLabel().'</li>
240 <li><div id="logout-button" class="toolbar-item no-separator">'.$this->moduleMenu
->renderLogoutButton().'</div></li>';
242 foreach($this->toolbarItems
as $toolbarItem) {
243 $additionalAttributes = $toolbarItem->getAdditionalAttributes();
245 $toolbar .= '<li'.$additionalAttributes.'>'.$toolbarItem->render().'</li>';
248 return $toolbar.'</ul>';
252 * gets the label of the currently loged in BE user
254 * @return string html code snippet displaying the currently logged in user
256 private function getLoggedInUserLabel() {
257 $username = '<div id="username" class="toolbar-item no-separator">['.htmlspecialchars($GLOBALS['BE_USER']->user
['username']).']</div>';;
260 if($BE_USER->user
['ses_backuserid']) {
261 $username = '<div id="username" class="toolbar-item no-separator typo3-red-background">[SU: '.htmlspecialchars($GLOBALS['BE_USER']->user
['username']).']</div>';
268 * Generates the JavaScript code for the backend.
272 private function generateJavascript() {
274 $pathTYPO3 = t3lib_div
::dirname(t3lib_div
::getIndpEnv('SCRIPT_NAME')).'/';
275 $goToModuleSwitch = $this->moduleMenu
->getGotoModuleJavascript();
276 $moduleFramesHelper = implode(chr(10), $this->moduleMenu
->getFsMod());
278 // If another page module was specified, replace the default Page module with the new one
279 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
280 $pageModule = t3lib_BEfunc
::isModuleSetInTBE_MODULES($newPageModule) ?
$newPageModule : 'web_layout';
282 $menuFrameName = 'menu';
283 if($GLOBALS['BE_USER']->uc
['noMenuMode'] === 'icons') {
284 $menuFrameName = 'topmenuFrame';
289 * Function similar to PHPs rawurlencode();
291 function rawurlencode(str) { //
292 var output = escape(str);
293 output = str_replace("*","%2A", output);
294 output = str_replace("+","%2B", output);
295 output = str_replace("/","%2F", output);
296 output = str_replace("@","%40", output);
301 * String-replace function
303 function str_replace(match,replace,string) { //
304 var input = ""+string;
305 var matchStr = ""+match;
306 if (!matchStr) {return string;}
309 var pos = input.indexOf(matchStr);
311 output+=""+input.substr(pointer, pos-pointer)+replace;
312 pointer=pos+matchStr.length;
313 pos = input.indexOf(match,pos+1);
315 output+=""+input.substr(pointer);
322 function typoSetup() { //
323 this.PATH_typo3 = "'.$pathTYPO3.'";
324 this.PATH_typo3_enc = "'.rawurlencode($pathTYPO3).'";
325 this.username = "'.$GLOBALS['BE_USER']->user
['username'].'";
326 this.uniqueID = "'.t3lib_div
::shortMD5(uniqid('')).'";
327 this.navFrameWidth = 0;
329 var TS = new typoSetup();
332 * Functions for session-expiry detection:
335 this.loginRefreshed = busy_loginRefreshed;
336 this.checkLoginTimeout = busy_checkLoginTimeout;
337 this.openRefreshWindow = busy_OpenRefreshWindow;
340 this.reloginCancelled=0;
342 function busy_loginRefreshed() { //
343 var date = new Date();
344 this.busyloadTime = Math.floor(date.getTime()/1000);
347 function busy_checkLoginTimeout() { //
348 var date = new Date();
349 var theTime = Math.floor(date.getTime()/1000);
350 if (theTime > this.busyloadTime+'.intval($GLOBALS['BE_USER']->auth_timeout_field
).'-30) {
354 function busy_OpenRefreshWindow() { //
355 vHWin=window.open("login_frameset.php","relogin_"+TS.uniqueID,"height=350,width=700,status=0,menubar=0,location=1");
359 function busy_checkLoginTimeout_timer() { //
360 if (busy.checkLoginTimeout() && !busy.reloginCancelled && !busy.openRefreshW) {
361 if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.refresh_login')).')) {
362 busy.openRefreshWindow();
364 busy.reloginCancelled = 1;
367 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())
369 // 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!)
370 if (top && top.content && top.content.nav_frame && top.content.nav_frame.document && top.content.nav_frame.document.body) {
371 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;
376 * Launcing information window for records/files (fileref as "table" argument)
378 function launchView(table,uid,bP) { //
379 var backPath= bP ? bP : "";
380 var thePreviewWindow="";
381 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");
382 if (thePreviewWindow && thePreviewWindow.focus) {
383 thePreviewWindow.focus();
388 * Opens plain window with url
390 function openUrlInWindow(url,windowName) { //
391 regularWindow = window.open(url,windowName,"status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1");
392 regularWindow.focus();
397 * Loads a URL in the topmenuFrame
399 function loadTopMenu(url) { //
400 top.topmenuFrame.location = url;
404 * Loads a page id for editing in the page edit module:
406 function loadEditId(id,addGetVars) { //
407 top.fsMod.recentIds["web"]=id;
408 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_0"; // For highlighting
410 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
411 top.content.nav_frame.refresh_nav();
414 top.goToModule("'.$pageModule.'", 0, addGetVars?addGetVars:"");
418 * Returns incoming URL (to a module) unless nextLoadModuleUrl is set. If that is the case nextLoadModuleUrl is returned (and cleared)
419 * Used by the shortcut frame to set a "intermediate URL"
421 var nextLoadModuleUrl="";
422 function getModuleUrl(inUrl) { //
424 if (top.nextLoadModuleUrl) {
425 nMU=top.nextLoadModuleUrl;
426 top.nextLoadModuleUrl="";
434 * Print properties of an object
436 function debugObj(obj,name) { //
440 acc+=i+": "+obj[i]+"\n";
443 alert("Object: "+name+"\n\n"+acc);
447 * Initialize login expiration warning object
449 var busy = new busy();
450 busy.loginRefreshed();
451 busy_checkLoginTimeout_timer();
457 var currentlyHighLightedId = "";
458 var currentlyHighLighted_restoreValue = "";
459 var currentlyHighLightedMain = "";
460 function highlightModuleMenuItem(trId, mainModule) { //
461 currentlyHighLightedMain = mainModule;
462 // Get document object:
463 if (top.menu && top.menu.document) {
464 var docObj = top.menu.document;
465 var HLclass = mainModule ? "c-mainitem-HL" : "c-subitem-row-HL";
466 } else if (top.topmenuFrame && top.topmenuFrame.document) {
467 var docObj = top.topmenuFrame.document;
468 var HLclass = mainModule ? "c-mainitem-HL" : "c-subitem-HL";
473 if (currentlyHighLightedId && docObj.getElementById(currentlyHighLightedId)) {
474 docObj.getElementById(currentlyHighLightedId).attributes.getNamedItem("class").nodeValue = currentlyHighLighted_restoreValue;
477 currentlyHighLightedId = trId;
478 if (currentlyHighLightedId && docObj.getElementById(currentlyHighLightedId)) {
479 var classAttribObject = docObj.getElementById(currentlyHighLightedId).attributes.getNamedItem("class");
480 currentlyHighLighted_restoreValue = classAttribObject.nodeValue;
481 classAttribObject.nodeValue = HLclass;
487 * Function restoring previous selection in left menu after clearing cache
489 function restoreHighlightedModuleMenuItem() { //
490 if (currentlyHighLightedId) {
491 highlightModuleMenuItem(currentlyHighLightedId,currentlyHighLightedMain);
495 '.$goToModuleSwitch.'
498 * reloads the menu frame
500 function refreshMenu() {
501 top.'.$menuFrameName.'.location.href = top.'.$menuFrameName.'.document.URL
505 * Frameset Module object
507 * Used in main modules with a frameset for submodules to keep the ID between modules
508 * Typically that is set by something like this in a Web>* sub module:
509 * if (top.fsMod) top.fsMod.recentIds["web"] = "\'.intval($this->id).\'";
510 * if (top.fsMod) top.fsMod.recentIds["file"] = "...(file reference/string)...";
512 function fsModules() { //
513 this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
514 this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
515 this.currentMainLoaded="";
516 this.currentBank="0";
518 var fsMod = new fsModules();
519 '.$moduleFramesHelper.'
521 // Used by Frameset Modules
522 var condensedMode = '.($GLOBALS['BE_USER']->uc
['condensedMode']?
1:0).';
523 var currentSubScript = "";
524 var currentSubNavScript = "";
526 // Used for tab-panels:
527 var DTM_currentTabs = new Array();
530 // Check editing of page:
531 $this->handlePageEditing();
532 $this->setStartupModule();
536 * Checking if the "&edit" variable was sent so we can open it for editing the page.
537 * Code based on code from "alt_shortcut.php"
541 private function handlePageEditing() {
543 if(!t3lib_extMgm
::isLoaded('cms')) {
548 $editId = preg_replace('/[^[:alnum:]_]/', '', t3lib_div
::_GET('edit'));
553 // Looking up the page to edit, checking permissions:
554 $where = ' AND ('.$GLOBALS['BE_USER']->getPagePermsClause(2)
555 .' OR '.$GLOBALS['BE_USER']->getPagePermsClause(16).')';
557 if(t3lib_div
::testInt($editId)) {
558 $editRecord = t3lib_BEfunc
::getRecordWSOL('pages', $editId, '*', $where);
560 $records = t3lib_BEfunc
::getRecordsByField('pages', 'alias', $editId, $where);
562 if(is_array($records)) {
564 $editRecord = current($records);
565 t3lib_BEfunc
::workspaceOL('pages', $editRecord);
569 // If the page was accessible, then let the user edit it.
570 if(is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) {
571 // Setting JS code to open editing:
573 // Load page to edit:
574 window.setTimeout("top.loadEditId('.intval($editRecord['uid']).');", 500);
576 // Checking page edit parameter:
577 if(!$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_dontSetPageTree')) {
579 // Expanding page tree:
580 t3lib_BEfunc
::openPageTree(intval($editRecord['pid']), !$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_keepExistingExpanded'));
584 // Warning about page editing:
585 alert('.$GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)).');
592 * Sets the startup module from either GETvars module and mpdParams or user configuration.
596 private function setStartupModule() {
597 $startModule = preg_replace('/[^[:alnum:]_]/', '', t3lib_div
::_GET('module'));
600 if ($GLOBALS['BE_USER']->uc
['startModule']) {
601 $startModule = $GLOBALS['BE_USER']->uc
['startModule'];
602 } else if($GLOBALS['BE_USER']->uc
['startInTaskCenter']) {
603 $startModule = 'user_task';
607 $moduleParameters = t3lib_div
::_GET('modParams');
611 function startInModule(modName, cMR_flag, addGetVars) {
612 Event.observe(document, \'dom:loaded\', function() {
613 top.goToModule(modName, cMR_flag, addGetVars);
617 startInModule(\''.$startModule.'\', false, \''.$moduleParameters.'\');
623 * generates the code for the TYPO3 logo, either the default TYPO3 logo or a custom one
625 * @return string HTML code snippet to display the TYPO3 logo
627 private function getLogo() {
628 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
629 '<img'.t3lib_iconWorks
::skinImg('','gfx/alt_backend_logo.gif','width="117" height="32"').' title="TYPO3 Content Management Framework" alt="" />'.
632 // overwrite with custom logo
633 if($GLOBALS['TBE_STYLES']['logo']) {
634 if(substr($GLOBALS['TBE_STYLES']['logo'], 0, 3) == '../') {
635 $imgInfo = @getimagesize
(PATH_site
.substr($GLOBALS['TBE_STYLES']['logo'], 3));
637 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
638 '<img src="'.$GLOBALS['TBE_STYLES']['logo'].'" '.$imgInfo[3].' title="TYPO3 Content Management Framework" alt="" />'.
646 * adds a javascript snippet to the backend
648 * @param string javascript snippet
651 public function addJavascript($javascript) {
652 // TODO do we need more checks?
653 if(!is_string($javascript)) {
654 throw new InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
657 $this->js
.= $javascript;
661 * adds a javscript file to the backend after it has been checked that it exists
663 * @param string javascript file reference
664 * @return boolean true if the javascript file was successfully added, false otherwise
666 public function addJavascriptFile($javascriptFile) {
667 $jsFileAdded = false;
669 //TODO add more checks if neccessary
670 if(file_exists(t3lib_div
::resolveBackPath(PATH_site
.$javascriptFile))) {
672 if(t3lib_div
::isFirstPartOfStr($javascriptFile, 'typo3/')) {
673 $javascriptFile = substr($javascriptFile, 6); // make relative to typo3/
676 $this->jsFiles
[] = $javascriptFile;
684 * adds a css snippet to the backend
686 * @param string css snippet
689 public function addCss($css) {
690 if(!is_string($css)) {
691 throw new InvalidArgumentException('parameter $css must be of type string', 1195129642);
698 * adds a css file to the backend after it has been checked that it exists
700 * @param string the css file's name with out the .css ending
701 * @param string css file reference
702 * @return boolean true if the css file was added, false otherwise
704 public function addCssFile($cssFileName, $cssFile) {
705 $cssFileAdded = false;
707 //TODO add more checks if neccessary
708 if(file_exists(t3lib_div
::resolveBackPath(PATH_site
.$cssFile))) {
710 if(t3lib_div
::isFirstPartOfStr($cssFile, 'typo3/')) {
711 $cssFile = substr($cssFile, 6); // make relative to typo3/
714 // prevent overwriting existing css files
715 if(empty($this->cssFiles
[$cssFileName])) {
716 $this->cssFiles
[$cssFileName] = $cssFile;
717 $cssFileAdded = true;
721 return $cssFileAdded;
725 * adds an item to the toolbar
727 * @param string toolbar item class reference, f.e. EXT:toolbarextension/class.tx_toolbarextension_coolitem.php:tx_toolbarExtension_coolItem
728 * @param backend_toolbarItem object of an backend_toolbarItem implementation
731 public function addToolbarItem($toolbarItemName, $toolbarItemClassReference) {
732 $toolbarItem = t3lib_div
::getUserObj($toolbarItemClassReference);
734 if(!($toolbarItem instanceof backend_toolbarItem
)) {
735 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195125501);
738 $toolbarItem->setBackend($this);
739 $this->toolbarItems
[$toolbarItemName] = $toolbarItem;
745 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['typo3/backend.php']) {
746 include_once($TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['typo3/backend.php']);
750 // document generation
751 $TYPO3backend = t3lib_div
::makeInstance('TYPO3backend');
753 // include extensions which may add css, javascript or toolbar items
754 if(is_array($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'])) {
755 foreach($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'] as $additionalBackendItem) {
756 include_once($additionalBackendItem);
760 $TYPO3backend->render();