* added new installer (ALPHA) code in typo3/sysext/install
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / mod / class.tx_install_basics.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2006-2007 Thomas Hempel (thomas@work.de)
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 /**
29 * This provides some basic methods that are needed by the install tool and it's modules.
30 *
31 * $Id$
32 *
33 * @author Thomas Hempel <thomas@work.de>
34 * @author Ingo Renner <ingo@typo3.org>
35 */
36 class tx_install_basics {
37 // Private
38 private $localconfCache = array(); // contains cached localconf file
39 private $localconfModified = false; // boolean: set to true if localconf needs to be saved
40
41 /**
42 * parent tx_install object
43 *
44 * @var tx_install
45 */
46 private $pObj;
47
48 private $categoryData = NULL;
49 private $moduleDeliverables = array('checks', 'options', 'methods');
50
51 /**
52 * Initializes the object.
53 *
54 * TODO move this into a __construct() method
55 *
56 * @param object The installer object. Needed to get access to some variables
57 * @return void
58 */
59 public function init($pObj) {
60 $this->pObj = $pObj;
61 }
62
63 /**
64 * Get's a label from the LOCAL_LANG variable in the main-class. This is a wrapper so that
65 * none has to know where the labels are stored internally.
66 *
67 * @param string $label: The name of the label
68 * @param string $alternative: A string the is returned if no label was found for the index
69 * @return The label from the locallang data
70 */
71 public function getLabel($label, $alternative = '') {
72 $langObj = $this->pObj->getLanguageObject();
73
74 if(substr($label, 0, 4) == 'LLL:') {
75 $label = substr($label, 4);
76 }
77
78 $resultLabel = $langObj->getLLL($label, $this->pObj->getLocalLang());
79
80 return (empty($resultLabel)) ? $alternative : $resultLabel;
81 }
82
83 /**
84 * Retrieves the absolute path to a module.
85 *
86 * @param string $moduleName: The name of the module
87 * @return mixed The absolute path to the module or FALSE if the module does not exist
88 */
89 public function getModulePath($moduleName) {
90 $moduleClass = $this->getModuleClass($moduleName);
91
92 $returnValue = false;
93 if($moduleClass) {
94 $returnValue = $this->getModulepathFromClass($moduleClass);
95 }
96
97 return $returnValue;
98 }
99
100 /**
101 * Enter description here...
102 *
103 * @param unknown_type $moduleClass
104 * @return string module path
105 */
106 private function getModulePathFromClass($moduleClass) {
107 $moduleClass = explode(':', $moduleClass);
108 $moduleClass = dirname($moduleClass[0]);
109
110 return $moduleClass.'/';
111 }
112
113 /**
114 * Retrieves the path to a module that is reachable from a browser.
115 *
116 * @param string $moduleName: The name of the module
117 * @return mixed The web path to the module or FALSE if the module does not exist
118 */
119 private function getModuleWebPath($moduleName) {
120 $moduleClass = $this->getModuleClass($moduleName);
121
122 $returnValue = false;
123 if($moduleClass) {
124 $returnValue = $this->getInstallerWebPath().'modules/'.$moduleName.'/';
125 }
126
127 return $returnValue;
128 }
129
130
131 /**
132 * Checks if a module exists or not.
133 *
134 * @param string name of the moldule that should be checked
135 * @return mixed The module class or false if the module was not registered.
136 */
137 private function getModuleClass($moduleName) {
138 $moduleClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['modules'][$moduleName];
139 $returnValue = false;
140
141 if(empty($moduleClass)) {
142 $this->addError(sprintf($this->getLabel('msg_error_noclassfile'), $moduleClass, $moduleName), FATAL);
143 } else {
144 $returnValue = $moduleClass;
145 }
146
147 return $returnValue;
148 }
149
150 public function getModuleDeliverables() {
151 return $this->moduleDeliverables;
152 }
153
154
155 /**
156 * Loads the config of a module and returns it in the result. If the config was already loaded
157 * the config is not loaded again.
158 *
159 * @param string $moduleName: The name of the requested module
160 * @return The
161 */
162 public function loadModuleConfig($moduleName) {
163 if(!is_array($GLOBALS['MCA'][$moduleName])) {
164 // get the path to the module
165 $modulePath = $this->getModulePath($moduleName);
166
167 // try to load config or return error
168 if(!file_exists($modulePath.'conf.php')) {
169 $this->addError(sprintf($this->getLabel('msg_error_nomoduleconfig'), $moduleName), FATAL);
170 return false;
171 }
172
173 require_once($modulePath.'conf.php');
174 }
175
176 return $GLOBALS['MCA'][$moduleName];
177 }
178
179
180 /**
181 * Instanciates a module and returns the instance
182 *
183 * @param string $moduleName: The name of the module that should be loaded
184 * @return mixed the request module or boolean false on failure
185 */
186 public function loadModule($moduleName) {
187 $moduleClassName = $this->getModuleClass($moduleName);
188 $returnValue = false;
189
190 if($moduleClassName) {
191 $modules = $this->pObj->getLoadedModules();
192
193
194 if(!is_object($modules[$moduleName])) {
195 if($this->loadModuleConfig($moduleName) !== false) {
196 // try to load the language data before we load the module
197 $this->loadModuleLocallang($moduleName);
198
199 // Now load the module
200 $module = t3lib_div::getUserObj($moduleClassName);
201 $module->init($this->pObj);
202 $this->pObj->addLoadedModule($moduleName, $module);
203
204 $returnValue = $module;
205 }
206 } else {
207 $returnValue = $modules[$moduleName];
208 }
209 }
210
211 return $returnValue;
212 }
213
214 public function loadModuleLocallang($moduleName) {
215 $modulePath = t3lib_extMgm::extPath('install').'modules/'.$moduleName.'/';
216
217 // try to load the language data before we load the module
218 $languageFile = $modulePath.'locallang.xml';
219 if(file_exists($languageFile)) {
220 $languageData = $this->pObj->getLanguageObject()->includeLLFile($languageFile, false);
221 $this->pObj->setLocalLang(t3lib_div::array_merge_recursive_overrule($this->pObj->getLocalLang(), $languageData));
222 }
223 }
224
225
226 /**
227 * Executes a requested method.
228 * The method has to be given in combination with the module. It can be given by strinf or array. If type is
229 * string the format is modulename:methodname. If the type is an array, the first array element has to be the
230 * module name and the second has to be the methodname.
231 *
232 * The module will be instaciated automatically if it is not already instanciated.
233 *
234 * @param mixed $method: The module and the method name
235 * @param mixed $args: If this is not NULL this argument will be passed to the called method as is
236 * @return mixed The return value of the method or false if something went wrong
237 */
238 public function executeMethod($method, $args = NULL) {
239 $returnValue = false;
240
241 if(!is_array($method)) {
242 $method = t3lib_div::trimExplode(':', $method);
243 }
244
245 $moduleName = $method[0];
246 $methodName = $method[1];
247 $moduleObj = $this->loadModule($moduleName);
248
249 if(!$moduleObj) {
250 $this->addError(sprintf($this->getLabel('msg_error_modulenotloaded'), $moduleName), FATAL);
251 $returnValue = false;
252 } else if(!method_exists($moduleObj, $methodName)) {
253 $this->addError(sprintf($this->getLabel('msg_error_methodnotfound'), $methodName, $moduleName), FATAL);
254 $returnValue = false;
255 } else if($args == NULL) {
256 $returnValue = $moduleObj->$methodName();
257 } else {
258 $returnValue = $moduleObj->$methodName($args);
259 }
260
261 return $returnValue;
262 }
263
264
265 /**
266 * Builds an array with all categories and sub-catagories of all registered modules.
267 * The category tree is saved in a class variable and is returned from there if it already
268 * exists.
269 *
270 * @return array module category data
271 */
272 public function getModuleCategoryData() {
273 $returnValue = false;
274
275 if(!is_null($this->categoryData)) {
276 $returnValue = $this->categoryData;
277 } else if(!is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['modules'])) {
278 $this->addError($this->getLabel('msg_error_nomodregister'));
279 } else {
280 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['modules'] as $modName => $modClass) {
281 $modConfig = $this->loadModuleConfig($modName);
282
283 $this->loadModuleLocallang($modName);
284
285 if($modConfig === false) {
286 continue;
287 }
288
289 foreach ($this->moduleDeliverables as $deliverable) {
290
291 if(is_array($modConfig[$deliverable])) {
292 foreach ($modConfig[$deliverable] as $name => $config) {
293 if(empty($config['categoryMain']) || empty($config['categorySub'])) {
294 continue;
295 }
296 // finally store the stuff
297 $this->categoryData[$config['categoryMain']][$config['categorySub']][$deliverable][$name] = $modName;
298
299 // add the labels to the label index
300 $this->pObj->addLabelIndex($config['categoryMain'], $config['categorySub'], $deliverable, $name, $config['title']);
301 $this->pObj->addLabelIndex($config['categoryMain'], $config['categorySub'], $deliverable, $name, $config['help']);
302 $this->pObj->addLabelIndex($config['categoryMain'], $config['categorySub'], $deliverable, $name, $config['description']);
303 }
304 }
305 }
306 }
307
308 $returnValue = $this->categoryData;
309 }
310
311 return $returnValue;
312 }
313
314 /**
315 * Returns all options, checks or methods that are assigned to the selected category.
316 */
317 public function getCategoryModuleDeliverables($categoryMain, $categorySub = null) {
318 $result = false;
319 $categoryData = $this->getModulecategoryData();
320 if (!isset($categoryData[$categoryMain])) {
321 $this->addError(sprintf($this->getLabel('msg_warning_nomaincat'), $categoryMain), FATAL);
322 }
323
324 $result = $categoryData[$categoryMain];
325 if (!is_null($categorySub)) {
326 if (!isset($result[$categorySub])) {
327 $this->addError(sprintf($this->getLabel('msg_warning_nosubcat'), $categorySub));
328 } else {
329 $result = $result[$categorySub];
330 }
331 }
332
333 return $result;
334 }
335
336 public function getModuleDeliverableConfigs($modName, $deliverable) {
337 $categoryData = $this->getModuleCategoryData();
338 t3lib_div($categoryData);
339 }
340
341
342 /**
343 * Retrieves the absolute path to the installer that is reachable with a webbrowser
344 *
345 * @return string Web-path to the installer
346 */
347 public function getInstallerWebPath() {
348 return t3lib_div::getIndpEnv('TYPO3_SITE_URL').$GLOBALS['TYPO3_LOADED_EXT']['install']['siteRelPath'];
349 }
350
351
352 /**
353 * Retrieves the saved password in localconf
354 *
355 * return string The password (md5 hash)
356 */
357 private function getPassword() {
358 if(isset($this->localconfCache['data']['BE']['installToolPassword'])) {
359 $installToolPassword = $this->localconfCache['data']['BE']['installToolPassword'];
360 } else {
361 $installToolPassword = $this->localconfCache['userSettings']['data']['BE']['installToolPassword'];
362 }
363
364 return $installToolPassword;
365 }
366
367
368 /**
369 * Tries to login with a given password. The password has to be submitted as plain text. The generation
370 * of the md5 hash will be created as first step inside the method.
371 * If the login does not work, an error message is saved in $this->errorMessage. This message is
372 * compatible to RENDER-OBJECT::MESSAGE
373 *
374 * @param string The plaintext password
375 * @return boolean true on successfull log in, false on failure
376 */
377 private function doLogIn($password) {
378 $md5Password = md5($password);
379 $loginSuccess = false;
380
381 if($md5Password == $this->getPassword()) {
382 $_SESSION['installTool']['password'] = $md5Password;
383 $loginSuccess = true;
384 } else {
385 $this->statusMessage = array(
386 'severity' => 'error',
387 'label' => $this->getLabel('login_not_sucessful'),
388 'message' => sprintf($this->getLabel('login_not_sucessful_message'), $md5Password)
389 );
390 }
391
392 return $loginSuccess;
393 }
394
395 /**
396 * Checks if a valid login is present.
397 * This method checks the data from localconf and
398 */
399 private function checkLogIn() {
400 $environment = $this->pObj->getEnvironment();
401 return ($environment['installTool']['password'] === $this->getPassword());
402 }
403
404
405 /**
406 * Creates a link for the current module and adds all given parameters to it
407 *
408 * @param array $params: A list of parameter names. The values will be retrieved from the environment
409 * @param array $paramValues: A list of key value pairs that will overrule the values in the resultstring
410 * @return string The URL to the module
411 */
412 private function getModuleLink_URL($params, $paramValues = array()) {
413 $moduleURL = 'index.php?';
414 $environment = $this->pObj->getEnvironment();
415 $parameterList = array('module' => $environment['module']);
416
417 // compile a list of params from the values inside the environment
418 if(is_array($params)) {
419 foreach($params as $param) {
420 $parameterList[$param] = $environment[$param];
421 }
422 }
423
424 // merge the list of parameters for overrule
425 $parameterList = t3lib_div::array_merge_recursive_overrule($parameterList, $paramValues);
426
427 // build URL string
428 $urlParameter = array();
429 foreach ($parameterList as $parameter => $parameterValue) {
430 $urlParameter[$parameter] = $parameter.'='.$parameterValue;
431 }
432
433 // create result string
434 $moduleURL .= implode('&', $urlParameter);
435
436 return $moduleURL;
437 }
438
439
440 /**
441 * Returns a full link with.
442 *
443 * @see getModuleLink_URL
444 *
445 * @param string $title: The title that is wrapped by the a-tag
446 * @param array $tagAttributes: A list of parameters that will be used for the tag
447 * @param array $params: A list of parameter names. The values will be retrieved from the environment
448 * @param array $paramValues: A list of key value pairs that will overrule the values in the resultstring
449 * @return string The complete HTML code for a link
450 */
451 private function getModuleLink($title, $tagAttributes, $params, $paramValues = array()) {
452 $url = $this->getModuleLink_URL($params, $paramValues);
453 $moduleLink = '<a href="'.$url.'"';
454
455 if(is_array($tagAttributes)) {
456 foreach ($tagAttributes as $attrName => $attrValue) {
457 $moduleLink .= ' '.$attrName.'="'.$attrValue.'"';
458 }
459 }
460 $moduleLink .= '>'.$title.'</a>';
461
462 return $moduleLink;
463 }
464
465
466 /**
467 * Modifies a localconf setting.
468 *
469 * Expects an array (multi-dimensional) which should be inserted/updated into localconf.
470 * @param array localconf array of values which should be changed
471 * @return void
472 */
473 private function modifyLocalconf($overrideArr) {
474 // if localconf cache is empty, load localconf file
475 if(!count($this->localconfCache)) {
476 $this->loadLocalconf();
477 }
478
479 // update data part
480 $this->localconfCache['data'] = t3lib_div::array_merge_recursive_overrule($this->localconfCache['data'], $overrideArr);
481 $this->localconfModified = 1;
482 }
483
484
485 /**
486 * Writes a value to the localconf cache at the given path.
487 *
488 * @param string $path
489 * @param string $value
490 * @param string $type: The type of the value
491 */
492 public function addToLocalconf($path, $value, $type) {
493 // var_dump(array('addToLocalconf', $value));
494 $path = t3lib_div::trimExplode(':', $path);
495
496 if (!empty($type)) {
497 settype($value, $type);
498 }
499
500 if ($path[0] == 'LC') {
501 array_shift($path);
502 }
503
504 $path = t3lib_div::trimExplode('/', $path[0]);
505
506 $data = &$this->localconfCache['data'];
507 foreach ($path as $pathSegment) {
508 $data = &$data[$pathSegment];
509 }
510 $data = $value;
511
512 $this->localconfModified = 1;
513 }
514
515 /**
516 * Adds special database data to localconf. This is a special method because database
517 * data is not stored in an array but plain in localconf file.
518 * Sets this->localconfModified to true!
519 *
520 * @param array $dbSettings associative array with optionname => optionvalue
521 */
522 public function addDbDataToLocalconf($dbSettings) {
523 if(!count($this->localconfCache)) {
524 $this->loadLocalconf();
525 }
526
527 foreach ($dbSettings as $varName => $varValue) {
528 $this->localconfCache['db'][$varName] = $varValue;
529 }
530
531 $this->localconfModified = 1;
532 }
533
534
535 /**
536 * Returns the value of value in the localconf file addressed by a path
537 *
538 * @param string $path to value
539 * @param string $default data if localconf value in path is empty
540 * @return mixed value stored in localconf.php
541 */
542 public function getLocalconfValue($path, $default = '') {
543 $path = t3lib_div::trimExplode(':', $path);
544
545 if ($path[0] == 'LC') {
546 array_shift($path);
547 }
548
549 if($path[0] == 'db') {
550 $data = $this->localconfCache['db'][$path[1]];
551 } else {
552 $data = $this->localconfCache['data'];
553
554 $path = t3lib_div::trimExplode('/', $path[0]);
555 if(is_array($path)) {
556 foreach ($path as $pathElement) {
557 $data = $data[$pathElement];
558 }
559 }
560
561 if (!isset($data)) {
562 $data = $default;
563 }
564 }
565
566 return $data;
567 }
568
569
570 public function getLocalconfPath($mainSec, $opName = NULL) {
571 $result = '';
572 if ($opName != NULL) {
573 $result = '$TYPO3_CONF_VARS[\''.$mainSec.'\'][\''.$opName.'\']';
574 } else {
575 $path = t3lib_div::trimExplode(':', $mainSec);
576 if ($path[0] == 'LC') {
577 array_shift($path);
578 }
579 if($path[0] == 'db') {
580 $result = '$'.$path[1];
581 } else {
582 $path = t3lib_div::trimExplode('/', $path[0]);
583 $result = '$TYPO3_CONF_VARS[\''.$path[0].'\'][\''.$path[1].'\']';
584 }
585 }
586
587 return $result;
588 }
589
590 /**
591 * Saves the localconf to file. Needs to be called from somewhere within the framework
592 *
593 * @param string absolute path to localconf file. If empty, defaults to typo3conf/localconf.php
594 * @return boolean
595 */
596 public function saveLocalconf($file = '') {
597 $hasNoErrors = true;
598
599 if($this->localconfModified) {
600 $viewObj = $this->pObj->getViewObject();
601
602 // build up file contents
603 $fileContents = '<?php'.$this->localconfCache['userSettings']['string']."\n".
604 $this->localconfCache['installToolToken']."\n\n";
605
606 // save db data
607 if(is_array($this->localconfCache['db'])) {
608 foreach ($this->localconfCache['db'] as $variableName => $variableValue) {
609 $fileContents .= '$'.$variableName.' = \''.stripslashes($variableValue).'\';'."\n";
610 }
611 $fileContents .= "\n";
612 }
613
614 // and the TYPO3_CONF_VARS
615 if(count($this->localconfCache['data']) > 0) {
616 foreach ($this->localconfCache['data'] as $mainSec => $secOptions) {
617 if (is_array($secOptions)) {
618 foreach ($secOptions as $secOptionsName => $secOptionsValue) {
619 $fileContents .= $this->getLocalconfPath($mainSec, $secOptionsName).' = '.var_export($secOptionsValue, true).';'.chr(10);
620 }
621 }
622 $fileContents .= chr(10);
623 }
624 }
625 $fileContents .= chr(10).'?>';
626
627 // initialize saving of localconf
628 $tmpExt = '.TMP.php';
629 $file = $file ? $file : PATH_typo3conf.'localconf.php';
630 $tmpFile = $file.$tmpExt;
631
632 // Checking write state of localconf.php
633 if(!$this->pObj->updateLocalconfAllowed()) {
634 $viewObj->addError($this->getLabel('msg_noallowupdate_flag'), FATAL);
635 $hasNoErrors = false;
636 }
637
638 if($hasNoErrors && !@is_writable($file)) {
639 $this->viewObj->addError(sprintf($this->getLabel('msg_filenotwriteable'), $file), FATAL);
640 $hasNoErrors = false;
641 }
642
643 // write localconf!
644 if ($hasNoErrors) {
645
646 if (!t3lib_div::writeFile($tmpFile,$fileContents)) {
647 $viewObj->addError(sprintf($this->getLabel('msg_filenotwriteable'), $tmpFile), FATAL);
648 $hasNoErrors = false;
649 } else if(strcmp(t3lib_div::getUrl($tmpFile), $fileContents)) {
650 @unlink($tmpFile);
651 $viewObj->addError(sprintf($this->getLabel('msg_error_filenotmatch'), $tmpFile), FATAL);
652 $hasNoErrors = false;
653 } else if(!@copy($tmpFile,$file)) {
654 $viewObj->addError(sprintf($this->getLabel('msg_error_filenotcopy'), $file, $tmpFile), FATAL);
655 $hasNoErrors = false;
656 } else {
657 @unlink($tmpFile);
658 $viewObj->addMessage(sprintf($this->getLabel('label_localconfwritten'), $file));
659 }
660 }
661 }
662
663 return $hasNoErrors;
664 }
665
666 /**
667 * Loads localconf file
668 *
669 * @param string absolute path to localconf file. If empty, defaults to typo3conf/localconf.php
670 * @return void
671 * @private
672 */
673 public function loadLocalconf($file = '') {
674 $TYPO3_CONF_VARS = array(); // needs to be declared LOCALLY
675
676 // load file
677 $file = $file ? $file:PATH_typo3conf.'localconf.php';
678 $fileContents = str_replace(chr(13),'',trim(t3lib_div::getUrl($file)));
679
680 // split file by the install script edit point token
681 if (preg_match('/<?php(.*?)\n((.*?)INSTALL SCRIPT EDIT POINT TOKEN(.*?))\n(.*)\?>$/s', $fileContents, $matches));
682
683 // get user settings
684 eval($matches[1]);
685 $userSettings = $TYPO3_CONF_VARS;
686 $TYPO3_CONF_VARS = array();
687
688 // eval PHP code -> the local variable $TYPO3_CONF_VARS is set now
689 eval($matches[5]);
690
691 // save cache
692 $this->localconfCache = array (
693 'userSettings' => array(
694 'string' => $matches[1],
695 'data' => $userSettings
696 ),
697 'installToolToken' => $matches[2],
698 'data' => $TYPO3_CONF_VARS,
699 'db' => array (
700 'typo_db_host' => $typo_db_host,
701 'typo_db_username' => $typo_db_username,
702 'typo_db_password' => $typo_db_password,
703 'typo_db' => $typo_db
704 )
705 );
706 }
707
708
709 /**
710 * Adds an error to the global view object.
711 *
712 * @param string $errorMsg: The error message or a label index (if prepended with LLL: its treated like a locallang label)
713 * @param integer $errorSeverity: The severity of the error (defined in view object!)
714 * @param string $errorContext: The context of the error (general or fields)
715 * @param string $errorField: The field where the error occured if errorContext is field
716 * @return void
717 */
718 public function addError($errorMsg, $errorSeverity = WARNING, $errorContext = 'general', $errorField = NULL, $getLL = true) {
719 $viewObj = $this->pObj->getViewObject();
720
721 if(substr($errorMsg, 0, 4) == 'LLL:') {
722 $errorMsg = $this->getLabel(substr($errorMsg, 4));
723 }
724 $error = array('severity' => $errorSeverity, 'message' => $errorMsg);
725
726 switch ($errorContext) {
727 case 'fields':
728 $viewObj->addError($errorContext, $error, $errorField);
729 break;
730 case 'general':
731 default:
732 $viewObj->addError($errorContext, $error);
733 break;
734 }
735 }
736
737 /**
738 * gets the localconf cache
739 *
740 * @return array
741 */
742 public function getLocalconfCache() {
743 return $this->localconfCache;
744 }
745 }
746
747 if(defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install_basics.php']) {
748 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install_basics.php']);
749 }
750 ?>