2 /***************************************************************
5 * (c) 1999-2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
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 * This document provides a class that loads the modules for the TYPO3 interface.
31 * Modifications by Rene Fritz, 2001
32 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
34 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
38 * [CLASS/FUNCTION INDEX of SCRIPT]
42 * 78: class t3lib_loadModules
43 * 97: function load($modulesArray,$BE_USER='')
44 * 366: function checkExtensionModule($name)
45 * 385: function checkMod($name, $fullpath)
46 * 465: function checkModAccess($name,$MCONF)
47 * 488: function parseModulesArray($arr)
48 * 517: function cleanName ($str)
49 * 528: function getRelativePath($baseDir,$destDir)
52 * (This index is automatically created/updated by the extension "extdeveval")
68 * Load Backend Interface modules
70 * Typically instantiated like this:
71 * $this->loadModules = t3lib_div::makeInstance('t3lib_loadModules');
72 * $this->loadModules->load($TBE_MODULES);
74 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
78 class t3lib_loadModules
{
79 var $modules = Array(); // After the init() function this array will contain the structure of available modules for the backend user.
80 var $absPathArray = array(); // Array with paths pointing to the location of modules from extensions
82 var $modListGroup = Array(); // this array will hold the elements that should go into the select-list of modules for groups...
83 var $modListUser = Array(); // this array will hold the elements that should go into the select-list of modules for users...
85 var $BE_USER = ''; // The backend user for use internally
90 * The outcome of the load() function will be a $this->modules array populated with the backend module structure available to the BE_USER
91 * Further the global var $LANG will have labels and images for the modules loaded in an internal array.
93 * @param array $modulesArray should be the global var $TBE_MODULES, $BE_USER can optionally be set to an alternative Backend user object than the global var $BE_USER (which is the currently logged in user)
94 * @param object Optional backend user object to use. If not set, the global BE_USER object is used.
97 function load($modulesArray,$BE_USER='') {
98 // Setting the backend user for use internally
99 if (is_object($BE_USER)) {
100 $this->BE_USER
= $BE_USER;
102 $this->BE_USER
= $GLOBALS['BE_USER'];
107 $modulesArray might look like this when entering this function.
108 Notice the two modules added by extensions - they have a path attached
112 [web] => list,info,perm,func
116 [tools] => em,install,txphpmyadmin
120 [tools_install] => /www/htdocs/typo3/32/coreinstall/typo3/ext/install/mod/
121 [tools_txphpmyadmin] => /www/htdocs/typo3/32/coreinstall/typo3/ext/phpmyadmin/modsub/
128 $this->absPathArray
= $modulesArray['_PATHS'];
129 unset($modulesArray['_PATHS']);
132 With the above data for modules the result of this function call will be:
165 $theMods = $this->parseModulesArray($modulesArray);
168 Originally modules were found in typo3/mod/
169 User defined modules were found in ../typo3conf/
171 Today almost all modules reside in extensions and they are found by the _PATHS array of the incoming $TBE_MODULES array
173 // Setting paths for 1) core modules (old concept from mod/) and 2) user-defined modules (from ../typo3conf)
175 $paths['defMods'] = PATH_typo3
.'mod/'; // Path of static modules
176 $paths['userMods'] = PATH_typo3
.'../typo3conf/'; // local modules (maybe frontend specific)
178 // Traverses the module setup and creates the internal array $this->modules
179 foreach($theMods as $mods => $subMod) {
182 $extModRelPath = $this->checkExtensionModule($mods);
183 if ($extModRelPath) { // EXTENSION module:
184 $theMainMod = $this->checkMod($mods,PATH_site
.$extModRelPath);
185 if (is_array($theMainMod) ||
$theMainMod!='notFound') {
186 $path = 1; // ... just so it goes on... submodules cannot be within this path!
188 } else { // 'CLASSIC' module
189 // Checking for typo3/mod/ module existence...
190 $theMainMod = $this->checkMod($mods,$paths['defMods'].$mods);
191 if (is_array($theMainMod) ||
$theMainMod!='notFound') {
192 $path = $paths['defMods'];
194 // If not typo3/mod/ then it could be user-defined in typo3conf/ ...?
195 $theMainMod = $this->checkMod($mods,$paths['userMods'].$mods);
196 if (is_array($theMainMod) ||
$theMainMod!='notFound') {
197 $path = $paths['userMods'];
202 // if $theMainMod is not set (false) there is no access to the module !(?)
203 if ($theMainMod && isset($path)) {
204 $this->modules
[$mods] = $theMainMod;
206 // SUBMODULES - if any - are loaded (The 'doc' module cannot have submodules...)
207 if ($mods!='doc' && is_array($subMod)) {
208 foreach($subMod as $valsub) {
209 $extModRelPath = $this->checkExtensionModule($mods.'_'.$valsub);
210 if ($extModRelPath) { // EXTENSION submodule:
211 $theTempSubMod = $this->checkMod($mods.'_'.$valsub,PATH_site
.$extModRelPath);
212 if (is_array($theTempSubMod)) { // default sub-module in either main-module-path, be it the default or the userdefined.
213 $this->modules
[$mods]['sub'][$valsub] = $theTempSubMod;
215 } else { // 'CLASSIC' submodule
216 // Checking for typo3/mod/xxx/ module existence...
217 $theTempSubMod = $this->checkMod($mods.'_'.$valsub,$path.$mods.'/'.$valsub);
218 if (is_array($theTempSubMod)) { // default sub-module in either main-module-path, be it the default or the userdefined.
219 $this->modules
[$mods]['sub'][$valsub] = $theTempSubMod;
220 } elseif ($path == $paths['defMods']) { // If the submodule did not exist in the default module path, then check if there is a submodule in the submodule path!
221 $theTempSubMod = $this->checkMod($mods.'_'.$valsub,$paths['userMods'].$mods.'/'.$valsub);
222 if (is_array($theTempSubMod)) {
223 $this->modules
[$mods]['sub'][$valsub] = $theTempSubMod;
229 } else { // This must be done in order to fill out the select-lists for modules correctly!!
230 if ($mods!='doc' && is_array($subMod)) {
231 foreach($subMod as $valsub) {
232 $this->checkMod($mods.'_'.$valsub,$path.$mods.'/'.$valsub);
238 At this point $this->modules should look like this:
239 Only modules which were accessible to the $BE_USER is listed in this array.
246 [script] => dummy.php
253 [script] => mod/web/list/../../../db_list.php
259 [script] => mod/web/info/index.php
265 [script] => mod/web/perm/index.php
271 [script] => mod/web/func/index.php
281 [script] => dummy.php
287 [script] => mod/file/list/../../../file_list.php
297 [script] => mod/doc/../../alt_doc.php
303 [script] => dummy.php
310 [script] => dummy.php
316 [script] => mod/tools/em/index.php
321 [name] => tools_install
322 [script] => ext/install/mod/../../../install/index.php
325 [txphpmyadmin] => Array
327 [name] => tools_txphpmyadmin
328 [script] => ext/phpmyadmin/modsub/index.php
338 [script] => dummy.php
339 [defaultMod] => welcome
345 [script] => mod/help/about/index.php
356 #debug($this->modules);
357 #debug($GLOBALS['LANG']->moduleLabels);
361 * If the module name ($name) is a module from an extension (has path in $this->absPathArray) then that path is returned relative to PATH_site
363 * @param string Module name
364 * @return string If found, the relative path from PATH_site
366 function checkExtensionModule($name) {
367 global $TYPO3_LOADED_EXT;
369 if (isset($this->absPathArray
[$name])) {
370 return ereg_replace ('\/$', '', substr($this->absPathArray
[$name],strlen(PATH_site
)));
375 * Here we check for the module.
377 * 'notFound': If the module was not found in the path (no "conf.php" file)
378 * false: If no access to the module (access check failed)
379 * array(): Configuration array, in case a valid module where access IS granted exists.
381 * @param string Module name
382 * @param string Absolute path to module
383 * @return mixed See description of function
385 function checkMod($name, $fullpath) {
387 $path = ereg_replace ('/[^/.]+/\.\./', '/', $fullpath); // because 'path/../path' does not work
388 if (@is_dir
($path) && @file_exists
($path.'/conf.php')) {
389 include($path.'/conf.php'); // The conf-file is included. This must be valid PHP.
390 if (!$MCONF['shy'] && $this->checkModAccess($name,$MCONF)) {
391 $modconf['name']=$name;
392 // language processing. This will add module labels and image reference to the internal ->moduleLabels array of the LANG object.
393 if (is_object($GLOBALS['LANG'])) {
394 // $MLANG['default']['tabs_images']['tab'] is for modules the reference to the module icon.
395 // Here the path is transformed to an absolute reference.
396 if ($MLANG['default']['tabs_images']['tab']) {
398 // Initializing search for alternative icon:
399 $altIconKey = 'MOD:'.$name.'/'.$MLANG['default']['tabs_images']['tab']; // Alternative icon key (might have an alternative set in $TBE_STYLES['skinImg']
400 $altIconAbsPath = is_array($GLOBALS['TBE_STYLES']['skinImg'][$altIconKey]) ? t3lib_div
::resolveBackPath(PATH_typo3
.$GLOBALS['TBE_STYLES']['skinImg'][$altIconKey][0]) : '';
402 // Setting icon, either default or alternative:
403 if ($altIconAbsPath && @is_file
($altIconAbsPath)) {
404 $MLANG['default']['tabs_images']['tab']=$this->getRelativePath(PATH_typo3
,$altIconAbsPath);
406 // Setting default icon:
407 $MLANG['default']['tabs_images']['tab']=$this->getRelativePath(PATH_typo3
,$fullpath.'/'.$MLANG['default']['tabs_images']['tab']);
410 // Finally, setting the icon with correct path:
411 if (substr($MLANG['default']['tabs_images']['tab'],0,3)=='../') {
412 $MLANG['default']['tabs_images']['tab'] = PATH_site
.substr($MLANG['default']['tabs_images']['tab'],3);
414 $MLANG['default']['tabs_images']['tab'] = PATH_typo3
.$MLANG['default']['tabs_images']['tab'];
418 // If LOCAL_LANG references are used for labels of the module:
419 if ($MLANG['default']['ll_ref']) {
420 // Now the 'default' key is loaded with the CURRENT language - not the english translation...
421 $MLANG['default']['labels']['tablabel'] = $GLOBALS['LANG']->sL($MLANG['default']['ll_ref'].':mlang_labels_tablabel');
422 $MLANG['default']['labels']['tabdescr'] = $GLOBALS['LANG']->sL($MLANG['default']['ll_ref'].':mlang_labels_tabdescr');
423 $MLANG['default']['tabs']['tab'] = $GLOBALS['LANG']->sL($MLANG['default']['ll_ref'].':mlang_tabs_tab');
424 $GLOBALS['LANG']->addModuleLabels($MLANG['default'],$name.'_');
425 } else { // ... otherwise use the old way:
426 $GLOBALS['LANG']->addModuleLabels($MLANG['default'],$name.'_');
427 $GLOBALS['LANG']->addModuleLabels($MLANG[$GLOBALS['LANG']->lang
],$name.'_');
431 // Default script setup
432 if ($MCONF['script'] && @file_exists
($path.'/'.$MCONF['script'])) {
433 $modconf['script'] = $this->getRelativePath(PATH_typo3
,$fullpath.'/'.$MCONF['script']);
435 $modconf['script'] = 'dummy.php';
437 // Default tab setting
438 if ($MCONF['defaultMod']) {
439 $modconf['defaultMod'] = $MCONF['defaultMod'];
441 // Navigation Frame Script (GET params could be added)
442 if ($MCONF['navFrameScript']) {
443 $navFrameScript = explode('?', $MCONF['navFrameScript']);
444 $navFrameScript = $navFrameScript[0];
445 if (@file_exists
($path.'/'.$navFrameScript)) {
446 $modconf['navFrameScript'] = $this->getRelativePath(PATH_typo3
,$fullpath.'/'.$MCONF['navFrameScript']);
449 // additional params for Navigation Frame Script: "&anyParam=value&moreParam=1"
450 if ($MCONF['navFrameScriptParam']) {
451 $modconf['navFrameScriptParam'] = $MCONF['navFrameScriptParam'];
454 } else $modconf = 'notFound';
459 * Returns true if the internal BE_USER has access to the module $name with $MCONF (based on security level set for that module)
461 * @param string Module name
462 * @param array MCONF array (module configuration array) from the modules conf.php file (contains settings about what access level the module has)
463 * @return boolean True if access is granted for $this->BE_USER
465 function checkModAccess($name,$MCONF) {
466 if ($MCONF['access']) {
467 $access=strtolower($MCONF['access']);
468 // Checking if admin-access is required
469 if (strstr($access,'admin')) { // If admin-permissions is required then return true if user is admin
470 if ($this->BE_USER
->isAdmin()) {return true;}
472 // This will add modules to the select-lists of user and groups
473 if (strstr($access,'user')) { $this->modListUser
[]=$name; }
474 if (strstr($access,'group')) { $this->modListGroup
[]=$name; }
475 // This checks if a user is permitted to access the module
476 if ($this->BE_USER
->isAdmin() ||
$this->BE_USER
->check('modules',$name)) {return true;} // If admin you can always access a module
478 } else return true; // If conf[access] is not set, then permission IS granted!
482 * Parses the moduleArray ($TBE_MODULES) into a internally useful structure.
483 * Returns an array where the keys are names of the module and the values may be true (only module) or an array (of submodules)
485 * @param array moduleArray ($TBE_MODULES)
486 * @return array Output structure with available modules
488 function parseModulesArray($arr) {
490 if (is_array($arr)) {
491 foreach($arr as $mod => $subs) {
492 $mod = $this->cleanName($mod); // clean module name to alphanum
495 $subsArr = t3lib_div
::trimExplode(',', $subs);
496 foreach($subsArr as $subMod) {
497 $subMod = $this->cleanName($subMod);
499 $theMods[$mod][] = $subMod;
512 * The $str is cleaned so that it contains alphanumerical characters only. Modules must only consist of these characters
514 * @param string String to clean up
517 function cleanName ($str) {
518 return ereg_replace('[^A-Za-z0-9]*','',$str);
522 * Get relative path for $destDir compared to $baseDir
524 * @param string Base directory
525 * @param string Destination directory
526 * @return string The relative path of destination compared to base.
528 function getRelativePath($baseDir,$destDir){
530 // a special case , the dirs are equals
531 if ($baseDir == $destDir){
535 $baseDir = ereg_replace ('^/', '', $baseDir); // remove beginning
536 $destDir = ereg_replace ('^/', '', $destDir);
542 $slash_pos = strpos ($destDir, '/');
543 if (substr($destDir, 0, $slash_pos) == substr($baseDir, 0, $slash_pos)){
544 $baseDir = substr($baseDir, $slash_pos+
1);
545 $destDir = substr($destDir, $slash_pos+
1);
549 } while($found == true);
551 $slashes = strlen ($baseDir) - strlen (str_replace('/', '', $baseDir));
552 for($i=0;$i < $slashes;$i++
) {
553 $destDir = '../'.$destDir;
560 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['t3lib/class.t3lib_loadmodules.php']) {
561 include_once($TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['t3lib/class.t3lib_loadmodules.php']);