39ac53864f82ff7c9b400b496f0fb8daf0e1ddf8
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',
110 '../t3lib/jsfunc.evalfield.js'
113 // add default BE css
114 $this->cssFiles
= array(
115 'css/backend-scaffolding.css',
116 'css/backend-style.css',
117 'css/verticalmenu.css'
120 $this->toolbarItems
= array();
121 $this->initializeCoreToolbarItems();
125 * initializes the core toolbar items
129 private function initializeCoreToolbarItems() {
131 $coreToolbarItems = array(
132 'workspaceSelector' => 'WorkspaceSelector',
133 'clearCacheActions' => 'ClearCacheMenu',
134 # 'shortcuts' => 'ShortcutMenu',
135 'backendSearch' => 'BackendSearchMenu'
138 foreach($coreToolbarItems as $toolbarItemName => $toolbarItemClass) {
139 $toolbarItem = t3lib_div
::makeInstance($toolbarItemClass);
141 if(!($toolbarItem instanceof backend_toolbarItem
)) {
142 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface backend_toolbarItem', 1195126772);
145 $toolbarItem->setBackend($this);
146 $this->toolbarItems
[$toolbarItemName] = $toolbarItem;
151 * main function generating the BE scaffolding
155 public function render() {
157 // prepare the scaffolding, at this point extension still may addjavascript and css
158 $logo = t3lib_div
::makeInstance('TYPO3Logo');
159 $logo->setLogo('gfx/typo3logo_mini.png');
161 $menu = $this->moduleMenu
->render();
164 // create backend scaffolding
165 $backendScaffolding = '
166 <div id="typo3-backend">
167 <div id="typo3-top-container">
168 <div id="typo3-logo">'.$logo->render().'</div>
169 <div id="typo3-top" class="typo3-top-toolbar">'
170 .$this->renderToolbar()
173 <div id="typo3-main-container">
174 <div id="typo3-side-menu">
177 <div id="typo3-content">
178 <iframe src="alt_intro.php" name="content" id="content" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" noresize="noresize"></iframe>
185 /******************************************************
186 * now put the complete backend document together
187 ******************************************************/
190 $GLOBALS['TBE_TEMPLATE']->docType
= 'xhtml_trans';
193 foreach($this->jsFiles
as $jsFile) {
194 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
195 <script type="text/javascript" src="'.$jsFile.'"></script>';
197 $GLOBALS['TBE_TEMPLATE']->JScode
.= chr(10);
198 $this->generateJavascript();
199 $GLOBALS['TBE_TEMPLATE']->JScode
.= $GLOBALS['TBE_TEMPLATE']->wrapScriptTags($this->js
);
201 // abusing the JS container to add CSS
202 // TODO fix template.php
203 foreach($this->cssFiles
as $cssFile) {
204 $GLOBALS['TBE_TEMPLATE']->JScode
.= '
205 <link rel="stylesheet" type="text/css" href="'.$cssFile.'" />
208 // TODO add CSS from $this->css
210 // set document title
211 $title = $TYPO3_CONF_VARS['SYS']['sitename'] ?
212 $TYPO3_CONF_VARS['SYS']['sitename'].' [TYPO3 '.TYPO3_version
.']'
213 : 'TYPO3 '.TYPO3_version
;
215 // start page header:
216 $this->content
.= $GLOBALS['TBE_TEMPLATE']->startPage($title);
217 $this->content
.= $GLOBALS['TBE_TEMPLATE']->endPage();
219 $this->content
.= $backendScaffolding;
225 * renders the items in the top toolbar
227 * @return string top toolbar elements as HTML
229 private function renderToolbar() {
230 $toolbar = '<ul id="typo3-toolbar">';
231 $toolbar.= '<li>'.$this->getLoggedInUserLabel().'</li>
232 <li><div id="logout-button" class="toolbar-item no-separator">'.$this->moduleMenu
->renderLogoutButton().'</div></li>';
234 foreach($this->toolbarItems
as $toolbarItem) {
235 $additionalAttributes = $toolbarItem->getAdditionalAttributes();
237 $toolbar .= '<li'.$additionalAttributes.'>'.$toolbarItem->render().'</li>';
240 return $toolbar.'</ul>';
244 * gets the label of the currently loged in BE user
246 * @return string html code snippet displaying the currently logged in user
248 private function getLoggedInUserLabel() {
249 $username = '<div id="username" class="toolbar-item no-separator">['.htmlspecialchars($GLOBALS['BE_USER']->user
['username']).']</div>';;
252 if($BE_USER->user
['ses_backuserid']) {
253 $username = '<div id="username" class="toolbar-item no-separator typo3-red-background">[SU: '.htmlspecialchars($GLOBALS['BE_USER']->user
['username']).']</div>';
260 * Generates the JavaScript code for the backend.
264 private function generateJavascript() {
266 $pathTYPO3 = t3lib_div
::dirname(t3lib_div
::getIndpEnv('SCRIPT_NAME')).'/';
267 $goToModuleSwitch = $this->moduleMenu
->getGotoModuleJavascript();
268 $moduleFramesHelper = implode(chr(10), $this->moduleMenu
->getFsMod());
270 // If another page module was specified, replace the default Page module with the new one
271 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
272 $pageModule = t3lib_BEfunc
::isModuleSetInTBE_MODULES($newPageModule) ?
$newPageModule : 'web_layout';
274 $menuFrameName = 'menu';
275 if($GLOBALS['BE_USER']->uc
['noMenuMode'] === 'icons') {
276 $menuFrameName = 'topmenuFrame';
281 * Function similar to PHPs rawurlencode();
283 function rawurlencode(str) { //
284 var output = escape(str);
285 output = str_replace("*","%2A", output);
286 output = str_replace("+","%2B", output);
287 output = str_replace("/","%2F", output);
288 output = str_replace("@","%40", output);
293 * String-replace function
295 function str_replace(match,replace,string) { //
296 var input = ""+string;
297 var matchStr = ""+match;
298 if (!matchStr) {return string;}
301 var pos = input.indexOf(matchStr);
303 output+=""+input.substr(pointer, pos-pointer)+replace;
304 pointer=pos+matchStr.length;
305 pos = input.indexOf(match,pos+1);
307 output+=""+input.substr(pointer);
314 function typoSetup() { //
315 this.PATH_typo3 = "'.$pathTYPO3.'";
316 this.PATH_typo3_enc = "'.rawurlencode($pathTYPO3).'";
317 this.username = "'.$GLOBALS['BE_USER']->user
['username'].'";
318 this.uniqueID = "'.t3lib_div
::shortMD5(uniqid('')).'";
319 this.navFrameWidth = 0;
321 var TS = new typoSetup();
324 * Functions for session-expiry detection:
327 this.loginRefreshed = busy_loginRefreshed;
328 this.checkLoginTimeout = busy_checkLoginTimeout;
329 this.openRefreshWindow = busy_OpenRefreshWindow;
332 this.reloginCancelled=0;
334 function busy_loginRefreshed() { //
335 var date = new Date();
336 this.busyloadTime = Math.floor(date.getTime()/1000);
339 function busy_checkLoginTimeout() { //
340 var date = new Date();
341 var theTime = Math.floor(date.getTime()/1000);
342 if (theTime > this.busyloadTime+'.intval($GLOBALS['BE_USER']->auth_timeout_field
).'-30) {
346 function busy_OpenRefreshWindow() { //
347 vHWin=window.open("login_frameset.php","relogin_"+TS.uniqueID,"height=350,width=700,status=0,menubar=0,location=1");
351 function busy_checkLoginTimeout_timer() { //
352 if (busy.checkLoginTimeout() && !busy.reloginCancelled && !busy.openRefreshW) {
353 if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.refresh_login')).')) {
354 busy.openRefreshWindow();
356 busy.reloginCancelled = 1;
359 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())
361 // 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!)
362 if (top && top.content && top.content.nav_frame && top.content.nav_frame.document && top.content.nav_frame.document.body) {
363 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;
368 * Launcing information window for records/files (fileref as "table" argument)
370 function launchView(table,uid,bP) { //
371 var backPath= bP ? bP : "";
372 var thePreviewWindow="";
373 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");
374 if (thePreviewWindow && thePreviewWindow.focus) {
375 thePreviewWindow.focus();
380 * Opens plain window with url
382 function openUrlInWindow(url,windowName) { //
383 regularWindow = window.open(url,windowName,"status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1");
384 regularWindow.focus();
389 * Loads a URL in the topmenuFrame
391 function loadTopMenu(url) { //
392 top.topmenuFrame.location = url;
396 * Loads a page id for editing in the page edit module:
398 function loadEditId(id,addGetVars) { //
399 top.fsMod.recentIds["web"]=id;
400 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_0"; // For highlighting
402 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
403 top.content.nav_frame.refresh_nav();
406 top.goToModule("'.$pageModule.'", 0, addGetVars?addGetVars:"");
410 * Returns incoming URL (to a module) unless nextLoadModuleUrl is set. If that is the case nextLoadModuleUrl is returned (and cleared)
411 * Used by the shortcut frame to set a "intermediate URL"
413 var nextLoadModuleUrl="";
414 function getModuleUrl(inUrl) { //
416 if (top.nextLoadModuleUrl) {
417 nMU=top.nextLoadModuleUrl;
418 top.nextLoadModuleUrl="";
426 * Print properties of an object
428 function debugObj(obj,name) { //
432 acc+=i+": "+obj[i]+"\n";
435 alert("Object: "+name+"\n\n"+acc);
439 * Initialize login expiration warning object
441 var busy = new busy();
442 busy.loginRefreshed();
443 busy_checkLoginTimeout_timer();
449 var currentlyHighLightedId = "";
450 var currentlyHighLighted_restoreValue = "";
451 var currentlyHighLightedMain = "";
452 function highlightModuleMenuItem(trId, mainModule) { //
453 currentlyHighLightedMain = mainModule;
454 // Get document object:
455 if (top.menu && top.menu.document) {
456 var docObj = top.menu.document;
457 var HLclass = mainModule ? "c-mainitem-HL" : "c-subitem-row-HL";
458 } else if (top.topmenuFrame && top.topmenuFrame.document) {
459 var docObj = top.topmenuFrame.document;
460 var HLclass = mainModule ? "c-mainitem-HL" : "c-subitem-HL";
465 if (currentlyHighLightedId && docObj.getElementById(currentlyHighLightedId)) {
466 docObj.getElementById(currentlyHighLightedId).attributes.getNamedItem("class").nodeValue = currentlyHighLighted_restoreValue;
469 currentlyHighLightedId = trId;
470 if (currentlyHighLightedId && docObj.getElementById(currentlyHighLightedId)) {
471 var classAttribObject = docObj.getElementById(currentlyHighLightedId).attributes.getNamedItem("class");
472 currentlyHighLighted_restoreValue = classAttribObject.nodeValue;
473 classAttribObject.nodeValue = HLclass;
479 * Function restoring previous selection in left menu after clearing cache
481 function restoreHighlightedModuleMenuItem() { //
482 if (currentlyHighLightedId) {
483 highlightModuleMenuItem(currentlyHighLightedId,currentlyHighLightedMain);
487 '.$goToModuleSwitch.'
490 * reloads the menu frame
492 function refreshMenu() {
493 top.'.$menuFrameName.'.location.href = top.'.$menuFrameName.'.document.URL
497 * Frameset Module object
499 * Used in main modules with a frameset for submodules to keep the ID between modules
500 * Typically that is set by something like this in a Web>* sub module:
501 * if (top.fsMod) top.fsMod.recentIds["web"] = "\'.intval($this->id).\'";
502 * if (top.fsMod) top.fsMod.recentIds["file"] = "...(file reference/string)...";
504 function fsModules() { //
505 this.recentIds=new Array(); // used by frameset modules to track the most recent used id for list frame.
506 this.navFrameHighlightedID=new Array(); // used by navigation frames to track which row id was highlighted last time
507 this.currentMainLoaded="";
508 this.currentBank="0";
510 var fsMod = new fsModules();
511 '.$moduleFramesHelper.'
513 // Used by Frameset Modules
514 var condensedMode = '.($GLOBALS['BE_USER']->uc
['condensedMode']?
1:0).';
515 var currentSubScript = "";
516 var currentSubNavScript = "";
518 // Used for tab-panels:
519 var DTM_currentTabs = new Array();
522 // Check editing of page:
523 $this->editPageHandling();
524 $this->setStartupModule();
528 * Checking if the "&edit" variable was sent so we can open for editing the page.
529 * Code based on code from "alt_shortcut.php"
533 private function editPageHandling() {
535 if(!t3lib_extMgm
::isLoaded('cms')) {
540 $editId = preg_replace('/[^[:alnum:]_]/', '', t3lib_div
::_GET('edit'));
545 // Looking up the page to edit, checking permissions:
546 $where = ' AND ('.$GLOBALS['BE_USER']->getPagePermsClause(2)
547 .' OR '.$GLOBALS['BE_USER']->getPagePermsClause(16).')';
549 if(t3lib_div
::testInt($editId)) {
550 $editRecord = t3lib_BEfunc
::getRecordWSOL('pages', $editId, '*', $where);
552 $records = t3lib_BEfunc
::getRecordsByField('pages', 'alias', $editId, $where);
554 if(is_array($records)) {
556 $editRecord = current($records);
557 t3lib_BEfunc
::workspaceOL('pages', $editRecord);
561 // If the page was accessible, then let the user edit it.
562 if(is_array($editRecord) && $GLOBALS['BE_USER']->isInWebMount($editRecord['uid'])) {
563 // Setting JS code to open editing:
565 // Load page to edit:
566 window.setTimeout("top.loadEditId('.intval($editRecord['uid']).');", 500);
568 // Checking page edit parameter:
569 if(!$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_dontSetPageTree')) {
571 // Expanding page tree:
572 t3lib_BEfunc
::openPageTree(intval($editRecord['pid']), !$GLOBALS['BE_USER']->getTSConfigVal('options.shortcut_onEditId_keepExistingExpanded'));
576 // Warning about page editing:
577 alert('.$GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->getLL('noEditPage'), $editId)).');
584 * Sets the startup module from either GETvars module and mpdParams or user configuration.
588 private function setStartupModule() {
589 $startModule = preg_replace('/[^[:alnum:]_]/', '', t3lib_div
::_GET('module'));
592 if ($GLOBALS['BE_USER']->uc
['startModule']) {
593 $startModule = $GLOBALS['BE_USER']->uc
['startModule'];
594 } else if($GLOBALS['BE_USER']->uc
['startInTaskCenter']) {
595 $startModule = 'user_task';
599 $moduleParameters = t3lib_div
::_GET('modParams');
603 function startInModule(modName, cMR_flag, addGetVars) { //
604 if ($(content) && top.goToModule) {
605 top.goToModule(modName, cMR_flag, addGetVars);
607 window.setTimeout(function() { startInModuleModule(modName, cMR_flag, addGetVars); }, 500);
611 // startInModule(\''.$startModule.'\', false, \''.$moduleParameters.'\');
612 '; //TODO get start module working
617 * generates the code for the TYPO3 logo, either the default TYPO3 logo or a custom one
619 * @return string HTML code snippet to display the TYPO3 logo
621 private function getLogo() {
622 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
623 '<img'.t3lib_iconWorks
::skinImg('','gfx/alt_backend_logo.gif','width="117" height="32"').' title="TYPO3 Content Management Framework" alt="" />'.
626 // overwrite with custom logo
627 if($GLOBALS['TBE_STYLES']['logo']) {
628 if(substr($GLOBALS['TBE_STYLES']['logo'], 0, 3) == '../') {
629 $imgInfo = @getimagesize
(PATH_site
.substr($GLOBALS['TBE_STYLES']['logo'], 3));
631 $logo = '<a href="http://www.typo3.com/" target="_blank" onclick="'.$GLOBALS['TBE_TEMPLATE']->thisBlur().'">'.
632 '<img src="'.$GLOBALS['TBE_STYLES']['logo'].'" '.$imgInfo[3].' title="TYPO3 Content Management Framework" alt="" />'.
640 * adds a javascript snippet to the backend
642 * @param string javascript snippet
645 public function addJavascript($javascript) {
646 // TODO do we need more checks?
647 if(!is_string($javascript)) {
648 throw new InvalidArgumentException('parameter $javascript must be of type string', 1195129553);
651 $this->js
.= $javascript;
655 * adds a javscript file to the backend after it has been checked that it exists
657 * @param string javascript file reference
660 public function addJavascriptFile($javascriptFile) {
661 //TODO add more checks if neccessary
663 if(file_exists(t3lib_div
::resolveBackPath(PATH_site
.$javascriptFile))) {
665 if(t3lib_div
::isFirstPartOfStr($javascriptFile, 'typo3/')) {
666 $javascriptFile = substr($javascriptFile, 6); // make relative to typo3/
669 $this->jsFiles
[] = $javascriptFile;
674 * adds a css snippet to the backend
676 * @param string css snippet
679 public function addCss($css) {
680 if(!is_string($css)) {
681 throw new InvalidArgumentException('parameter $css must be of type string', 1195129642);
688 * adds a css file to the backend after it has been checked that it exists
690 * @param string css file reference
693 public function addCssFile($cssFile) {
694 //TODO add more checks if neccessary
696 if(file_exists(t3lib_div
::resolveBackPath(PATH_site
.$cssFile))) {
698 if(t3lib_div
::isFirstPartOfStr($cssFile, 'typo3/')) {
699 $cssFile = substr($cssFile, 6); // make relative to typo3/
702 $this->cssFiles
[] = $cssFile;
707 * adds an item to the toolbar
709 * @param string toolbar item class reference, f.e. EXT:toolbarextension/class.tx_toolbarextension_coolitem.php:tx_toolbarExtension_coolItem
711 public function addToolbarItem($toolbarItemName, $toolbarItemClassReference) {
712 $toolbarItem = t3lib_div
::getUserObj($toolbarItemClassReference);
714 if(!($toolbarItem instanceof t3lib_backendToolbarItem
)) {
715 throw new UnexpectedValueException('$toolbarItem "'.$toolbarItemName.'" must implement interface t3lib_backendToolbarItem', 1195125501);
718 $toolbarItem->setBackend($this);
719 $this->toolbarItems
[$toolbarItemName] = $toolbarItem;
725 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['typo3/backend.php']) {
726 include_once($TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['typo3/backend.php']);
730 // document generation
731 $TYPO3backend = t3lib_div
::makeInstance('TYPO3backend');
733 // include extensions which may add css, javascript or toolbar items
734 if(is_array($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'])) {
735 foreach($GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'] as $additionalBackendItem) {
736 include_once($additionalBackendItem);
740 $TYPO3backend->render();