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>
61 private $toolbarItems;
64 * Object for loading backend modules
66 * @var t3lib_loadModules
68 private $moduleLoader;
71 * module menu generating object
82 public function __construct() {
83 // Initializes the backend modules structure for use later.
84 $this->moduleLoader
= t3lib_div
::makeInstance('t3lib_loadModules');
85 $this->moduleLoader
->load($GLOBALS['TBE_MODULES']);
87 $this->moduleMenu
= t3lib_div
::makeInstance('ModuleMenu');
89 // add default BE javascript
91 $this->jsFiles
= array(
92 'contrib/prototype/prototype.js',
93 'contrib/scriptaculous/scriptaculous.js?load=builder,effects,controls,dragdrop',
98 'js/toolbarmanager.js',
100 'js/iecompatibility.js',
101 '../t3lib/jsfunc.evalfield.js'
104 // add default BE css
106 $this->cssFiles
= array(
107 'backend-scaffolding' => 'css/backend-scaffolding.css',
108 'backend-style' => 'css/backend-style.css',
109 'modulemenu' => 'css/modulemenu.css'
112 $this->toolbarItems
= array();
113 $this->initializeCoreToolbarItems();
117 * initializes the core toolbar items
121 private function initializeCoreToolbarItems() {
123 $coreToolbarItems = array(
124 'workspaceSelector' => 'WorkspaceSelector',
125 'clearCacheActions' => 'ClearCacheMenu',
126 'shortcuts' => 'ShortcutMenu',
127 'backendSearch' => 'BackendSearchMenu'
130 foreach($coreToolbarItems as $toolbarItemName => $toolbarItemClassName) {
131 // Get name of XCLASS (if any):
132 $toolbarItemClassName = t3lib_div
::makeInstanceClassName($toolbarItemClassName);
133 $toolbarItem = new $toolbarItemClassName($this);
135 if(!($toolbarItem instanceof backend_toolbarItem
)) {
136 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195126772);
139 if($toolbarItem->checkAccess()) {
140 $this->toolbarItems
[$toolbarItemName] = $toolbarItem;
148 * main function generating the BE scaffolding
152 public function render() {
154 // prepare the scaffolding, at this point extension may still add javascript and css
155 $logo = t3lib_div
::makeInstance('TYPO3Logo');
156 $logo->setLogo('gfx/typo3logo_mini.png');
158 $menu = $this->moduleMenu
->render();
161 // create backend scaffolding
162 $backendScaffolding = '
163 <div id="typo3-backend">
164 <div id="typo3-top-container">
165 <div id="typo3-logo">'.$logo->render().'</div>
166 <div id="typo3-top" class="typo3-top-toolbar">'
167 .$this->renderToolbar()
170 <div id="typo3-main-container">
171 <div id="typo3-side-menu">
174 <div id="typo3-content">
175 <iframe src="alt_intro.php" name="content" id="content" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" noresize="noresize"></iframe>
181 /******************************************************
182 * now put the complete backend document together
183 ******************************************************/
186 $GLOBALS['TBE_TEMPLATE']->docType
= 'xhtml_trans';
189 foreach($this->jsFiles
as $jsFile) {
190 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
191 <script type="text/javascript" src="'.$jsFile.'"></script>';
193 $GLOBALS['TBE_TEMPLATE']->JScode
.= chr(10);
194 $this->generateJavascript();
195 $GLOBALS['TBE_TEMPLATE']->JScode
.= $GLOBALS['TBE_TEMPLATE']->wrapScriptTags($this->js
);
197 // FIXME abusing the JS container to add CSS, need to fix template.php
198 foreach($this->cssFiles
as $cssFileName => $cssFile) {
199 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
200 <link rel="stylesheet" type="text/css" href="'.$cssFile.'" />
203 // load addditional css files to overwrite existing core styles
204 if(!empty($GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName])) {
205 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
206 <link rel="stylesheet" type="text/css" href="'.$GLOBALS['TBE_STYLES']['stylesheets'][$cssFileName].'" />
211 if(!empty($this->css
)) {
212 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
213 <style type="text/css" id="internalStyle">
218 // set document title:
219 $title = ($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']
220 ?
$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'].' [TYPO3 '.TYPO3_version
.']'
221 : 'TYPO3 '.TYPO3_version
224 // start page header:
225 $this->content
.= $GLOBALS['TBE_TEMPLATE']->startPage($title);
226 $this->content
.= $backendScaffolding;
227 $this->content
.= $GLOBALS['TBE_TEMPLATE']->endPage();
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 global $BE_USER, $BACK_PATH;
259 $icon = '<img'.t3lib_iconWorks
::skinImg(
261 $BE_USER->isAdmin() ?
262 'gfx/i/be_users_admin.gif' :
263 'gfx/i/be_users.gif',
264 'width="18" height="16"'
266 .' title="" alt="" />';
268 $label = $GLOBALS['BE_USER']->user
['realName'] ?
269 $BE_USER->user
['realName'].' ['.$BE_USER->user
['username'].']' :
270 $BE_USER->user
['username'];
272 // Link to user setup if it's loaded and user has access
274 if (t3lib_extMgm
::isLoaded('setup') && $BE_USER->check('modules','user_setup')) {
275 $link = '<a href="#" onclick="top.goToModule(\'user_setup\');this.blur();return false;">';
278 $username = '">'.$link.$icon.'<span>'.htmlspecialchars($label).'</span>'.($link?
'</a>':'');
281 if($BE_USER->user
['ses_backuserid']) {
282 $username = ' su-user">'.$icon.
283 '<span title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:switchtouser').'">SU: </span>'.
284 '<span>'.htmlspecialchars($label).'</span>';
287 return '<div id="username" class="toolbar-item no-separator'.$username.'</div>';
291 * Generates the JavaScript code for the backend.
295 private function generateJavascript() {
297 $pathTYPO3 = t3lib_div
::dirname(t3lib_div
::getIndpEnv('SCRIPT_NAME')).'/';
298 $goToModuleSwitch = $this->moduleMenu
->getGotoModuleJavascript();
299 $moduleFramesHelper = implode(chr(10), $this->moduleMenu
->getFsMod());
301 // If another page module was specified, replace the default Page module with the new one
302 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
303 $pageModule = t3lib_BEfunc
::isModuleSetInTBE_MODULES($newPageModule) ?
$newPageModule : 'web_layout';
305 $menuFrameName = 'menu';
306 if($GLOBALS['BE_USER']->uc
['noMenuMode'] === 'icons') {
307 $menuFrameName = 'topmenuFrame';
312 * Function similar to PHPs rawurlencode();
314 function rawurlencode(str) { //
315 var output = escape(str);
316 output = str_replace("*","%2A", output);
317 output = str_replace("+","%2B", output);
318 output = str_replace("/","%2F", output);
319 output = str_replace("@","%40", output);
324 * String-replace function
326 function str_replace(match,replace,string) { //
327 var input = ""+string;
328 var matchStr = ""+match;
329 if (!matchStr) {return string;}
332 var pos = input.indexOf(matchStr);
334 output+=""+input.substr(pointer, pos-pointer)+replace;
335 pointer=pos+matchStr.length;
336 pos = input.indexOf(match,pos+1);
338 output+=""+input.substr(pointer);
345 function typoSetup() { //
346 this.PATH_typo3 = "'.$pathTYPO3.'";
347 this.PATH_typo3_enc = "'.rawurlencode($pathTYPO3).'";
348 this.username = "'.$GLOBALS['BE_USER']->user
['username'].'";
349 this.uniqueID = "'.t3lib_div
::shortMD5(uniqid('')).'";
350 this.navFrameWidth = 0;
352 var TS = new typoSetup();
355 * Functions for session-expiry detection:
358 this.loginRefreshed = busy_loginRefreshed;
359 this.checkLoginTimeout = busy_checkLoginTimeout;
360 this.openRefreshWindow = busy_OpenRefreshWindow;
363 this.reloginCancelled=0;
365 function busy_loginRefreshed() { //
366 var date = new Date();
367 this.busyloadTime = Math.floor(date.getTime()/1000);
370 function busy_checkLoginTimeout() { //
371 var date = new Date();
372 var theTime = Math.floor(date.getTime()/1000);
373 if (theTime > this.busyloadTime+'.intval($GLOBALS['BE_USER']->auth_timeout_field
).'-30) {
377 function busy_OpenRefreshWindow() { //
378 vHWin=window.open("login_frameset.php","relogin_"+TS.uniqueID,"height=350,width=700,status=0,menubar=0,location=1");
382 function busy_checkLoginTimeout_timer() { //
383 if (busy.checkLoginTimeout() && !busy.reloginCancelled && !busy.openRefreshW) {
384 if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.refresh_login')).')) {
385 busy.openRefreshWindow();
387 busy.reloginCancelled = 1;
390 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())
392 // 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!)
393 if (top && top.content && top.content.nav_frame && top.content.nav_frame.document && top.content.nav_frame.document.body) {
394 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;
399 * Launcing information window for records/files (fileref as "table" argument)
401 function launchView(table,uid,bP) { //
402 var backPath= bP ? bP : "";
403 var thePreviewWindow="";
404 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");
405 if (thePreviewWindow && thePreviewWindow.focus) {
406 thePreviewWindow.focus();
411 * Opens plain window with url
413 function openUrlInWindow(url,windowName) { //
414 regularWindow = window.open(url,windowName,"status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1");
415 regularWindow.focus();
420 * Loads a page id for editing in the page edit module:
422 function loadEditId(id,addGetVars) { //
423 top.fsMod.recentIds["web"]=id;
424 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_0"; // For highlighting
426 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
427 top.content.nav_frame.refresh_nav();
430 top.goToModule("'.$pageModule.'", 0, addGetVars?addGetVars:"");
434 * Returns incoming URL (to a module) unless nextLoadModuleUrl is set. If that is the case nextLoadModuleUrl is returned (and cleared)
435 * Used by the shortcut frame to set a "intermediate URL"
437 var nextLoadModuleUrl="";
438 function getModuleUrl(inUrl) { //
440 if (top.nextLoadModuleUrl) {
441 nMU=top.nextLoadModuleUrl;
442 top.nextLoadModuleUrl="";
450 * Print properties of an object
452 function debugObj(obj,name) { //
456 acc+=i+": "+obj[i]+"\n";
459 alert("Object: "+name+"\n\n"+acc);
463 * Initialize login expiration warning object
465 var busy = new busy();
466 busy.loginRefreshed();
467 busy_checkLoginTimeout_timer();
470 * Function used to switch modules
472 var currentModuleLoaded = "";
473 var goToModule = '.$goToModuleSwitch.'
476 * Frameset Module object
478 * Used in main modules with a frameset for submodules to keep the ID between modules
479 * Typically that is set by something like this in a Web>* sub module:
480 * if (top.fsMod) top.fsMod.recentIds["web"] = "\'.intval($this->id).\'";
481 * if (top.fsMod) top.fsMod.recentIds["file"] = "...(file reference/string)...";
483 function fsModules() { //
484 this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
485 this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
486 this.currentMainLoaded="";
487 this.currentBank="0";
489 var fsMod = new fsModules();
490 '.$moduleFramesHelper.'
492 // Used by Frameset Modules
493 var condensedMode = '.($GLOBALS['BE_USER']->uc
['condensedMode']?
1:0).';
494 var currentSubScript = "";
495 var currentSubNavScript = "";
497 // Used for tab-panels:
498 var DTM_currentTabs = new Array();
501 // Check editing of page:
502 $this->handlePageEditing();
503 $this->setStartupModule();
507 * Checking if the "&edit" variable was sent so we can open it for editing the page.
508 * Code based on code from "alt_shortcut.php"
512 private function handlePageEditing() {
514 if(!t3lib_extMgm
::isLoaded('cms')) {
519 $editId = preg_replace('/[^[:alnum:]_]/', '', t3lib_div
::_GET('edit'));
524 // Looking up the page to edit, checking permissions:
525 $where = ' AND ('.$GLOBALS['BE_USER']->getPagePermsClause(2)
526 .' OR '.$GLOBALS['BE_USER']->getPagePermsClause(16).')';
528 if(t3lib_div
::testInt($editId)) {
529 $editRecord = t3lib_BEfunc
::getRecordWSOL('pages', $editId, '*', $where);
531 $records = t3lib_BEfunc
::getRecordsByField('pages', 'alias', $editId, $where);
533 if(is_array($records)) {
535 $editRecord = current($records);
536 t3lib_BEfunc
::workspaceOL('pages', $editRecord);
540 // If the page was accessible, then let the user edit it.
541 if(is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) {
542 // Setting JS code to open editing:
544 // Load page to edit:
545 window.setTimeout("top.loadEditId('.intval($editRecord['uid']).');", 500);
547 // Checking page edit parameter:
548 if(!$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_dontSetPageTree')) {
550 // Expanding page tree:
551 t3lib_BEfunc
::openPageTree(intval($editRecord['pid']), !$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_keepExistingExpanded'));
555 // Warning about page editing:
556 alert('.$GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)).');
563 * Sets the startup module from either GETvars module and mpdParams or user configuration.
567 private function setStartupModule() {
568 $startModule = preg_replace('/[^[:alnum:]_]/', '', t3lib_div
::_GET('module'));
571 if ($GLOBALS['BE_USER']->uc
['startModule']) {
572 $startModule = $GLOBALS['BE_USER']->uc
['startModule'];
573 } else if($GLOBALS['BE_USER']->uc
['startInTaskCenter']) {
574 $startModule = 'user_task';
578 $moduleParameters = t3lib_div
::_GET('modParams');
582 function startInModule(modName, cMR_flag, addGetVars) {
583 Event.observe(document, \'dom:loaded\', function() {
584 top.goToModule(modName, cMR_flag, addGetVars);
588 startInModule(\''.$startModule.'\', false, \''.$moduleParameters.'\');
594 * generates the code for the TYPO3 logo, either the default TYPO3 logo or a custom one
596 * @return string HTML code snippet to display the TYPO3 logo
598 private function getLogo() {
599 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
600 '<img'.t3lib_iconWorks
::skinImg('','gfx/alt_backend_logo.gif','width="117" height="32"').' title="TYPO3 Content Management Framework" alt="" />'.
603 // overwrite with custom logo
604 if($GLOBALS['TBE_STYLES']['logo']) {
605 if(substr($GLOBALS['TBE_STYLES']['logo'], 0, 3) == '../') {
606 $imgInfo = @getimagesize
(PATH_site
.substr($GLOBALS['TBE_STYLES']['logo'], 3));
608 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
609 '<img src="'.$GLOBALS['TBE_STYLES']['logo'].'" '.$imgInfo[3].' title="TYPO3 Content Management Framework" alt="" />'.
617 * adds a javascript snippet to the backend
619 * @param string javascript snippet
622 public function addJavascript($javascript) {
623 // TODO do we need more checks?
624 if(!is_string($javascript)) {
625 throw new InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
628 $this->js
.= $javascript;
632 * adds a javscript file to the backend after it has been checked that it exists
634 * @param string javascript file reference
635 * @return boolean true if the javascript file was successfully added, false otherwise
637 public function addJavascriptFile($javascriptFile) {
638 $jsFileAdded = false;
640 //TODO add more checks if neccessary
641 if(file_exists(t3lib_div
::resolveBackPath(PATH_typo3
.$javascriptFile))) {
642 $this->jsFiles
[] = $javascriptFile;
650 * adds a css snippet to the backend
652 * @param string css snippet
655 public function addCss($css) {
656 if(!is_string($css)) {
657 throw new InvalidArgumentException('parameter $css must be of type string', 1195129642);
664 * adds a css file to the backend after it has been checked that it exists
666 * @param string the css file's name with out the .css ending
667 * @param string css file reference
668 * @return boolean true if the css file was added, false otherwise
670 public function addCssFile($cssFileName, $cssFile) {
671 $cssFileAdded = false;
673 //TODO add more checks if neccessary
674 if(file_exists(t3lib_div
::resolveBackPath(PATH_typo3
.$cssFile))) {
675 // prevent overwriting existing css files
676 if(empty($this->cssFiles
[$cssFileName])) {
677 $this->cssFiles
[$cssFileName] = $cssFile;
678 $cssFileAdded = true;
682 return $cssFileAdded;
686 * adds an item to the toolbar, the class file for the toolbar item must be loaded at this point
688 * @param string toolbar item name, f.e. tx_toolbarExtension_coolItem
689 * @param string toolbar item class name, f.e. tx_toolbarExtension_coolItem
692 public function addToolbarItem($toolbarItemName, $toolbarItemClassName) {
693 $toolbarItemResolvedClassName = t3lib_div
::makeInstanceClassName($toolbarItemClassName);
694 $toolbarItem = new $toolbarItemResolvedClassName($this);
696 if(!($toolbarItem instanceof backend_toolbarItem
)) {
697 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195125501);
700 if($toolbarItem->checkAccess()) {
701 $this->toolbarItems
[$toolbarItemName] = $toolbarItem;
710 if(defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['typo3/backend.php']) {
711 include_once($TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['typo3/backend.php']);
715 // document generation
716 $TYPO3backend = t3lib_div
::makeInstance('TYPO3backend');
718 // include extensions which may add css, javascript or toolbar items
719 if(is_array($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'])) {
720 foreach($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'] as $additionalBackendItem) {
721 include_once($additionalBackendItem);
725 $TYPO3backend->render();