Prevented writing dumb DBAL configuration when using MySQL
[Packages/TYPO3.CMS.git] / typo3 / sysext / dbal / class.tx_dbal_installtool.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Xavier Perseguers <typo3@perseguers.ch>
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 * Hooks for TYPO3 Install Tool.
30 *
31 * $Id$
32 *
33 * @author Xavier Perseguers <typo3@perseguers.ch>
34 *
35 * @package TYPO3
36 * @subpackage dbal
37 */
38 class tx_dbal_installtool {
39
40 /**
41 * @var string
42 */
43 protected $templateFilePath = 'res/Templates/';
44
45 /**
46 * @var array
47 */
48 protected $supportedDrivers;
49
50 /**
51 * @var array
52 */
53 protected $availableDrivers;
54
55 /**
56 * Default constructor.
57 */
58 public function __construct() {
59 $this->supportedDrivers = $this->getSupportedDrivers();
60 $this->availableDrivers = $this->getAvailableDrivers();
61 }
62
63 /**
64 * Hooks into Installer to let a non-MySQL database to be configured.
65 *
66 * @param array $markers
67 * @param integer $step
68 * @param tx_install $instObj
69 * @return void
70 */
71 public function executeStepOutput(array &$markers, $step, tx_install $instObj) {
72 switch ($step) {
73 case 2:
74 $this->createConnectionForm(t3lib_div::_GET('driver'), $markers, $instObj);
75 break;
76 case 3:
77 $this->createDatabaseForm($markers, $instObj);
78 break;
79 }
80 }
81
82 /**
83 * Hooks into Installer to modify lines to be written to localconf.php.
84 *
85 * @param array $lines
86 * @param integer $step
87 * @param tx_install $instObj
88 * @return void
89 */
90 public function executeWriteLocalconf(array &$lines, $step, tx_install $instObj) {
91 switch ($step) {
92 case 3:
93 case 4:
94 $driver = $instObj->INSTALL['localconf.php']['typo_db_driver'];
95 $driverConfig = '';
96 switch ($driver) {
97 case 'oci8':
98 $driverConfig = '\'driverOptions\' => array(' .
99 '\'connectSID\' => ' . ($instObj->INSTALL['localconf.php']['typo_db_type'] === 'sid' ? 'TRUE' : 'FALSE') .
100 ')' ;
101 break;
102 case 'mssql':
103 case 'odbc_mssql':
104 $driverConfig = '\'useNameQuote\' => TRUE';
105 break;
106 case 'mysql':
107 case 'mysqli':
108 return;
109 }
110 $config = 'array(' .
111 '\'_DEFAULT\' => array(' .
112 '\'type\' => \'adodb\',' .
113 '\'config\' => array(' .
114 '\'driver\' => \'' . $driver . '\',' .
115 $driverConfig .
116 ')' .
117 ')' .
118 ');';
119 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXTCONF\'][\'dbal\'][\'handlerCfg\']', $config, FALSE);
120 break;
121 }
122 }
123
124 /**
125 * Creates a specialized form to configure the DBMS connection.
126 *
127 * @param string $driver
128 * @param array $markers
129 * @param tx_install $instObj
130 * @return void
131 */
132 protected function createConnectionForm($driver, array &$markers, tx_install $instObj) {
133 // Get the template file
134 $templateFile = @file_get_contents(
135 t3lib_extMgm::extPath('dbal') . $this->templateFilePath . 'install.html'
136 );
137 // Get the template part from the file
138 $template = t3lib_parsehtml::getSubpart(
139 $templateFile, '###TEMPLATE###'
140 );
141
142 // Get the subpart for the connection form
143 $formSubPart = t3lib_parsehtml::getSubpart(
144 $template, '###CONNECTION_FORM###'
145 );
146 $driverTemplate = t3lib_parsehtml::getSubpart(
147 $formSubPart, '###DATABASE_DRIVER###'
148 );
149 $driverSubPart = $this->prepareDatabaseDrivers($driverTemplate);
150 $formSubPart = t3lib_parsehtml::substituteSubpart(
151 $formSubPart,
152 '###DATABASE_DRIVER###',
153 $driverSubPart
154 );
155
156 if (!$driver) {
157 $driver = $this->getDefaultDriver();
158 }
159 // Get the subpart related to selected database driver
160 if ($driver === '' || $driver === 'mysql' || $driver === 'mysqli') {
161 $driverOptionsSubPart = t3lib_parsehtml::getSubpart(
162 $template, '###DRIVER_MYSQL###'
163 );
164 } else {
165 $driverOptionsSubPart = t3lib_parsehtml::getSubpart(
166 $template, '###DRIVER_' . t3lib_div::strtoupper($driver) . '###'
167 );
168 if ($driverOptionsSubPart === '') {
169 $driverOptionsSubPart = t3lib_parsehtml::getSubpart(
170 $template, '###DRIVER_DEFAULT###'
171 );
172 }
173 }
174
175 // Define driver-specific markers
176 $driverMarkers = array();
177 switch ($driver) {
178 case 'mssql':
179 $driverMarkers = array(
180 'labelUsername' => 'Username',
181 'username' => TYPO3_db_username,
182 'labelPassword' => 'Password',
183 'password' => TYPO3_db_password,
184 'labelHost' => 'Host',
185 'host' => TYPO3_db_host ? TYPO3_db_host : 'windows',
186 'labelDatabase' => 'Database',
187 'database' => TYPO3_db,
188 );
189 $nextStep = $instObj->step + 2;
190 break;
191 case 'odbc_mssql':
192 $driverMarkers = array(
193 'labelUsername' => 'Username',
194 'username' => TYPO3_db_username,
195 'labelPassword' => 'Password',
196 'password' => TYPO3_db_password,
197 'labelHost' => 'Host',
198 'host' => TYPO3_db_host ? TYPO3_db_host : 'windows',
199 'database' => 'dummy_string',
200 );
201 $nextStep = $instObj->step + 2;
202 break;
203 case 'oci8':
204 $driverMarkers = array(
205 'labelUsername' => 'Username',
206 'username' => TYPO3_db_username,
207 'labelPassword' => 'Password',
208 'password' => TYPO3_db_password,
209 'labelHost' => 'Host',
210 'host' => TYPO3_db_host ? TYPO3_db_host : 'localhost',
211 'labelType' => 'Type',
212 'labelSID' => 'SID',
213 'labelServiceName' => 'Service Name',
214 'labelDatabase' => 'Name',
215 'database' => TYPO3_db,
216 );
217 $nextStep = $instObj->step + 2;
218 break;
219 default:
220 $driverMarkers = array(
221 'labelUsername' => 'Username',
222 'username' => TYPO3_db_username,
223 'labelPassword' => 'Password',
224 'password' => TYPO3_db_password,
225 'labelHost' => 'Host',
226 'host' => TYPO3_db_host ? TYPO3_db_host : 'localhost',
227 'labelDatabase' => 'Database',
228 'database' => TYPO3_db,
229 );
230 $nextStep = $instObj->step + 1;
231 break;
232 }
233
234 // Add header marker for main template
235 $markers['header'] = 'Connect to your database host';
236 // Define the markers content for the subpart
237 $subPartMarkers = array(
238 'step' => $nextStep,
239 'action' => htmlspecialchars($instObj->action),
240 'encryptionKey' => $instObj->createEncryptionKey(),
241 'branch' => TYPO3_branch,
242 'driver_options' => $driverOptionsSubPart,
243 'continue' => 'Continue'
244 );
245 $subPartMarkers = array_merge($subPartMarkers, $driverMarkers);
246
247 // Add step marker for main template
248 $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
249 $formSubPart,
250 $subPartMarkers,
251 '###|###',
252 1,
253 1
254 );
255 }
256
257 /**
258 * Prepares the list of database drivers for step 2.
259 *
260 * @param string $template
261 * @return string
262 */
263 protected function prepareDatabaseDrivers($template) {
264 $subParts = array(
265 'abstractionLayer' => t3lib_parsehtml::getSubpart($template, '###ABSTRACTION_LAYER###'),
266 'vendor' => t3lib_parsehtml::getSubpart($template, '###VENDOR###'),
267 );
268
269 // Create the drop-down list of available drivers
270 $dropdown = '';
271 $activeDriver = t3lib_div::_GET('driver');
272 foreach ($this->availableDrivers as $abstractionLayer => $drivers) {
273 $options = array();
274 foreach ($drivers as $driver => $label) {
275 $markers = array(
276 'driver' => $driver,
277 'labelvendor' => $label,
278 'onclick' => 'document.location=\'index.php?TYPO3_INSTALL[type]=config&mode=123&step=2&driver=' . $driver . '\';',
279 'selected' => '',
280 );
281 if ($driver === $activeDriver) {
282 $markers['selected'] .= ' selected="selected"';
283 }
284 $options[] = t3lib_parsehtml::substituteMarkerArray(
285 $subParts['vendor'],
286 $markers,
287 '###|###',
288 1
289 );
290 }
291 $subPart = t3lib_parsehtml::substituteSubpart(
292 $subParts['abstractionLayer'],
293 '###VENDOR###',
294 implode("\n", $options)
295 );
296 $dropdown .= t3lib_parsehtml::substituteMarker(
297 $subPart,
298 '###LABELABSTRACTIONLAYER###',
299 $abstractionLayer
300 );
301 }
302 $form = t3lib_parsehtml::substituteSubpart(
303 $template,
304 '###ABSTRACTION_LAYER###',
305 $dropdown
306 );
307 $form = t3lib_parsehtml::substituteMarker(
308 $form,
309 '###LABELDRIVER###',
310 'Driver'
311 );
312 return $form;
313 }
314
315 /**
316 * Returns a list of DBAL supported database drivers, with a user-friendly name
317 * and any PHP module dependency.
318 *
319 * @return array
320 */
321 protected function getSupportedDrivers() {
322 $supportedDrivers = array(
323 'Native' => array(
324 'mysqli' => array(
325 'label' => 'MySQLi (recommended)',
326 'extensions' => array('mysqli'),
327 ),
328 'mysql' => array(
329 'label' => 'MySQL',
330 'extensions' => array('mysql'),
331 ),
332 'mssql' => array(
333 'label' => 'Microsoft SQL Server',
334 'extensions' => array('mssql'),
335 ),
336 'oci8' => array(
337 'label' => 'Oracle OCI8',
338 'extensions' => array('oci8'),
339 ),
340 'postgres' => array(
341 'label' => 'PostgreSQL',
342 'extensions' => array('pgsql'),
343 )
344 ),
345 'ODBC' => array(
346 'odbc_mssql' => array(
347 'label' => 'Microsoft SQL Server',
348 'extensions' => array('odbc', 'mssql'),
349 ),
350 ),
351 );
352 return $supportedDrivers;
353 }
354
355 /**
356 * Returns a list of database drivers that are available on current server.
357 *
358 * @return array
359 */
360 protected function getAvailableDrivers() {
361 $availableDrivers = array();
362 foreach ($this->supportedDrivers as $abstractionLayer => $drivers) {
363 foreach ($drivers as $driver => $info) {
364 $isAvailable = TRUE;
365
366 // Loop through each PHP module dependency to ensure it is loaded
367 foreach ($info['extensions'] as $extension) {
368 $isAvailable &= extension_loaded($extension);
369 }
370
371 if ($isAvailable) {
372 if (!isset($availableDrivers[$abstractionLayer])) {
373 $availableDrivers[$abstractionLayer] = array();
374 }
375 $availableDrivers[$abstractionLayer][$driver] = $info['label'];
376 }
377 }
378 }
379 return $availableDrivers;
380 }
381
382 /**
383 * Returns the driver that is selected by default in the
384 * Install Tool dropdown list.
385 *
386 * @return string
387 */
388 protected function getDefaultDriver() {
389 $defaultDriver = '';
390 if (count($this->availableDrivers)) {
391 $abstractionLayers = array_keys($this->availableDrivers);
392 $drivers = array_keys($this->availableDrivers[$abstractionLayers[0]]);
393 $defaultDriver = $drivers[0];
394 }
395 return $defaultDriver;
396 }
397
398 /**
399 * Creates a specialized form to configure the database.
400 *
401 * @param array $markers
402 * @param tx_install $instObj
403 */
404 protected function createDatabaseForm(array &$markers, tx_install $instObj) {
405 $error_missingConnect = '
406 <p class="typo3-message message-error">
407 <strong>
408 There is no connection to the database!
409 </strong>
410 <br />
411 (Username: <em>' . TYPO3_db_username . '</em>,
412 Host: <em>' . TYPO3_db_host . '</em>,
413 Using Password: YES)
414 <br />
415 Go to Step 1 and enter a proper username/password!
416 </p>
417 ';
418
419 // Add header marker for main template
420 $markers['header'] = 'Select database';
421 // There should be a database host connection at this point
422 if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(
423 TYPO3_db_host, TYPO3_db_username, TYPO3_db_password
424 )) {
425 // Get the template file
426 $templateFile = @file_get_contents(
427 t3lib_extMgm::extPath('dbal') . $this->templateFilePath . 'install.html'
428 );
429 // Get the template part from the file
430 $template = t3lib_parsehtml::getSubpart(
431 $templateFile, '###TEMPLATE###'
432 );
433 // Get the subpart for the database choice step
434 $formSubPart = t3lib_parsehtml::getSubpart(
435 $template, '###DATABASE_FORM###'
436 );
437 // Get the subpart for the database options
438 $step3DatabaseOptionsSubPart = t3lib_parsehtml::getSubpart(
439 $formSubPart, '###DATABASEOPTIONS###'
440 );
441
442 $dbArr = $instObj->getDatabaseList();
443 $dbIncluded = FALSE;
444 foreach ($dbArr as $dbname) {
445 // Define the markers content for database options
446 $step3DatabaseOptionMarkers = array(
447 'databaseValue' => htmlspecialchars($dbname),
448 'databaseSelected' => ($dbname === TYPO3_db) ? 'selected="selected"' : '',
449 'databaseName' => htmlspecialchars($dbname)
450 );
451 // Add the option HTML to an array
452 $step3DatabaseOptions[] = t3lib_parsehtml::substituteMarkerArray(
453 $step3DatabaseOptionsSubPart,
454 $step3DatabaseOptionMarkers,
455 '###|###',
456 1,
457 1
458 );
459 if ($dbname === TYPO3_db) {
460 $dbIncluded = TRUE;
461 }
462 }
463 if (!$dbIncluded && TYPO3_db) {
464 // // Define the markers content when no access
465 $step3DatabaseOptionMarkers = array(
466 'databaseValue' => htmlspecialchars(TYPO3_db),
467 'databaseSelected' => 'selected="selected"',
468 'databaseName' => htmlspecialchars(TYPO3_db) . ' (NO ACCESS!)'
469 );
470 // Add the option HTML to an array
471 $step3DatabaseOptions[] = t3lib_parsehtml::substituteMarkerArray(
472 $step3DatabaseOptionsSubPart,
473 $step3DatabaseOptionMarkers,
474 '###|###',
475 1,
476 1
477 );
478 }
479 // Substitute the subpart for the database options
480 $content = t3lib_parsehtml::substituteSubpart(
481 $formSubPart,
482 '###DATABASEOPTIONS###',
483 implode(chr(10), $step3DatabaseOptions)
484 );
485 // Define the markers content
486 $step3SubPartMarkers = array(
487 'step' => $instObj->step + 1,
488 'action' => htmlspecialchars($instObj->action),
489 'llOption2' => 'Select an EMPTY existing database:',
490 'llRemark2' => 'All tables used by TYPO3 will be overwritten in step 3.',
491 'continue' => 'Continue'
492 );
493 // Add step marker for main template
494 $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
495 $content,
496 $step3SubPartMarkers,
497 '###|###',
498 1,
499 1
500 );
501 } else {
502 // Add step marker for main template when no connection
503 $markers['step'] = $error_missingConnect;
504 }
505 }
506
507 }
508
509
510 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.tx_dbal_installtool.php']) {
511 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.tx_dbal_installtool.php']);
512 }
513 ?>