Updated years from 2004 to 2005 + all function indexes. NO actual code changes done!
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_loadmodules.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
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 * This document provides a class that loads the modules for the TYPO3 interface.
29 *
30 * $Id$
31 * Modifications by Rene Fritz, 2001
32 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
33 *
34 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
35 * @internal
36 */
37 /**
38 * [CLASS/FUNCTION INDEX of SCRIPT]
39 *
40 *
41 *
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)
50 *
51 * TOTAL FUNCTIONS: 7
52 * (This index is automatically created/updated by the extension "extdeveval")
53 *
54 */
55
56
57
58
59
60
61
62
63
64
65
66
67 /**
68 * Load Backend Interface modules
69 *
70 * Typically instantiated like this:
71 * $this->loadModules = t3lib_div::makeInstance('t3lib_loadModules');
72 * $this->loadModules->load($TBE_MODULES);
73 *
74 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
75 * @package TYPO3
76 * @subpackage t3lib
77 */
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
81
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...
84
85 var $BE_USER = ''; // The backend user for use internally
86
87
88 /**
89 * Init.
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.
92 *
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.
95 * @return void
96 */
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;
101 } else {
102 $this->BE_USER = $GLOBALS['BE_USER'];
103 }
104
105 /*
106
107 $modulesArray might look like this when entering this function.
108 Notice the two modules added by extensions - they have a path attached
109
110 Array
111 (
112 [web] => list,info,perm,func
113 [file] => list
114 [doc] =>
115 [user] =>
116 [tools] => em,install,txphpmyadmin
117 [help] => about
118 [_PATHS] => Array
119 (
120 [tools_install] => /www/htdocs/typo3/32/coreinstall/typo3/ext/install/mod/
121 [tools_txphpmyadmin] => /www/htdocs/typo3/32/coreinstall/typo3/ext/phpmyadmin/modsub/
122 )
123
124 )
125
126 */
127 //
128 $this->absPathArray = $modulesArray['_PATHS'];
129 unset($modulesArray['_PATHS']);
130
131 /*
132 With the above data for modules the result of this function call will be:
133
134 Array
135 (
136 [web] => Array
137 (
138 [0] => list
139 [1] => info
140 [2] => perm
141 [3] => func
142 )
143
144 [file] => Array
145 (
146 [0] => list
147 )
148
149 [doc] => 1
150 [user] => 1
151 [tools] => Array
152 (
153 [0] => em
154 [1] => install
155 [2] => txphpmyadmin
156 )
157
158 [help] => Array
159 (
160 [0] => about
161 )
162
163 )
164 */
165 $theMods = $this->parseModulesArray($modulesArray);
166
167 /*
168 Originally modules were found in typo3/mod/
169 User defined modules were found in ../typo3conf/
170
171 Today almost all modules reside in extensions and they are found by the _PATHS array of the incoming $TBE_MODULES array
172 */
173 // Setting paths for 1) core modules (old concept from mod/) and 2) user-defined modules (from ../typo3conf)
174 $paths = array();
175 $paths['defMods'] = PATH_typo3.'mod/'; // Path of static modules
176 $paths['userMods'] = PATH_typo3.'../typo3conf/'; // local modules (maybe frontend specific)
177
178 // Traverses the module setup and creates the internal array $this->modules
179 foreach($theMods as $mods => $subMod) {
180 unset ($path);
181
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!
187 }
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'];
193 } else {
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'];
198 }
199 }
200 }
201
202 // if $theMainMod is not set (false) there is no access to the module !(?)
203 if ($theMainMod && isset($path)) {
204 $this->modules[$mods] = $theMainMod;
205
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;
214 }
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;
224 }
225 }
226 }
227 }
228 }
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);
233 }
234 }
235 }
236 }
237 /*
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.
240
241 Array
242 (
243 [web] => Array
244 (
245 [name] => web
246 [script] => dummy.php
247 [defaultMod] => list
248 [sub] => Array
249 (
250 [list] => Array
251 (
252 [name] => web_list
253 [script] => mod/web/list/../../../db_list.php
254 )
255
256 [info] => Array
257 (
258 [name] => web_info
259 [script] => mod/web/info/index.php
260 )
261
262 [perm] => Array
263 (
264 [name] => web_perm
265 [script] => mod/web/perm/index.php
266 )
267
268 [func] => Array
269 (
270 [name] => web_func
271 [script] => mod/web/func/index.php
272 )
273
274 )
275
276 )
277
278 [file] => Array
279 (
280 [name] => file
281 [script] => dummy.php
282 [sub] => Array
283 (
284 [list] => Array
285 (
286 [name] => file_list
287 [script] => mod/file/list/../../../file_list.php
288 )
289
290 )
291
292 )
293
294 [doc] => Array
295 (
296 [name] => doc
297 [script] => mod/doc/../../alt_doc.php
298 )
299
300 [user] => Array
301 (
302 [name] => user
303 [script] => dummy.php
304 [defaultMod] => task
305 )
306
307 [tools] => Array
308 (
309 [name] => tools
310 [script] => dummy.php
311 [sub] => Array
312 (
313 [em] => Array
314 (
315 [name] => tools_em
316 [script] => mod/tools/em/index.php
317 )
318
319 [install] => Array
320 (
321 [name] => tools_install
322 [script] => ext/install/mod/../../../install/index.php
323 )
324
325 [txphpmyadmin] => Array
326 (
327 [name] => tools_txphpmyadmin
328 [script] => ext/phpmyadmin/modsub/index.php
329 )
330
331 )
332
333 )
334
335 [help] => Array
336 (
337 [name] => help
338 [script] => dummy.php
339 [defaultMod] => welcome
340 [sub] => Array
341 (
342 [about] => Array
343 (
344 [name] => help_about
345 [script] => mod/help/about/index.php
346 )
347
348 )
349
350 )
351
352 )
353
354 */
355
356 #debug($this->modules);
357 #debug($GLOBALS['LANG']->moduleLabels);
358 }
359
360 /**
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
362 *
363 * @param string Module name
364 * @return string If found, the relative path from PATH_site
365 */
366 function checkExtensionModule($name) {
367 global $TYPO3_LOADED_EXT;
368
369 if (isset($this->absPathArray[$name])) {
370 return ereg_replace ('\/$', '', substr($this->absPathArray[$name],strlen(PATH_site)));
371 }
372 }
373
374 /**
375 * Here we check for the module.
376 * Return values:
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.
380 *
381 * @param string Module name
382 * @param string Absolute path to module
383 * @return mixed See description of function
384 */
385 function checkMod($name, $fullpath) {
386 $modconf=Array();
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']) {
397
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]) : '';
401
402 // Setting icon, either default or alternative:
403 if ($altIconAbsPath && @is_file($altIconAbsPath)) {
404 $MLANG['default']['tabs_images']['tab']=$this->getRelativePath(PATH_typo3,$altIconAbsPath);
405 } else {
406 // Setting default icon:
407 $MLANG['default']['tabs_images']['tab']=$this->getRelativePath(PATH_typo3,$fullpath.'/'.$MLANG['default']['tabs_images']['tab']);
408 }
409
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);
413 } else {
414 $MLANG['default']['tabs_images']['tab'] = PATH_typo3.$MLANG['default']['tabs_images']['tab'];
415 }
416 }
417
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.'_');
428 }
429 }
430
431 // Default script setup
432 if ($MCONF['script'] && @file_exists($path.'/'.$MCONF['script'])) {
433 $modconf['script'] = $this->getRelativePath(PATH_typo3,$fullpath.'/'.$MCONF['script']);
434 } else {
435 $modconf['script'] = 'dummy.php';
436 }
437 // Default tab setting
438 if ($MCONF['defaultMod']) {
439 $modconf['defaultMod'] = $MCONF['defaultMod'];
440 }
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']);
447 }
448 }
449 // additional params for Navigation Frame Script: "&anyParam=value&moreParam=1"
450 if ($MCONF['navFrameScriptParam']) {
451 $modconf['navFrameScriptParam'] = $MCONF['navFrameScriptParam'];
452 }
453 } else return false;
454 } else $modconf = 'notFound';
455 return $modconf;
456 }
457
458 /**
459 * Returns true if the internal BE_USER has access to the module $name with $MCONF (based on security level set for that module)
460 *
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
464 */
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;}
471 }
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
477
478 } else return true; // If conf[access] is not set, then permission IS granted!
479 }
480
481 /**
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)
484 *
485 * @param array moduleArray ($TBE_MODULES)
486 * @return array Output structure with available modules
487 */
488 function parseModulesArray($arr) {
489 $theMods = Array();
490 if (is_array($arr)) {
491 foreach($arr as $mod => $subs) {
492 $mod = $this->cleanName($mod); // clean module name to alphanum
493 if ($mod) {
494 if ($subs) {
495 $subsArr = t3lib_div::trimExplode(',', $subs);
496 foreach($subsArr as $subMod) {
497 $subMod = $this->cleanName($subMod);
498 if ($subMod) {
499 $theMods[$mod][] = $subMod;
500 }
501 }
502 } else {
503 $theMods[$mod] = 1;
504 }
505 }
506 }
507 }
508 return $theMods;
509 }
510
511 /**
512 * The $str is cleaned so that it contains alphanumerical characters only. Modules must only consist of these characters
513 *
514 * @param string String to clean up
515 * @return string
516 */
517 function cleanName ($str) {
518 return ereg_replace('[^A-Za-z0-9]*','',$str);
519 }
520
521 /**
522 * Get relative path for $destDir compared to $baseDir
523 *
524 * @param string Base directory
525 * @param string Destination directory
526 * @return string The relative path of destination compared to base.
527 */
528 function getRelativePath($baseDir,$destDir){
529 // By Rene Fritz
530 // a special case , the dirs are equals
531 if ($baseDir == $destDir){
532 return './';
533 }
534
535 $baseDir = ereg_replace ('^/', '', $baseDir); // remove beginning
536 $destDir = ereg_replace ('^/', '', $destDir);
537
538 $found = true;
539 $slash_pos=0;
540
541 do {
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);
546 } else {
547 $found = false;
548 }
549 } while($found == true);
550
551 $slashes = strlen ($baseDir) - strlen (str_replace('/', '', $baseDir));
552 for($i=0;$i < $slashes;$i++) {
553 $destDir = '../'.$destDir;
554 }
555 return $destDir;
556 }
557 }
558
559
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']);
562 }
563 ?>