TYPO3 API  SVNRelease
class.tx_dbal_installtool.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 2010 Xavier Perseguers <typo3@perseguers.ch>
00006  *  All rights reserved
00007  *
00008  *  This script is part of the TYPO3 project. The TYPO3 project is
00009  *  free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  The GNU General Public License can be found at
00015  *  http://www.gnu.org/copyleft/gpl.html.
00016  *  A copy is found in the textfile GPL.txt and important notices to the license
00017  *  from the author is found in LICENSE.txt distributed with these scripts.
00018  *
00019  *
00020  *  This script is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU General Public License for more details.
00024  *
00025  *  This copyright notice MUST APPEAR in all copies of the script!
00026  ***************************************************************/
00027 
00028 /**
00029  * Hooks for TYPO3 Install Tool.
00030  *
00031  * $Id$
00032  *
00033  * @author Xavier Perseguers <typo3@perseguers.ch>
00034  *
00035  * @package TYPO3
00036  * @subpackage dbal
00037  */
00038 class tx_dbal_installtool {
00039 
00040     /**
00041      * @var string
00042      */
00043     protected $templateFilePath = 'res/Templates/';
00044 
00045     /**
00046      * @var array
00047      */
00048     protected $supportedDrivers;
00049 
00050     /**
00051      * @var array
00052      */
00053     protected $availableDrivers;
00054 
00055     /**
00056      * @var string
00057      */
00058     protected $driver;
00059 
00060     /**
00061      * Default constructor.
00062      */
00063     public function __construct() {
00064         $this->supportedDrivers = $this->getSupportedDrivers();
00065         $this->availableDrivers = $this->getAvailableDrivers();
00066 
00067         $configDriver =& $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['handlerCfg']['_DEFAULT']['config']['driver'];
00068         $this->driver = t3lib_div::_GET('driver');
00069         if (!$this->driver && $configDriver) {
00070             $this->driver = $configDriver;
00071         }
00072     }
00073 
00074     /**
00075      * Hooks into Installer to set required PHP modules.
00076      *
00077      * @param array $modules
00078      * @param tx_install $instObj
00079      * @return array modules
00080      */
00081     public function setRequiredPhpModules(array &$modules, tx_install $instObj) {
00082         foreach ($modules as $key => $module) {
00083             if ($module === 'mysql') {
00084                 $dbModules = array();
00085                 foreach ($this->supportedDrivers as $abstractionLayer => $drivers) {
00086                     $dbModules = array_merge($dbModules, array_keys($drivers));
00087                 }
00088                 $module = $dbModules;
00089             }
00090             $modifiedModules[] = $module;
00091         }
00092         return $modifiedModules;
00093     }
00094 
00095     /**
00096      * Hooks into Installer to let a non-MySQL database to be configured.
00097      *
00098      * @param array $markers
00099      * @param integer $step
00100      * @param tx_install $instObj
00101      * @return void
00102      */
00103     public function executeStepOutput(array &$markers, $step, tx_install $instObj) {
00104         switch ($step) {
00105             case 2:
00106                 $this->createConnectionForm($markers, $instObj);
00107                 break;
00108             case 3:
00109                 $this->createDatabaseForm($markers, $instObj);
00110                 break;
00111         }
00112     }
00113 
00114     /**
00115      * Hooks into Installer to modify lines to be written to localconf.php.
00116      *
00117      * @param array $lines
00118      * @param integer $step
00119      * @param tx_install $instObj
00120      * @return void
00121      */
00122     public function executeWriteLocalconf(array &$lines, $step, tx_install $instObj) {
00123         switch ($step) {
00124             case 3:
00125             case 4:
00126                 $driver = $instObj->INSTALL['localconf.php']['typo_db_driver'];
00127                 if (!$driver && $this->driver) {
00128                     // Driver was already configured
00129                     break;
00130                 }
00131                 $driverConfig = '';
00132                 switch ($driver) {
00133                     case 'oci8':
00134                         $driverConfig = '\'driverOptions\' => array(' .
00135                                 '\'connectSID\' => ' . ($instObj->INSTALL['localconf.php']['typo_db_type'] === 'sid' ? 'TRUE' : 'FALSE') .
00136                                 ')';
00137                         break;
00138                     case 'mssql':
00139                     case 'odbc_mssql':
00140                         $driverConfig = '\'useNameQuote\' => TRUE';
00141                         break;
00142                     case 'mysql':
00143                         return;
00144                 }
00145                 $config = 'array(' .
00146                         '\'_DEFAULT\' => array(' .
00147                         '\'type\' => \'adodb\',' .
00148                         '\'config\' => array(' .
00149                         '\'driver\' => \'' . $driver . '\',' .
00150                         $driverConfig .
00151                         ')' .
00152                         ')' .
00153                         ');';
00154                 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXTCONF\'][\'dbal\'][\'handlerCfg\']', $config, FALSE);
00155                 break;
00156         }
00157     }
00158 
00159     /**
00160      * Creates a specialized form to configure the DBMS connection.
00161      *
00162      * @param array $markers
00163      * @param tx_install $instObj
00164      * @return void
00165      */
00166     protected function createConnectionForm(array &$markers, tx_install $instObj) {
00167         // Normalize current driver
00168         if (!$this->driver) {
00169             $this->driver = $this->getDefaultDriver();
00170         }
00171 
00172         // Get the template file
00173         $templateFile = @file_get_contents(
00174             t3lib_extMgm::extPath('dbal') . $this->templateFilePath . 'install.html'
00175         );
00176         // Get the template part from the file
00177         $template = t3lib_parsehtml::getSubpart(
00178             $templateFile, '###TEMPLATE###'
00179         );
00180 
00181         // Get the subpart for the connection form
00182         $formSubPart = t3lib_parsehtml::getSubpart(
00183             $template, '###CONNECTION_FORM###'
00184         );
00185         if ($this->getNumberOfAvailableDrivers() == 1 && $this->getDefaultDriver() === 'mysql') {
00186             // Only MySQL is actually available (PDO support may be compiled in
00187             // PHP itself and as such DBAL was activated, behaves as if DBAL were
00188             // not activated
00189             $driverSubPart = '<input type="hidden" name="TYPO3_INSTALL[localconf.php][typo_db_driver]" value="mysql" />';
00190         } else {
00191             $driverTemplate = t3lib_parsehtml::getSubpart(
00192                 $formSubPart, '###DATABASE_DRIVER###'
00193             );
00194             $driverSubPart = $this->prepareDatabaseDrivers($driverTemplate);
00195         }
00196         $formSubPart = t3lib_parsehtml::substituteSubpart(
00197             $formSubPart,
00198             '###DATABASE_DRIVER###',
00199             $driverSubPart
00200         );
00201 
00202         // Get the subpart related to selected database driver
00203         if ($this->driver === '' || $this->driver === 'mysql') {
00204             $driverOptionsSubPart = t3lib_parsehtml::getSubpart(
00205                 $template, '###DRIVER_MYSQL###'
00206             );
00207         } else {
00208             $driverOptionsSubPart = t3lib_parsehtml::getSubpart(
00209                 $template, '###DRIVER_' . t3lib_div::strtoupper($this->driver) . '###'
00210             );
00211             if ($driverOptionsSubPart === '') {
00212                 $driverOptionsSubPart = t3lib_parsehtml::getSubpart(
00213                     $template, '###DRIVER_DEFAULT###'
00214                 );
00215             }
00216         }
00217 
00218         // Define driver-specific markers
00219         $driverMarkers = array();
00220         switch ($this->driver) {
00221             case 'mssql':
00222                 $driverMarkers = array(
00223                     'labelUsername' => 'Username',
00224                     'username' => TYPO3_db_username,
00225                     'labelPassword' => 'Password',
00226                     'password' => TYPO3_db_password,
00227                     'labelHost' => 'Host',
00228                     'host' => TYPO3_db_host ? TYPO3_db_host : 'windows',
00229                     'labelDatabase' => 'Database',
00230                     'database' => TYPO3_db,
00231                 );
00232                 $nextStep = $instObj->step + 2;
00233                 break;
00234             case 'odbc_mssql':
00235                 $driverMarkers = array(
00236                     'labelUsername' => 'Username',
00237                     'username' => TYPO3_db_username,
00238                     'labelPassword' => 'Password',
00239                     'password' => TYPO3_db_password,
00240                     'labelHost' => 'Host',
00241                     'host' => TYPO3_db_host ? TYPO3_db_host : 'windows',
00242                     'database' => 'dummy_string',
00243                 );
00244                 $nextStep = $instObj->step + 2;
00245                 break;
00246             case 'oci8':
00247                 $driverMarkers = array(
00248                     'labelUsername' => 'Username',
00249                     'username' => TYPO3_db_username,
00250                     'labelPassword' => 'Password',
00251                     'password' => TYPO3_db_password,
00252                     'labelHost' => 'Host',
00253                     'host' => TYPO3_db_host ? TYPO3_db_host : 'localhost',
00254                     'labelType' => 'Type',
00255                     'labelSID' => 'SID',
00256                     'labelServiceName' => 'Service Name',
00257                     'labelDatabase' => 'Name',
00258                     'database' => TYPO3_db,
00259                 );
00260                 $nextStep = $instObj->step + 2;
00261                 break;
00262             case 'postgres':
00263                 $driverMarkers = array(
00264                     'labelUsername' => 'Username',
00265                     'username' => TYPO3_db_username,
00266                     'labelPassword' => 'Password',
00267                     'password' => TYPO3_db_password,
00268                     'labelHost' => 'Host',
00269                     'host' => TYPO3_db_host ? TYPO3_db_host : 'localhost',
00270                     'labelDatabase' => 'Database',
00271                     'database' => TYPO3_db,
00272                 );
00273                 $nextStep = $instObj->step + 2;
00274                 break;
00275             default:
00276                 $driverMarkers = array(
00277                     'labelUsername' => 'Username',
00278                     'username' => TYPO3_db_username,
00279                     'labelPassword' => 'Password',
00280                     'password' => TYPO3_db_password,
00281                     'labelHost' => 'Host',
00282                     'host' => TYPO3_db_host ? TYPO3_db_host : 'localhost',
00283                     'labelDatabase' => 'Database',
00284                     'database' => TYPO3_db,
00285                 );
00286                 $nextStep = $instObj->step + 1;
00287                 break;
00288         }
00289 
00290         // Add header marker for main template
00291         $markers['header'] = 'Connect to your database host';
00292         // Define the markers content for the subpart
00293         $subPartMarkers = array(
00294             'step' => $nextStep,
00295             'action' => htmlspecialchars($instObj->action),
00296             'encryptionKey' => $instObj->createEncryptionKey(),
00297             'branch' => TYPO3_branch,
00298             'driver_options' => $driverOptionsSubPart,
00299             'continue' => 'Continue',
00300             'llDescription' => 'If you have not already created a username and password to access the database, please do so now. This can be done using tools provided by your host.'
00301         );
00302         $subPartMarkers = array_merge($subPartMarkers, $driverMarkers);
00303 
00304         // Add step marker for main template
00305         $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
00306             $formSubPart,
00307             $subPartMarkers,
00308             '###|###',
00309             1,
00310             1
00311         );
00312     }
00313 
00314     /**
00315      * Prepares the list of database drivers for step 2.
00316      *
00317      * @param string $template
00318      * @return string
00319      */
00320     protected function prepareDatabaseDrivers($template) {
00321         $subParts = array(
00322             'abstractionLayer' => t3lib_parsehtml::getSubpart($template, '###ABSTRACTION_LAYER###'),
00323             'vendor' => t3lib_parsehtml::getSubpart($template, '###VENDOR###'),
00324         );
00325 
00326         // Create the drop-down list of available drivers
00327         $dropdown = '';
00328         foreach ($this->availableDrivers as $abstractionLayer => $drivers) {
00329             $options = array();
00330             foreach ($drivers as $driver => $label) {
00331                 $markers = array(
00332                     'driver' => $driver,
00333                     'labelvendor' => $label,
00334                     'onclick' => 'document.location=\'index.php?TYPO3_INSTALL[type]=config&mode=123&step=2&driver=' . $driver . '\';',
00335                     'selected' => '',
00336                 );
00337                 if ($driver === $this->driver) {
00338                     $markers['selected'] .= ' selected="selected"';
00339                 }
00340                 $options[] = t3lib_parsehtml::substituteMarkerArray(
00341                     $subParts['vendor'],
00342                     $markers,
00343                     '###|###',
00344                     1
00345                 );
00346             }
00347             $subPart = t3lib_parsehtml::substituteSubpart(
00348                 $subParts['abstractionLayer'],
00349                 '###VENDOR###',
00350                 implode("\n", $options)
00351             );
00352             $dropdown .= t3lib_parsehtml::substituteMarker(
00353                 $subPart,
00354                 '###LABELABSTRACTIONLAYER###',
00355                 $abstractionLayer
00356             );
00357         }
00358         $form = t3lib_parsehtml::substituteSubpart(
00359             $template,
00360             '###ABSTRACTION_LAYER###',
00361             $dropdown
00362         );
00363         $form = t3lib_parsehtml::substituteMarker(
00364             $form,
00365             '###LABELDRIVER###',
00366             'Driver'
00367         );
00368         return $form;
00369     }
00370 
00371     /**
00372      * Returns a list of DBAL supported database drivers, with a user-friendly name
00373      * and any PHP module dependency.
00374      *
00375      * @return array
00376      */
00377     protected function getSupportedDrivers() {
00378         $supportedDrivers = array(
00379             'Native' => array(
00380                 'mysql' => array(
00381                     'label' => 'MySQL/MySQLi (recommended)',
00382                     'combine' => 'OR',
00383                     'extensions' => array('mysql', 'mysqli'),
00384                 ),
00385                 'mssql' => array(
00386                     'label' => 'Microsoft SQL Server',
00387                     'extensions' => array('mssql'),
00388                 ),
00389                 'oci8' => array(
00390                     'label' => 'Oracle OCI8',
00391                     'extensions' => array('oci8'),
00392                 ),
00393                 'postgres' => array(
00394                     'label' => 'PostgreSQL',
00395                     'extensions' => array('pgsql'),
00396                 )
00397             ),
00398             'ODBC' => array(
00399                 'odbc_mssql' => array(
00400                     'label' => 'Microsoft SQL Server',
00401                     'extensions' => array('odbc', 'mssql'),
00402                 ),
00403             ),
00404         );
00405         return $supportedDrivers;
00406     }
00407 
00408     /**
00409      * Returns a list of database drivers that are available on current server.
00410      *
00411      * @return array
00412      */
00413     protected function getAvailableDrivers() {
00414         $availableDrivers = array();
00415         foreach ($this->supportedDrivers as $abstractionLayer => $drivers) {
00416             foreach ($drivers as $driver => $info) {
00417                 if (isset($info['combine']) && $info['combine'] === 'OR') {
00418                     $isAvailable = FALSE;
00419                 } else {
00420                     $isAvailable = TRUE;
00421                 }
00422 
00423                 // Loop through each PHP module dependency to ensure it is loaded
00424                 foreach ($info['extensions'] as $extension) {
00425                     if (isset($info['combine']) && $info['combine'] === 'OR') {
00426                         $isAvailable |= extension_loaded($extension);
00427                     } else {
00428                         $isAvailable &= extension_loaded($extension);
00429                     }
00430                 }
00431 
00432                 if ($isAvailable) {
00433                     if (!isset($availableDrivers[$abstractionLayer])) {
00434                         $availableDrivers[$abstractionLayer] = array();
00435                     }
00436                     $availableDrivers[$abstractionLayer][$driver] = $info['label'];
00437                 }
00438             }
00439         }
00440         return $availableDrivers;
00441     }
00442 
00443     /**
00444      * Returns the number of available drivers.
00445      *
00446      * @return boolean
00447      */
00448     protected function getNumberOfAvailableDrivers() {
00449         $count = 0;
00450         foreach ($this->availableDrivers as $drivers) {
00451             $count += count($drivers);
00452         }
00453         return $count;
00454     }
00455 
00456     /**
00457      * Returns the driver that is selected by default in the
00458      * Install Tool dropdown list.
00459      *
00460      * @return string
00461      */
00462     protected function getDefaultDriver() {
00463         $defaultDriver = '';
00464         if (count($this->availableDrivers)) {
00465             $abstractionLayers = array_keys($this->availableDrivers);
00466             $drivers = array_keys($this->availableDrivers[$abstractionLayers[0]]);
00467             $defaultDriver = $drivers[0];
00468         }
00469         return $defaultDriver;
00470     }
00471 
00472     /**
00473      * Creates a specialized form to configure the database.
00474      *
00475      * @param array $markers
00476      * @param tx_install $instObj
00477      */
00478     protected function createDatabaseForm(array &$markers, tx_install $instObj) {
00479         $error_missingConnect = '
00480             <p class="typo3-message message-error">
00481                 <strong>
00482                     There is no connection to the database!
00483                 </strong>
00484                 <br />
00485                 (Username: <em>' . TYPO3_db_username . '</em>,
00486                 Host: <em>' . TYPO3_db_host . '</em>,
00487                 Using Password: YES)
00488                 <br />
00489                 Go to Step 1 and enter a valid username and password!
00490             </p>
00491         ';
00492 
00493         // Add header marker for main template
00494         $markers['header'] = 'Select database';
00495         // There should be a database host connection at this point
00496         if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(
00497             TYPO3_db_host, TYPO3_db_username, TYPO3_db_password
00498         )) {
00499             // Get the template file
00500             $templateFile = @file_get_contents(
00501                 t3lib_extMgm::extPath('dbal') . $this->templateFilePath . 'install.html'
00502             );
00503             // Get the template part from the file
00504             $template = t3lib_parsehtml::getSubpart(
00505                 $templateFile, '###TEMPLATE###'
00506             );
00507             // Get the subpart for the database choice step
00508             $formSubPart = t3lib_parsehtml::getSubpart(
00509                 $template, '###DATABASE_FORM###'
00510             );
00511             // Get the subpart for the database options
00512             $step3DatabaseOptionsSubPart = t3lib_parsehtml::getSubpart(
00513                 $formSubPart, '###DATABASEOPTIONS###'
00514             );
00515 
00516             $dbArr = $instObj->getDatabaseList();
00517             $dbIncluded = FALSE;
00518             foreach ($dbArr as $dbname) {
00519                 // Define the markers content for database options
00520                 $step3DatabaseOptionMarkers = array(
00521                     'databaseValue' => htmlspecialchars($dbname),
00522                     'databaseSelected' => ($dbname === TYPO3_db) ? 'selected="selected"' : '',
00523                     'databaseName' => htmlspecialchars($dbname)
00524                 );
00525                 // Add the option HTML to an array
00526                 $step3DatabaseOptions[] = t3lib_parsehtml::substituteMarkerArray(
00527                     $step3DatabaseOptionsSubPart,
00528                     $step3DatabaseOptionMarkers,
00529                     '###|###',
00530                     1,
00531                     1
00532                 );
00533                 if ($dbname === TYPO3_db) {
00534                     $dbIncluded = TRUE;
00535                 }
00536             }
00537             if (!$dbIncluded && TYPO3_db) {
00538                 // // Define the markers content when no access
00539                 $step3DatabaseOptionMarkers = array(
00540                     'databaseValue' => htmlspecialchars(TYPO3_db),
00541                     'databaseSelected' => 'selected="selected"',
00542                     'databaseName' => htmlspecialchars(TYPO3_db) . ' (NO ACCESS!)'
00543                 );
00544                 // Add the option HTML to an array
00545                 $step3DatabaseOptions[] = t3lib_parsehtml::substituteMarkerArray(
00546                     $step3DatabaseOptionsSubPart,
00547                     $step3DatabaseOptionMarkers,
00548                     '###|###',
00549                     1,
00550                     1
00551                 );
00552             }
00553             // Substitute the subpart for the database options
00554             $content = t3lib_parsehtml::substituteSubpart(
00555                 $formSubPart,
00556                 '###DATABASEOPTIONS###',
00557                 implode(chr(10), $step3DatabaseOptions)
00558             );
00559             // Define the markers content
00560             $step3SubPartMarkers = array(
00561                 'step' => $instObj->step + 1,
00562                 'action' => htmlspecialchars($instObj->action),
00563                 'llOption2' => 'Select an EMPTY existing database:',
00564                 'llRemark2' => 'Any tables used by TYPO3 will be overwritten.',
00565                 'continue' => 'Continue'
00566             );
00567             // Add step marker for main template
00568             $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
00569                 $content,
00570                 $step3SubPartMarkers,
00571                 '###|###',
00572                 1,
00573                 1
00574             );
00575         } else {
00576             // Add step marker for main template when no connection
00577             $markers['step'] = $error_missingConnect;
00578         }
00579     }
00580 
00581 }
00582 
00583 
00584 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/class.tx_dbal_installtool.php'])) {
00585     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/class.tx_dbal_installtool.php']);
00586 }
00587 ?>