* Added support for listing and calling methods in new installer
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / modules / database / class.tx_install_module_database.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 require_once(PATH_t3lib.'class.t3lib_install.php');
29
30 /**
31 * $Id$
32 *
33 * @author Thomas Hempel <thomas@work.de>
34 * @author Ingo Renner <ingo@typo3.org>
35 */
36 class tx_install_module_database extends tx_install_module_base {
37 protected $moduleKey = 'database';
38 protected $priority = IMPORTANT;
39
40 /*
41 * API FUNCTIONS
42 */
43 /**
44 * This is the main method
45 */
46 public function main() {
47 }
48
49 /*
50 * CHECK FUNCTIONS
51 */
52
53 /**
54 * Checks if the database can be connected.
55 *
56 * @param string $host
57 * @param string $username
58 * @param string $password
59 * @return boolean
60 */
61 public function checkDatabaseConnect($host = TYPO3_db_host, $username = TYPO3_db_username, $password = TYPO3_db_password) {
62 if (!$GLOBALS['TYPO3_DB']->sql_pconnect($host, $username, $password)) {
63 $this->addError('LLL:msg_database_error_cantconnect');
64 return false;
65 }
66 return true;
67 }
68
69 public function checkSelectDatabase($host = TYPO3_db_host, $username = TYPO3_db_username, $password = TYPO3_db_password, $db = TYPO3_db) {
70 if (!$this->checkDatabaseConnect($host, $username, $password)) return false;
71 if (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
72 $this->addError(sprintf($this->get_LL('msg_database_error_cantselectdb'), TYPO3_db));
73 return false;
74 }
75 return true;
76 }
77
78
79 /*
80 * USER FUNCTIONS
81 */
82
83 /**
84 * Returns the list of available databases (with access-check based on username/password)
85 *
86 * @return [type] ...
87 */
88 public function getDatabaseList() {
89 $dbArr = array();
90 $dbList = array();
91 $localconfCache = $this->basicsObject->getLocalconfCache();
92
93 if ($GLOBALS['TYPO3_DB']->sql_pconnect(
94 $localconfCache['db']['typo_db_host'],
95 $localconfCache['db']['typo_db_username'],
96 $localconfCache['db']['typo_db_password'])
97 ) {
98 $dbArr = $GLOBALS['TYPO3_DB']->admin_get_dbs();
99
100 foreach ($dbArr as $dbName) {
101 $dbList[$dbName] = $dbName;
102 }
103 }
104
105 return $dbList;
106 }
107
108 /*
109 * INSTALLER STEP METHODS
110 */
111
112 /**
113 * Connects to database.
114 *
115 * @param static fields for form (hidden fields)
116 * @return string
117 */
118 public function connectDatabase($staticFields) {
119 // get all options for this step
120 $options = array (
121 'typo_db_host' => $GLOBALS['MCA']['database']['options']['typo_db_host'],
122 'typo_db_username' => $GLOBALS['MCA']['database']['options']['typo_db_username'],
123 'typo_db_password' => $GLOBALS['MCA']['database']['options']['typo_db_password']
124 );
125
126 $formConfig = array (
127 'type' => 'form',
128 'value' => array(
129 'options' => array(
130 'name' => 'form_connectDatabase',
131 'submit' => $this->get_LL('label_next_step'),
132 ),
133 'hidden' => $staticFields
134 )
135 );
136
137 foreach ($options as $optionName => $optionConfig) {
138 $elementConfig = $this->pObj->getViewObject()->renderOption($optionName, $optionConfig);
139 if ($elementConfig !== false) {
140 $formConfig['value']['elements'][] = $elementConfig;
141 }
142 }
143
144 return $this->pObj->getViewObject()->render($formConfig);
145 }
146
147 public function connectDatabaseProcess($staticFields) {
148 // try to connect with the given values
149 $connectResult = $this->checkDatabaseConnect($this->env['typo_db_host'], $this->env['typo_db_username'], $this->env['typo_db_password']);
150 if(!$connectResult) {
151 return false;
152 }
153
154 // if connection was sucessfull, write to localconf cache aand save it to file
155 $this->basicsObject->addDbDataToLocalconf(array(
156 'typo_db_host' => $this->env['typo_db_host'],
157 'typo_db_username' => $this->env['typo_db_username'],
158 'typo_db_password' => $this->env['typo_db_password']
159 ));
160
161 if (!$this->basicsObject->saveLocalconf()) return false;
162
163 return true;
164 }
165
166 /**
167 * Provides the form for selecting or creating the database
168 */
169 public function createDatabase($staticFields) {
170 global $MCA;
171
172 // get all options for this step
173 $options = array (
174 'typo_db' => $MCA['database']['options']['typo_db'],
175 'typo_db_new' => $MCA['database']['options']['typo_db_new'],
176 );
177
178 $formConfig = array (
179 'type' => 'form',
180 'value' => array (
181 'options' => array (
182 'name' => 'form_createDatabase',
183 'submit' => $this->get_LL('label_next_step'),
184 ),
185 'hidden' => $staticFields
186 )
187 );
188
189 foreach ($options as $optionName => $optionConfig) {
190 $elementConfig = $this->pObj->getViewObject()->renderOption($optionName, $optionConfig);
191 if ($elementConfig !== false) {
192 $formConfig['value']['elements'][] = $elementConfig;
193 }
194 }
195
196 return $this->pObj->getViewObject()->render($formConfig);
197 }
198
199
200 /**
201 * Does the processing of creating the database
202 */
203 public function createDatabaseProcess($staticFields) {
204 // check if a database was selected or if a new databse was filled in
205 if (empty($this->env['typo_db']) && empty($this->env['typo_db_new'])) {
206 $this->addError('LLL:msg_database_warning_selectdb');
207 return false;
208 }
209
210 // set an existing database or try to create a new one. If a new name was entered, try to create new one
211 if (!empty($this->env['typo_db_new'])) {
212 // check name
213 if (!ereg('[^[:alnum:]_-]', $this->env['typo_db_new'])) {
214 // try to create the database
215 if ($this->checkDatabaseConnect()) {
216 $GLOBALS['TYPO3_DB']->admin_query('CREATE DATABASE '.$this->env['typo_db_new'].' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci');
217 $res = $GLOBALS['TYPO3_DB']->admin_query('SHOW DATABASES');
218 $tables = array();
219 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res)) {
220 $tables[] = $row;
221 }
222
223 if(t3lib_div::inArray($tables, $this->env['typo_db_new'])) {
224 // db created -> write name to localconf
225 $this->basicsObject->addDbDataToLocalconf(array('typo_db' => $this->env['typo_db_new']));
226 if($this->basicsObject->saveLocalconf()) {
227 return true;
228 }
229 } else $this->addError(sprintf($this->get_LL('msg_database_error_couldnotcreate'), $this->env['typo_db_new']), WARNING, 'fields', 'typo_db_new');
230 }
231 } else $this->addError(sprintf($this->get_LL('msg_database_warning_invalidname'), $this->env['typo_db_new']), WARNING, 'fields', 'typo_db_new');
232 // if we reach this point, something went wrong
233 return false;
234 } else {
235 $this->basicsObject->addDbDataToLocalconf(array('typo_db' => $this->env['typo_db']));
236 if (!$this->basicsObject->saveLocalconf()) {
237 return false;
238 }
239 }
240
241 return true;
242 }
243
244
245 /**
246 * Provides the form for initial database import.
247 */
248 public function createTables($staticFields) {
249 $sFiles = t3lib_div::getFilesInDir(PATH_typo3conf,'sql',1,1);
250
251 // Check if default database scheme "database.sql" already exists, otherwise create it
252 if (!strstr(implode(',', $sFiles).',', '/database.sql,')) {
253 array_unshift($sFiles, $this->get_LL('label_database_defaulttables'));
254 }
255
256 $elements = array();
257 foreach ($sFiles as $f) {
258 if ($f == $this->get_LL('label_database_defaulttables')) {
259 $key = 'CURRENT_TABLES+STATIC';
260 } else {
261 $key = htmlspecialchars($f);
262 }
263
264 $elements['import|'.$key] = htmlspecialchars(basename($f));
265 }
266
267 $formConfig = array (
268 'type' => 'form',
269 'value' => array (
270 'options' => array (
271 'name' => 'form_createTables',
272 'submit' => $this->get_LL('label_next_step'),
273 ),
274 'hidden' => $staticFields,
275 'elements' => array (
276 array (
277 'type' => 'formelement',
278 'value' => array (
279 'label' => 'label_selectdump',
280 'elementType' => 'selectbox',
281 'options' => array (
282 'name' => 'L',
283 'elements' => $elements
284 )
285 )
286 )
287 )
288 )
289 );
290
291 return $this->pObj->getViewObject()->render($formConfig);
292 }
293
294 /**
295 * Does the processing for initial database import
296 */
297 public function createTablesProcess($staticFields) {
298 if (!$GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
299 $this->addError('LLL:msg_database_error_cantconnect', CRITICAL);
300 return false;
301 }
302
303 if (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
304 $this->addError(sprintf($this->get_LL('LLL:msg_database_error_cantselectdb'), TYPO3_db), CRITICAL);
305 return false;
306 }
307
308 $tblFileContent = t3lib_div::getUrl(PATH_t3lib.'stddb/tables.sql');
309
310 reset($GLOBALS['TYPO3_LOADED_EXT']);
311 foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $loadedExtConf) {
312 if (is_array($loadedExtConf) && $loadedExtConf['ext_tables.sql']) {
313 $tblFileContent.= chr(10).chr(10).chr(10).chr(10).t3lib_div::getUrl($loadedExtConf['ext_tables.sql']);
314 }
315 }
316
317 $t3lib_install = t3lib_div::makeInstance('t3lib_install');
318 $statements = $t3lib_install->getStatementArray($tblFileContent, 1);
319
320 list($statements_table, $insertCount) = $t3lib_install->getCreateTables($statements, 1);
321
322 // create tables and count them
323 $createCount = 0;
324 foreach ($statements as $tableName => $query) {
325 $res = $GLOBALS['TYPO3_DB']->admin_query($query);
326 $createCount++;
327 }
328
329 // Make a database comparison because some tables that are defined twice have not been created at this point. This applies to the "pages.*" fields defined in sysext/cms/ext_tables.sql for example.
330 $fileContent = implode(chr(10), $t3lib_install->getStatementArray($tblFileContent,1,'^CREATE TABLE '));
331 $FDfile = $t3lib_install->getFieldDefinitions_sqlContent($fileContent);
332 $FDdb = $t3lib_install->getFieldDefinitions_database();
333 $diff = $t3lib_install->getDatabaseExtra($FDfile, $FDdb);
334 $update_statements = $t3lib_install->getUpdateSuggestions($diff);
335 if (is_array($update_statements['add'])) {
336 foreach ($update_statements['add'] as $statement) {
337 $res = $GLOBALS['TYPO3_DB']->admin_query($statement);
338 }
339 }
340
341 return true;
342 }
343
344 /**
345 * Provides a form for creating a new admin user
346 */
347 public function createAdmin($staticFields) {
348 $formConfig = array (
349 'type' => 'form',
350 'value' => array (
351 'options' => array (
352 'name' => 'form_getlanguage',
353 'submit' => $this->get_LL('label_next_step'),
354 ),
355 'hidden' => $staticFields,
356 'elements' => array (
357 array (
358 'type' => 'formelement',
359 'value' => array (
360 'label' => 'label_admin_username',
361 'elementType' => 'input',
362 'options' => array (
363 'name' => 'createadmin_username',
364 )
365 )
366 ),
367 array (
368 'type' => 'formelement',
369 'value' => array (
370 'label' => 'label_admin_password',
371 'elementType' => 'password',
372 'renderTwice' => true,
373 'options' => array (
374 'name' => 'createadmin_password'
375 )
376 )
377 )
378 )
379 )
380 );
381
382 return $this->pObj->getViewObject()->render($formConfig);
383 }
384
385 public function createAdminProcess($staticFields) {
386 if (ereg('[^[:alnum:]_-]', $this->env['createadmin_username'])) {
387 $this->addError(sprintf($this->get_LL('msg_warning_invalidusername'), $this->env['createadmin_username']), FATAL, 'fields', 'createadmin_username');
388 return false;
389 }
390
391 if (empty($this->env['createadmin_username'])) {
392 $this->addError($this->get_LL('msg_warning_emptyusername'), FATAL, 'fields', 'createadmin_username');
393 return false;
394 }
395
396 if ($this->env['createadmin_password1'] != $this->env['createadmin_password2']) {
397 $this->addError($this->get_LL('msg_warning_passwordmatch'), FATAL, 'fields', 'createadmin_password1');
398 return false;
399 }
400
401 if (empty($this->env['createadmin_password1'])) {
402 $viewObj = $this->addError($this->get_LL('msg_warning_emptypassword'), FATAL, 'fields', 'createadmin_password1');
403 return false;
404 }
405
406 // input data is OK ...
407
408 if (!$this->basicsObject->executeMethod(array('database', 'checkSelectDatabase'))) {
409 return false;
410 }
411
412 // connected to database ...
413
414 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'be_users', 'username='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->env['createadmin_username'], 'be_users'));
415 if($GLOBALS['TYPO3_DB']->sql_num_rows($res) > 0) {
416 $this->addError(sprintf($this->get_LL('msg_warning_usernameexists'), $this->env['createadmin_username']), FATAL, 'fields', 'createadmin_username');
417 return false;
418 }
419
420 // no user with the entered name exist ... create
421
422 $insertFields = array(
423 'username' => strtolower($this->env['createadmin_username']),
424 'password' => md5($this->env['createadmin_password1']),
425 'admin' => 1,
426 'uc' => '',
427 'fileoper_perms' => 7,
428 'tstamp' => time(),
429 'crdate' => time()
430 );
431
432 $GLOBALS['TYPO3_DB']->exec_INSERTquery('be_users', $insertFields);
433
434 return true;
435 }
436
437 /**
438 * Compares the current database with a given SQL file. If the argument is null it uses the
439 * default file t3lib/stddb/tables.sql.
440 *
441 * @param string $sqlFile: The file that is used for comparision; NULL for default file
442 * @return HTML-Code or false if an error occured
443 */
444 public function analyzeCompareFile($sqlFile = NULL) {
445 if (is_null($sqlFile)) {
446 $sqlFile = PATH_t3lib.'stddb/tables.sql';
447 }
448
449 $tblFileContent = t3lib_div::getUrl($sqlFile);
450
451 // return an error if the given file was not found
452 if (!$tblFileContent) {
453 $this->addError(sprintf($this->get_LL('msg_database_error_filenotfound'), $sqlFile), FATAL);
454 return false;
455 }
456
457 /*
458 reset($GLOBALS['TYPO3_LOADED_EXT']);
459 foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $loadedExtConf) {
460 if (is_array($loadedExtConf) && $loadedExtConf['ext_tables.sql']) {
461 $tblFileContent.= chr(10).chr(10).chr(10).chr(10).t3lib_div::getUrl($loadedExtConf['ext_tables.sql']);
462 }
463 }
464
465 $t3lib_install = t3lib_div::makeInstance('t3lib_install');
466 $statements = $t3lib_install->getStatementArray($tblFileContent, 1);
467
468 list($statements_table, $insertCount) = $t3lib_install->getCreateTables($statements, 1);
469
470 $tblFileContent = t3lib_div::getUrl(PATH_t3lib.'stddb/tables.sql');
471 reset($GLOBALS['TYPO3_LOADED_EXT']);
472
473
474
475 $fileContent = implode(
476 $t3lib_install->getStatementArray($tblFileContent,1,'^CREATE TABLE '),
477 chr(10)
478 );
479 $FDfile = $t3lib_install->getFieldDefinitions_sqlContent($fileContent);
480
481 if (!count($FDfile)) {
482 $this->addError(sprintf('There were no "CREATE TABLE" definitions in the provided file: %s', PATH_t3lib.'stddb/tables.sql'), FATAL);
483 return false;
484 }
485
486 // Updating database...
487 /*
488 if (is_array($this->INSTALL['database_update'])) {
489 $FDdb = $this->getFieldDefinitions_database();
490 $diff = $this->getDatabaseExtra($FDfile, $FDdb);
491 $update_statements = $this->getUpdateSuggestions($diff);
492 $diff = $this->getDatabaseExtra($FDdb, $FDfile);
493 $remove_statements = $this->getUpdateSuggestions($diff,'remove');
494
495 $this->performUpdateQueries($update_statements['add'],$this->INSTALL['database_update']);
496 $this->performUpdateQueries($update_statements['change'],$this->INSTALL['database_update']);
497 $this->performUpdateQueries($remove_statements['change'],$this->INSTALL['database_update']);
498 $this->performUpdateQueries($remove_statements['drop'],$this->INSTALL['database_update']);
499
500 $this->performUpdateQueries($update_statements['create_table'],$this->INSTALL['database_update']);
501 $this->performUpdateQueries($remove_statements['change_table'],$this->INSTALL['database_update']);
502 $this->performUpdateQueries($remove_statements['drop_table'],$this->INSTALL['database_update']);
503 }
504 */
505
506 /*
507 // Init again / first time depending...
508 $FDdb = $t3lib_install->getFieldDefinitions_database();
509
510 $diff = $t3lib_install->getDatabaseExtra($FDfile, $FDdb);
511 $update_statements = $t3lib_install->getUpdateSuggestions($diff);
512
513 $diff = $t3lib_install->getDatabaseExtra($FDdb, $FDfile);
514 $remove_statements = $t3lib_install->getUpdateSuggestions($diff,'remove');
515
516 $tLabel = 'Update database tables and fields';
517
518 if ($remove_statements || $update_statements) {
519 $formContent = $this->generateUpdateDatabaseForm('get_form',$update_statements,$remove_statements,$action_type);
520 $this->message($tLabel,'Table and field definitions should be updated',"
521 There seems to be a number of differencies between the database and the selected SQL-file.
522 Please select which statements you want to execute in order to update your database:<br /><br />
523 ".$formContent."
524 ",2);
525 } else {
526 $formContent = $this->generateUpdateDatabaseForm('get_form',$update_statements,$remove_statements,$action_type);
527 $this->message($tLabel,'Table and field definitions are OK.',"
528 The tables and fields in the current database corresponds perfectly to the database in the selected SQL-file.
529 ",-1);
530 }
531
532 return $formContent;
533 */
534
535 return 'Here comes the result from the database analyzer';
536 }
537
538
539
540 private function displaySuggestions($arr, $excludeList='') {
541 $out='';
542 $out.='<tr><td bgcolor="#9BA1A8" align="center"><strong>'.$this->fw('Field name:').'</strong></td><td bgcolor="#9BA1A8" align="center"><strong>'.$this->fw('Info / Suggestion for the field:').'</strong></td></tr>';
543 $fC=0;
544 if (is_array($arr)) {
545 reset($arr);
546 while(list($fieldname, $fieldContent)=each($arr)) {
547 if (!t3lib_div::inList($excludeList,$fieldname) && substr($fieldname,0,strlen($this->deletedPrefixKey))!=$this->deletedPrefixKey && substr($fieldname,-1)!='.') {
548 $fieldContent = $this->fw($fieldContent);
549 if ($arr[$fieldname.'.']) {
550 $fieldContent.= '<hr />';
551 $fieldContent.= '<pre>'.trim($arr[$fieldname.'.']).'</pre>';
552 }
553 $out.='<tr><td bgcolor="#ABBBB4">'.$this->fw($fieldname).'</td><td bgcolor="#ABBBB4">'.$fieldContent.'</td></tr>';
554 $fC++;
555 }
556 }
557 }
558 $out= '<table border="0" cellpadding="2" cellspacing="2">'.$out.'</table>';
559 return array($out,$fC);
560 }
561
562
563 }
564
565 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/modules/database/class.tx_install_database.php']) {
566 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/modules/database/class.tx_install_database.php']);
567 }
568 ?>