* Installer: Improved the installer module.
[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 /*
38 * API FUNCTIONS
39 */
40 /**
41 * This is the main method
42 */
43 public function main() {
44 }
45
46 /*
47 * CHECK FUNCTIONS
48 */
49
50 /**
51 * Checks if the database can be connected.
52 *
53 * @param string $host
54 * @param string $username
55 * @param string $password
56 * @return boolean
57 */
58 public function checkDatabaseConnect($host = TYPO3_db_host, $username = TYPO3_db_username, $password = TYPO3_db_password) {
59 if (!$GLOBALS['TYPO3_DB']->sql_pconnect($host, $username, $password)) {
60 $this->addError('LLL:msg_database_error_cantconnect');
61 return false;
62 }
63
64 $this->pObj->getViewObject()->addMessage($this->get_LL('msg_database_connected'));
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 * METHODS
81 */
82
83 /**
84 * Renders an overview over the most interesting database releated things
85 *
86 */
87 public function renderOverview() {
88 // connection possible?
89 $message = $this->get_LL('title_typo_db_host').': '.TYPO3_db_host.'<br />'.
90 $this->get_LL('title_typo_db_username').': '.TYPO3_db_username.'<br />'.
91 $this->get_LL('title_typo_db_password').': '.TYPO3_db_password;
92
93 $messageConf = array (
94 'type' => 'message',
95 'value' => array (
96 'message' => '',
97 )
98
99 );
100
101 if ($this->checkSelectDatabase() == true) {
102 $messageConf['value']['severity'] = 'ok';
103 $messageConf['value']['label'] = $this->get_LL('msg_database_connected');
104
105 $t3lib_install = t3lib_div::makeInstance('t3lib_install');
106 $whichTables = $t3lib_install->getListOfTables();
107
108 $messageConf['value']['message'] = $message;
109
110 $messageConf = array($messageConf, array(
111 'type' => 'message',
112 'value' => array (
113 'severity' => 'ok',
114 'label' => $this->get_LL('title_module_database'),
115 'message' => sprintf($this->get_LL('msg_database_connectedto'), TYPO3_db, count($whichTables))
116 )
117 ));
118
119 } else {
120 $messageConf['value']['severity'] = 'error';
121 $messageConf['value']['label'] = $this->get_LL('msg_database_notconnected');
122
123 $message = $this->get_LL('msg_database_failedwith').'<br />'.$messageConf['value']['message'];
124 $message .= $this->pObj->getViewObject()->renderErrors(true);
125 // $messageConf['value']['message'] .= $this->pObj->getViewObject()->renderErrors();
126 $messageConf['value']['message'] = $message;
127 }
128
129 return $this->pObj->getViewObject()->render($messageConf);
130 }
131
132
133 /*
134 * USER FUNCTIONS
135 */
136
137 /**
138 * Returns the list of available databases (with access-check based on username/password)
139 *
140 * @return [type] ...
141 */
142 public function getDatabaseList() {
143 $dbArr = array();
144 $dbList = array();
145 $localconfCache = $this->basicsObject->getLocalconfCache();
146
147 if ($GLOBALS['TYPO3_DB']->sql_pconnect(
148 $localconfCache['db']['typo_db_host'],
149 $localconfCache['db']['typo_db_username'],
150 $localconfCache['db']['typo_db_password'])
151 ) {
152 $dbArr = $GLOBALS['TYPO3_DB']->admin_get_dbs();
153
154 foreach ($dbArr as $dbName) {
155 $dbList[$dbName] = $dbName;
156 }
157 }
158
159 return $dbList;
160 }
161
162 /*
163 * INSTALLER STEP METHODS
164 */
165
166 /**
167 * Returns form config for database connection data
168 *
169 * @param static fields for form (hidden fields)
170 * @return string
171 */
172 public function databaseConnectionData() {
173 // get all options for this step
174
175 $elements = array(
176
177 'advanced' => array (
178 $this->pObj->getViewObject()->renderOption('typo_db_host', $GLOBALS['MCA']['database']['options']['typo_db_host'])
179 ),
180
181 'normal' => array (
182 $this->pObj->getViewObject()->renderOption('typo_db_username', $GLOBALS['MCA']['database']['options']['typo_db_username']),
183 $this->pObj->getViewObject()->renderOption('typo_db_password', $GLOBALS['MCA']['database']['options']['typo_db_password'])
184 )
185
186 );
187
188 return $elements;
189 }
190
191 public function connectDatabaseProcess() {
192 // try to connect with the given values
193 $connectResult = $this->checkDatabaseConnect($this->env['typo_db_host'], $this->env['typo_db_username'], $this->env['typo_db_password']);
194 if(!$connectResult) {
195 return false;
196 }
197
198 // if connection was sucessfull, write to localconf cache and save it to file
199 $this->basicsObject->addDbDataToLocalconf(array(
200 'typo_db_host' => $this->env['typo_db_host'],
201 'typo_db_username' => $this->env['typo_db_username'],
202 'typo_db_password' => $this->env['typo_db_password']
203 ));
204
205 if (!$this->basicsObject->saveLocalconf()) return false;
206
207 return true;
208 }
209
210 /**
211 * Provides the form for selecting or creating the database
212 */
213 public function selectDatabaseForm() {
214 // get all options for this step
215 $elements = array ('normal' => array (
216 'typo_db' => $this->pObj->getViewObject()->renderOption('typo_db', $GLOBALS['MCA']['database']['options']['typo_db']),
217 'typo_db_new' => $this->pObj->getViewObject()->renderOption('typo_db_new', $GLOBALS['MCA']['database']['options']['typo_db_new']),
218 ));
219 return $elements;
220 }
221
222
223 /**
224 * Does the processing of creating the database
225 */
226 public function createDatabase() {
227 // check if a database was selected or if a new databse was filled in
228 if (empty($this->env['typo_db']) && empty($this->env['typo_db_new'])) {
229 $this->addError('LLL:msg_database_warning_selectdb');
230 return false;
231 }
232
233 // set an existing database or try to create a new one. If a new name was entered, try to create new one
234 if (!empty($this->env['typo_db_new'])) {
235
236 // check name
237 if (!ereg('[^[:alnum:]_-]', $this->env['typo_db_new'])) {
238 // try to create the database
239 if ($this->checkDatabaseConnect()) {
240 $res = $GLOBALS['TYPO3_DB']->admin_query('CREATE DATABASE '.$this->env['typo_db_new'].' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci');
241 $res = $GLOBALS['TYPO3_DB']->admin_query('SHOW DATABASES');
242 $databases = array();
243 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res)) {
244 $databases[] = $row[0];
245 }
246
247 if(t3lib_div::inArray($databases, $this->env['typo_db_new'])) {
248 // db created -> write name to localconf
249 $this->basicsObject->addDbDataToLocalconf(array('typo_db' => $this->env['typo_db_new']));
250 if($this->basicsObject->saveLocalconf()) {
251 return true;
252 }
253 } else {
254 $this->addError(sprintf($this->get_LL('msg_database_error_couldnotcreate'), $this->env['typo_db_new']), WARNING, 'fields', 'typo_db_new');
255 }
256 }
257 } else {
258 $this->addError(sprintf($this->get_LL('msg_database_warning_invalidname'), $this->env['typo_db_new']), WARNING, 'fields', 'typo_db_new');
259 }
260
261 // if we reach this point, something went wrong
262 return false;
263 } else {
264 // use an existing database
265 // try to select that database
266 if ($this->checkSelectDatabase(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password, $this->env['typo3_db'])) {
267 $this->basicsObject->addDbDataToLocalconf(array('typo_db' => $this->env['typo_db']));
268 if (!$this->basicsObject->saveLocalconf()) {
269 return false;
270 }
271 } else {
272 // database could not be selected
273 return false;
274 }
275
276 }
277
278 return true;
279 }
280
281
282 /**
283 * Searches for sql files in typo3conf directory. Returns true or false wether some files where or not.
284 *
285 * @return boolean
286 */
287 public function checkForStaticFiles() {
288 $sFiles = t3lib_div::getFilesInDir(PATH_typo3conf,'sql',1,1);
289 return (count($sFiles) > 0);
290 }
291
292
293 /**
294 * Provides the form for initial database import.
295 */
296 public function selectStaticFileForm() {
297 $sFiles = t3lib_div::getFilesInDir(PATH_typo3conf,'sql',1,1);
298
299 // Check if default database scheme "database.sql" already exists, otherwise create it
300 if (!strstr(implode(',', $sFiles).',', '/database.sql,')) {
301 array_unshift($sFiles, $this->get_LL('label_database_defaulttables'));
302 }
303
304 $elements = array();
305 foreach ($sFiles as $f) {
306 if ($f == $this->get_LL('label_database_defaulttables')) {
307 $key = 'CURRENT_TABLES+STATIC';
308 } else {
309 $key = htmlspecialchars($f);
310 }
311
312 $elements['import|'.$key] = htmlspecialchars(basename($f));
313 }
314
315 $elements = array ( 'normal' => array (
316 array (
317 'type' => 'formelement',
318 'value' => array (
319 'label' => 'label_selectdump',
320 'elementType' => 'selectbox',
321 'options' => array (
322 'name' => 'action',
323 'elements' => $elements
324 )
325 )
326 )
327 ));
328
329 return $elements;
330 }
331
332 /**
333 * Does the processing for initial database import
334 */
335 public function importTables() {
336 if (!$GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
337 $this->addError('LLL:msg_database_error_cantconnect', CRITICAL);
338 return false;
339 }
340
341 if (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
342 $this->addError(sprintf($this->get_LL('LLL:msg_database_error_cantselectdb'), TYPO3_db), CRITICAL);
343 return false;
344 }
345
346 if (!isset($this->env['action'])) $this->env['action'] = 'import|CURRENT_TABLES+STATIC';
347 $actionParts = t3lib_div::trimExplode('|', $this->env['action']);
348
349 if (preg_match('/^CURRENT_/', $actionParts[1])) {
350 if (!strcmp($actionParts[1],'CURRENT_TABLES') || !strcmp($actionParts[1],'CURRENT_TABLES+STATIC')) {
351 $tblFileContent = t3lib_div::getUrl(PATH_t3lib.'stddb/tables.sql');
352
353 reset($GLOBALS['TYPO3_LOADED_EXT']);
354 while(list(,$loadedExtConf)=each($GLOBALS['TYPO3_LOADED_EXT'])) {
355 if (is_array($loadedExtConf) && $loadedExtConf['ext_tables.sql']) {
356 $tblFileContent.= chr(10).chr(10).chr(10).chr(10).t3lib_div::getUrl($loadedExtConf['ext_tables.sql']);
357 }
358 }
359 }
360 if (!strcmp($actionParts[1],'CURRENT_STATIC') || !strcmp($actionParts[1],'CURRENT_TABLES+STATIC')) {
361 reset($GLOBALS['TYPO3_LOADED_EXT']);
362 while(list(,$loadedExtConf)=each($GLOBALS['TYPO3_LOADED_EXT'])) {
363 if (is_array($loadedExtConf) && $loadedExtConf['ext_tables_static+adt.sql']) {
364 $tblFileContent.= chr(10).chr(10).chr(10).chr(10).t3lib_div::getUrl($loadedExtConf['ext_tables_static+adt.sql']);
365 }
366 }
367 }
368 } elseif (@is_file($actionParts[1])) {
369 $tblFileContent = t3lib_div::getUrl($actionParts[1]);
370 }
371
372 if (empty($tblFileContent)) {
373 $this->addError($this->get_LL('msg_database_error_emptydump'));
374 return false;
375 }
376
377 $t3lib_install = t3lib_div::makeInstance('t3lib_install');
378 $statements = $t3lib_install->getStatementArray($tblFileContent, 1);
379
380 // list($statements_table, $insertCount) = $t3lib_install->getCreateTables($statements, 1);
381
382 // create tables and count them
383 $createCount = 0;
384 $error = false;
385 $resultItems = array();
386 foreach ($statements as $queryIndex => $query) {
387
388 eregi('^create[[:space:]]*table[[:space:]]*[`]?([[:alnum:]_]*)[`]?',substr($query,0,100),$reg);
389 $tableName = trim($reg[1]);
390
391 $res = $GLOBALS['TYPO3_DB']->admin_query($query);
392 if (!$res) {
393 if (!array_key_exists($tableName, $resultItems)) {
394 $error = true;
395 $resultItems[$tableName] = array ('status' => 'warning', 'type' => 'plain', 'value' => sprintf($this->get_LL('msg_database_warning_tablecreatefailed'), $tableName, $GLOBALS['TYPO3_DB']->sql_error(), $query));
396 }
397 } else {
398 $resultItems[$tableName] = array ('status' => 'ok', 'type' => 'plain', 'value' => sprintf($this->get_LL('label_tablecreated'), $tableName));
399 $createCount++;
400 }
401 }
402
403 // 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.
404 $fileContent = implode(chr(10), $t3lib_install->getStatementArray($tblFileContent,1,'^CREATE TABLE '));
405 $FDfile = $t3lib_install->getFieldDefinitions_sqlContent($fileContent);
406 $FDdb = $t3lib_install->getFieldDefinitions_database();
407 $diff = $t3lib_install->getDatabaseExtra($FDfile, $FDdb);
408 $update_statements = $t3lib_install->getUpdateSuggestions($diff);
409 if (is_array($update_statements['add'])) {
410 foreach ($update_statements['add'] as $statement) {
411 $res = $GLOBALS['TYPO3_DB']->admin_query($statement);
412 if (!$res) {
413 $this->addError($this->get_LL('msg_database_warning_failedstatement').$statement);
414 $error = true;
415 }
416 }
417 }
418
419 $this->pObj->getViewObject()->addMessage($this->pObj->getViewObject()->render(array(
420 array('type' => 'plain', 'value' => $this->pObj->getViewObject()->renderTag('strong', ($error) ? $this->get_LL('msg_database_warning_failedstatements') : $this->get_LL('msg_database_tablescreated'))),
421 array('type' => 'list', 'value' => $resultItems)))
422 );
423
424 return ($error) ? false : true;
425 }
426
427 /**
428 * Provides a form for creating a new admin user
429 */
430 public function createAdminForm() {
431 $elements = array ( 'normal' => array (
432 array (
433 'type' => 'formelement',
434 'value' => array (
435 'label' => 'label_admin_username',
436 'elementType' => 'input',
437 'options' => array (
438 'name' => 'createadmin_username',
439 )
440 )
441 ),
442 array (
443 'type' => 'formelement',
444 'value' => array (
445 'label' => 'label_admin_password',
446 'elementType' => 'password',
447 'renderTwice' => true,
448 'options' => array (
449 'name' => 'createadmin_password'
450 )
451 )
452 )
453 ));
454
455 return $elements;
456 }
457
458 /**
459 * Processes the request for a new admin user. This might become obsolete in the next days!
460 *
461 * @param unknown_type $staticFields
462 * @return unknown
463 */
464 public function createAdmin() {
465 if (ereg('[^[:alnum:]_-]', $this->env['createadmin_username'])) {
466 $this->addError(sprintf($this->get_LL('msg_warning_invalidusername'), $this->env['createadmin_username']), FATAL, 'fields', 'createadmin_username');
467 return false;
468 }
469
470 if (empty($this->env['createadmin_username'])) {
471 $this->addError($this->get_LL('msg_warning_emptyusername'), FATAL, 'fields', 'createadmin_username');
472 return false;
473 }
474
475 if ($this->env['createadmin_password1'] != $this->env['createadmin_password2']) {
476 $this->addError($this->get_LL('msg_warning_passwordmatch'), FATAL, 'fields', 'createadmin_password1');
477 return false;
478 }
479
480 if (empty($this->env['createadmin_password1'])) {
481 $viewObj = $this->addError($this->get_LL('msg_warning_emptypassword'), FATAL, 'fields', 'createadmin_password1');
482 return false;
483 }
484
485 // input data is OK ...
486
487 if (!$this->basicsObject->executeMethod(array('database', 'checkSelectDatabase'))) {
488 return false;
489 }
490
491 // connected to database ...
492
493 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'be_users', 'username='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->env['createadmin_username'], 'be_users'));
494 if($GLOBALS['TYPO3_DB']->sql_num_rows($res) > 0) {
495 $this->addError(sprintf($this->get_LL('msg_warning_usernameexists'), $this->env['createadmin_username']), FATAL, 'fields', 'createadmin_username');
496 return false;
497 }
498
499 // no user with the entered name exist ... create
500
501 $insertFields = array(
502 'username' => strtolower($this->env['createadmin_username']),
503 'password' => md5($this->env['createadmin_password1']),
504 'admin' => 1,
505 'uc' => '',
506 'fileoper_perms' => 7,
507 'tstamp' => time(),
508 'crdate' => time()
509 );
510
511 $GLOBALS['TYPO3_DB']->exec_INSERTquery('be_users', $insertFields);
512
513 $this->pObj->getViewObject()->addMessage(sprintf($this->get_LL('msg_database_admincreated'), strtolower($this->env['createadmin_username'])));
514
515 return true;
516 }
517
518 /**
519 * Compares the current database with a given SQL file. If the argument is null it uses the
520 * default file t3lib/stddb/tables.sql.
521 *
522 * @param string $sqlFile: The file that is used for comparision; NULL for default file
523 * @return HTML-Code or false if an error occured
524 */
525 public function analyzeCompareFile($sqlFile = NULL) {
526 // Load default SQL file if none is given
527 if (is_null($sqlFile)) {
528 $sqlFile = PATH_t3lib.'stddb/tables.sql';
529 }
530 $tblFileContent = t3lib_div::getUrl($sqlFile);
531
532 // return an error if the given file was not found
533 if (!$tblFileContent) {
534 $this->addError(sprintf($this->get_LL('msg_database_error_filenotfound'), $sqlFile), FATAL);
535 return false;
536 }
537
538 // Add all SQL statements from all loaded extensions
539 reset($GLOBALS['TYPO3_LOADED_EXT']);
540 foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $loadedExtConf) {
541 if (is_array($loadedExtConf) && $loadedExtConf['ext_tables.sql']) {
542 $tblFileContent .= chr(10).chr(10).chr(10).chr(10).t3lib_div::getUrl($loadedExtConf['ext_tables.sql']);
543 }
544 }
545
546 // Get an instance of the t3lib_install class
547 $t3lib_install = t3lib_div::makeInstance('t3lib_install');
548
549 // Transform string of SQL statements into an array
550 $statements = $t3lib_install->getStatementArray($tblFileContent, 1);
551
552 // Get all the statements indexed for each table
553 list($statements_table, $insertCount) = $t3lib_install->getCreateTables($statements, 1);
554
555 // Get all create table statements
556 $fileContent = implode($t3lib_install->getStatementArray($tblFileContent, 1, '^CREATE TABLE '), chr(10));
557 // Get field definitions for each table and make sure they are clean
558 $FDfile = $t3lib_install->getFieldDefinitions_sqlContent($fileContent);
559
560 if (!count($FDfile)) {
561 $this->addError(sprintf($this->get_LL('msg_analyze_error_nocreatedefinitions'), PATH_t3lib.'stddb/tables.sql'), FATAL);
562 return false;
563 }
564
565 $FDdb = $t3lib_install->getFieldDefinitions_database();
566 $diff = $t3lib_install->getDatabaseExtra($FDfile, $FDdb);
567 $update_statements = $t3lib_install->getUpdateSuggestions($diff);
568 $diff = $t3lib_install->getDatabaseExtra($FDdb, $FDfile);
569 $remove_statements = $t3lib_install->getUpdateSuggestions($diff,'remove');
570
571 // Updating database...
572 if ($this->env['action'] == 'performUpdate') {
573 // Here the script has to perform the update of the database. The code is pasted from old install class.
574 $errors = $t3lib_install->performUpdateQueries($update_statements['add'], $this->env);
575 if (is_array($errors)) $this->addErrors($errors);
576
577 $errors = $t3lib_install->performUpdateQueries($update_statements['change'], $this->env);
578 if (is_array($errors)) $this->addErrors($errors);
579
580 $errors = $t3lib_install->performUpdateQueries($remove_statements['change'], $this->env);
581 if (is_array($errors)) $this->addErrors($errors);
582
583 $errors = $t3lib_install->performUpdateQueries($remove_statements['drop'], $this->env);
584 if (is_array($errors)) $this->addErrors($errors);
585
586 $errors = $t3lib_install->performUpdateQueries($update_statements['create_table'], $this->env);
587 if (is_array($errors)) $this->addErrors($errors);
588
589 $errors = $t3lib_install->performUpdateQueries($remove_statements['change_table'], $this->env);
590 if (is_array($errors)) $this->addErrors($errors);
591
592 $errors = $t3lib_install->performUpdateQueries($remove_statements['drop_table'], $this->env);
593 if (is_array($errors)) $this->addErrors($errors);
594
595 // Init again / first time depending...
596 $FDdb = $t3lib_install->getFieldDefinitions_database();
597 $diff = $t3lib_install->getDatabaseExtra($FDfile, $FDdb);
598 $update_statements = $t3lib_install->getUpdateSuggestions($diff);
599 $diff = $t3lib_install->getDatabaseExtra($FDdb, $FDfile);
600 $remove_statements = $t3lib_install->getUpdateSuggestions($diff,'remove');
601 }
602
603 // render form and / or message depending on result of DB compare
604 if ($remove_statements || $update_statements) {
605 $errors = $this->pObj->getViewObject()->getErrors();
606 if (count($errors['general']) > 0) $this->addError($this->get_LL('msg_database_warning_failedstatements'), WARNING, 'general', NULL, true);
607 $formContent .= $this->pObj->getViewObject()->renderErrors().$this->get_LL('msg_database_updateneeded').'<br />'.$this->generateUpdateDatabaseForm($update_statements, $remove_statements, $allErrors);
608 } else {
609 $formContent = $this->get_LL('msg_database_noupdateneeded');
610 }
611
612 return $formContent;
613 }
614
615
616
617 /**
618 * Generates the form for selecting actions that can be performed after a comparison.
619 *
620 * @param array $arr_update: All actions concerning database updates
621 * @param array $arr_remove: All actions concerning database removales
622 * @return HTML with complete formcode
623 */
624 private function generateUpdateDatabaseForm($arr_update, $arr_remove) {
625 $content = '';
626
627 // get elements for various states
628 $elements = array();
629
630 // Fields
631 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_update['add'], $this->get_LL('label_addfields')));
632 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_update['change'], $this->get_LL('label_changefields'), (t3lib_extMgm::isLoaded('dbal') ? false : true), $arr_update['change_currentValue']));
633 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_remove['change'], $this->get_LL('label_removeunusedfields')));
634 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop'], $this->get_LL('label_dropfields')));
635
636 // Tables
637 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_update['create_table'], $this->get_LL('label_addtables')));
638 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_remove['change_table'], $this->get_LL('label_removeunusedtables'), $this->setAllCheckBoxesByDefault));
639 $elements = array_merge($elements, $this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop_table'], $this->get_LL('label_removetables'), $this->setAllCheckBoxesByDefault));
640
641 // prepare config for rendering
642 $formConfig = array (
643 'type' => 'form',
644 'value' => array (
645 'options' => array (
646 'name' => 'form_analyzeCompareFile',
647 'id' => 'form_analyzeCompareFile',
648 'submit' => $this->get_LL('label_writechanges'),
649 'ajax' => true,
650 'action' => 'sendMethodForm(\'form_analyzeCompareFile\', \'database\', \'analyzeCompareFile\', displayMethodResult)',
651 ),
652 'hidden' => array (
653 'action' => 'performUpdate',
654 'target' => 'analyze_compareFile_result'
655 ),
656 'elements' => $elements
657 )
658 );
659
660 // render the form in viewObj
661 $content = $this->pObj->getViewObject()->render($formConfig);
662
663 return $content;
664 }
665
666 private function generateUpdateDatabaseForm_checkboxes($data, $label, $checked = true, $currentValue = array()) {
667 $result = array();
668
669 if (is_array($data)) {
670 $result[] = array(
671 'type' => 'formelement',
672 'value' => array (
673 'elementType' => 'fieldset',
674 'label' => $label
675 )
676 );
677
678 foreach ($data as $key => $statement) {
679 $result[] = array(
680 'type' => 'formelement',
681
682 'value' => array (
683 'elementType' => 'checkbox',
684 'label' => nl2br(htmlspecialchars($statement)).'<br /><br />'.((empty($currentValue[$key]) ? '' : '<em>Current value: '.$currentValue[$key].'</em><br />')),
685 'label_align' => 'right',
686 'options' => array (
687 'name' => $key,
688 'default' => $checked,
689 'id' => $key
690 )
691 )
692 );
693 }
694 }
695
696 return $result;
697 }
698
699 /**
700 * Displays a form for loading or reloading data into the so-called static tables
701 */
702 public function analyzeStaticTables() {
703 $content = '<p>'.$this->get_LL('msg_database_reloadstaticdata').'</p>';
704
705 // Read all table definitions
706 $tblFileContent = '';
707 reset($GLOBALS['TYPO3_LOADED_EXT']);
708 foreach($GLOBALS['TYPO3_LOADED_EXT'] as $loadedExtConf) {
709 if (is_array($loadedExtConf) && $loadedExtConf['ext_tables_static+adt.sql']) {
710 $tblFileContent.= chr(10).chr(10).chr(10).chr(10).t3lib_div::getUrl($loadedExtConf['ext_tables_static+adt.sql']);
711 }
712 }
713
714 // Get an instance of the t3lib_install class
715 $t3lib_install = t3lib_div::makeInstance('t3lib_install');
716
717 // Transform string of SQL statements into an array
718 $statements = $t3lib_install->getStatementArray($tblFileContent, 1);
719
720 // Get all the statements indexed for each table
721 list($statements_table, $insertCount) = $t3lib_install->getCreateTables($statements, 1);
722
723 // Get list of existing tables
724 $whichTables = $t3lib_install->getListOfTables();
725
726 // Drop/create selected static tables, load corresponding data
727 $actionMessages = array();
728 if ($this->env['action'] == 'performUpdate') {
729 foreach ($this->env as $table => $value) {
730 if ($this->env[$table] && isset($statements_table[$table])) {
731 $res = $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table);
732 $res = $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]);
733
734 // An error has occurred, issue message
735 if ($res === false) {
736 $actionMessages[] = '<p class="error error-fatal">'.sprintf($this->get_LL('msg_database_error_createtable'), $table).' ['.$this->get_LL('label_sqlerror').': '.$GLOBALS['TYPO3_DB']->sql_error().']'.'</p>';
737 }
738
739 // The table was successfully created, load the data
740 else {
741 if (!empty($insertCount[$table])) {
742 $statements_insert = $t3lib_install->getTableInsertStatements($statements, $table);
743 $dataErrors = array();
744 $lineCounter = 0;
745 foreach($statements_insert as $sql) {
746 $lineCounter++;
747 $res = $GLOBALS['TYPO3_DB']->admin_query($sql);
748 if ($res === false) {
749 $dataErrors[$lineCounter] = '('.$this->get_LL('label_line').' '.$lineCounter.') '.$GLOBALS['TYPO3_DB']->sql_error();
750 }
751 }
752 // Display result message. If errors occurred, list them after result message
753 $actionMessages[] = '<p>'.sprintf($this->get_LL('msg_database_staticdatareloaded'), $table, $lineCounter).'</p>';
754 if (count($dataErrors) > 0) {
755 $message = '<p class="error error-fatal">'.sprintf($this->get_LL('msg_database_error_insertingdata'), count($dataErrors));
756 foreach ($dataErrors as $sqlError) {
757 $message .= '<br />'.$sqlError;
758 }
759 $actionMessages[] = $message.'</p>';
760 }
761 }
762 }
763 }
764 }
765 }
766
767 // Assemble checkboxes for each table that could be updated
768 if (count($statements_table) > 0) {
769 $labels = array();
770 foreach ($statements_table as $table => $definition) {
771 $label = $table;
772 if (isset($insertCount[$table])) $label .= ' - '.$this->get_LL('label_rows').': '.$insertCount[$table];
773 if (isset($whichTables[$table])) $label .= ' - '.$this->get_LL('label_tableexists');
774 $labels[$table] = $label;
775 }
776 $checkboxes = $this->generateUpdateDatabaseForm_checkboxes($labels, $this->get_LL('label_selectimporttables'), false);
777
778 // prepare config for rendering
779 $formConfig = array (
780 'type' => 'form',
781 'value' => array (
782 'options' => array (
783 'name' => 'form_analyzeStaticTables',
784 'id' => 'form_analyzeStaticTables',
785 'submit' => $this->get_LL('label_writechanges'),
786 'ajax' => true,
787 'action' => 'sendMethodForm(\'form_analyzeStaticTables\', \'database\', \'analyzeStaticTables\', displayMethodResult)',
788 ),
789 'hidden' => array (
790 'action' => 'performUpdate',
791 'target' => 'analyze_staticTables_result'
792 ),
793 'elements' => $checkboxes
794 )
795 );
796
797 // render link to check/uncheck all checkboxes
798 // first get a list of all checkbox id's
799 $checkboxesID = array();
800 foreach ($checkboxes as $elementInfo) {
801 if ($elementInfo['value']['elementType'] == 'checkbox') {
802 $checkboxesID[] = $elementInfo['value']['options']['id'];
803 }
804 }
805 // assemble links with javascript calls to toggle checkboxes function
806 $checkboxJSArray = "new Array('".implode("','", $checkboxesID)."')";
807 $jsControl = '<a href="javascript:toggleCheckboxes('.$checkboxJSArray.', true)">'.$this->get_LL('label_selectall').'</a>';
808 $jsControl .= ' / ';
809 $jsControl .= '<a href="javascript:toggleCheckboxes('.$checkboxJSArray.', false)">'.$this->get_LL('label_deselectall').'</a>';
810 $content .= $this->pObj->getViewObject()->renderTag('p', $jsControl);
811
812 // render the form in viewObj
813 $content .= $this->pObj->getViewObject()->render($formConfig);
814 }
815
816 // If actions were performed, display their messages
817 if (count($actionMessages) > 0) {
818 foreach ($actionMessages as $aMessage) {
819 $content .= $aMessage;
820 }
821 }
822 return $content;
823 }
824
825 }
826
827 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/modules/database/class.tx_install_database.php']) {
828 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/modules/database/class.tx_install_database.php']);
829 }
830 ?>