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