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