MediaWiki  REL1_22
OracleInstaller.php
Go to the documentation of this file.
00001 <?php
00030 class OracleInstaller extends DatabaseInstaller {
00031 
00032     protected $globalNames = array(
00033         'wgDBserver',
00034         'wgDBname',
00035         'wgDBuser',
00036         'wgDBpassword',
00037         'wgDBprefix',
00038     );
00039 
00040     protected $internalDefaults = array(
00041         '_OracleDefTS' => 'USERS',
00042         '_OracleTempTS' => 'TEMP',
00043         '_InstallUser' => 'SYSTEM',
00044     );
00045 
00046     public $minimumVersion = '9.0.1'; // 9iR1
00047 
00048     protected $connError = null;
00049 
00050     public function getName() {
00051         return 'oracle';
00052     }
00053 
00054     public function isCompiled() {
00055         return self::checkExtension( 'oci8' );
00056     }
00057 
00058     public function getConnectForm() {
00059         if ( $this->getVar( 'wgDBserver' ) == 'localhost' ) {
00060             $this->parent->setVar( 'wgDBserver', '' );
00061         }
00062 
00063         return $this->getTextBox(
00064             'wgDBserver',
00065             'config-db-host-oracle',
00066             array(),
00067             $this->parent->getHelpBox( 'config-db-host-oracle-help' )
00068         ) .
00069             Html::openElement( 'fieldset' ) .
00070             Html::element( 'legend', array(), wfMessage( 'config-db-wiki-settings' )->text() ) .
00071             $this->getTextBox( 'wgDBprefix', 'config-db-prefix' ) .
00072             $this->getTextBox( '_OracleDefTS', 'config-oracle-def-ts' ) .
00073             $this->getTextBox(
00074                 '_OracleTempTS',
00075                 'config-oracle-temp-ts',
00076                 array(),
00077                 $this->parent->getHelpBox( 'config-db-oracle-help' )
00078             ) .
00079             Html::closeElement( 'fieldset' ) .
00080             $this->parent->getWarningBox( wfMessage( 'config-db-account-oracle-warn' )->text() ) .
00081             $this->getInstallUserBox() .
00082             $this->getWebUserBox();
00083     }
00084 
00085     public function submitInstallUserBox() {
00086         parent::submitInstallUserBox();
00087         $this->parent->setVar( '_InstallDBname', $this->getVar( '_InstallUser' ) );
00088 
00089         return Status::newGood();
00090     }
00091 
00092     public function submitConnectForm() {
00093         // Get variables from the request
00094         $newValues = $this->setVarsFromRequest( array(
00095             'wgDBserver',
00096             'wgDBprefix',
00097             'wgDBuser',
00098             'wgDBpassword'
00099         ) );
00100         $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) );
00101 
00102         // Validate them
00103         $status = Status::newGood();
00104         if ( !strlen( $newValues['wgDBserver'] ) ) {
00105             $status->fatal( 'config-missing-db-server-oracle' );
00106         } elseif ( !self::checkConnectStringFormat( $newValues['wgDBserver'] ) ) {
00107             $status->fatal( 'config-invalid-db-server-oracle', $newValues['wgDBserver'] );
00108         }
00109         if ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBprefix'] ) ) {
00110             $status->fatal( 'config-invalid-schema', $newValues['wgDBprefix'] );
00111         }
00112         if ( !$status->isOK() ) {
00113             return $status;
00114         }
00115 
00116         // Submit user box
00117         $status = $this->submitInstallUserBox();
00118         if ( !$status->isOK() ) {
00119             return $status;
00120         }
00121 
00122         // Try to connect trough multiple scenarios
00123         // Scenario 1: Install with a manually created account
00124         $status = $this->getConnection();
00125         if ( !$status->isOK() ) {
00126             if ( $this->connError == 28009 ) {
00127                 // _InstallUser seems to be a SYSDBA
00128                 // Scenario 2: Create user with SYSDBA and install with new user
00129                 $status = $this->submitWebUserBox();
00130                 if ( !$status->isOK() ) {
00131                     return $status;
00132                 }
00133                 $status = $this->openSYSDBAConnection();
00134                 if ( !$status->isOK() ) {
00135                     return $status;
00136                 }
00137                 if ( !$this->getVar( '_CreateDBAccount' ) ) {
00138                     $status->fatal( 'config-db-sys-create-oracle' );
00139                 }
00140             } else {
00141                 return $status;
00142             }
00143         } else {
00144             // check for web user credentials
00145             // Scenario 3: Install with a priviliged user but use a restricted user
00146             $statusIS3 = $this->submitWebUserBox();
00147             if ( !$statusIS3->isOK() ) {
00148                 return $statusIS3;
00149             }
00150         }
00151 
00155         $conn = $status->value;
00156 
00157         // Check version
00158         $version = $conn->getServerVersion();
00159         if ( version_compare( $version, $this->minimumVersion ) < 0 ) {
00160             return Status::newFatal( 'config-oracle-old', $this->minimumVersion, $version );
00161         }
00162 
00163         return $status;
00164     }
00165 
00166     public function openConnection() {
00167         $status = Status::newGood();
00168         try {
00169             $db = new DatabaseOracle(
00170                 $this->getVar( 'wgDBserver' ),
00171                 $this->getVar( '_InstallUser' ),
00172                 $this->getVar( '_InstallPassword' ),
00173                 $this->getVar( '_InstallDBname' ),
00174                 0,
00175                 $this->getVar( 'wgDBprefix' )
00176             );
00177             $status->value = $db;
00178         } catch ( DBConnectionError $e ) {
00179             $this->connError = $e->db->lastErrno();
00180             $status->fatal( 'config-connection-error', $e->getMessage() );
00181         }
00182 
00183         return $status;
00184     }
00185 
00186     public function openSYSDBAConnection() {
00187         $status = Status::newGood();
00188         try {
00189             $db = new DatabaseOracle(
00190                 $this->getVar( 'wgDBserver' ),
00191                 $this->getVar( '_InstallUser' ),
00192                 $this->getVar( '_InstallPassword' ),
00193                 $this->getVar( '_InstallDBname' ),
00194                 DBO_SYSDBA,
00195                 $this->getVar( 'wgDBprefix' )
00196             );
00197             $status->value = $db;
00198         } catch ( DBConnectionError $e ) {
00199             $this->connError = $e->db->lastErrno();
00200             $status->fatal( 'config-connection-error', $e->getMessage() );
00201         }
00202 
00203         return $status;
00204     }
00205 
00206     public function needsUpgrade() {
00207         $tempDBname = $this->getVar( 'wgDBname' );
00208         $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) );
00209         $retVal = parent::needsUpgrade();
00210         $this->parent->setVar( 'wgDBname', $tempDBname );
00211 
00212         return $retVal;
00213     }
00214 
00215     public function preInstall() {
00216         # Add our user callback to installSteps, right before the tables are created.
00217         $callback = array(
00218             'name' => 'user',
00219             'callback' => array( $this, 'setupUser' )
00220         );
00221         $this->parent->addInstallStep( $callback, 'database' );
00222     }
00223 
00224     public function setupDatabase() {
00225         $status = Status::newGood();
00226 
00227         return $status;
00228     }
00229 
00230     public function setupUser() {
00231         global $IP;
00232 
00233         if ( !$this->getVar( '_CreateDBAccount' ) ) {
00234             return Status::newGood();
00235         }
00236 
00237         // normaly only SYSDBA users can create accounts
00238         $status = $this->openSYSDBAConnection();
00239         if ( !$status->isOK() ) {
00240             if ( $this->connError == 1031 ) {
00241                 // insufficient  privileges (looks like a normal user)
00242                 $status = $this->openConnection();
00243                 if ( !$status->isOK() ) {
00244                     return $status;
00245                 }
00246             } else {
00247                 return $status;
00248             }
00249         }
00250         $this->db = $status->value;
00251         $this->setupSchemaVars();
00252 
00253         if ( !$this->db->selectDB( $this->getVar( 'wgDBuser' ) ) ) {
00254             $this->db->setFlag( DBO_DDLMODE );
00255             $error = $this->db->sourceFile( "$IP/maintenance/oracle/user.sql" );
00256             if ( $error !== true || !$this->db->selectDB( $this->getVar( 'wgDBuser' ) ) ) {
00257                 $status->fatal( 'config-install-user-failed', $this->getVar( 'wgDBuser' ), $error );
00258             }
00259         } elseif ( $this->db->getFlag( DBO_SYSDBA ) ) {
00260             $status->fatal( 'config-db-sys-user-exists-oracle', $this->getVar( 'wgDBuser' ) );
00261         }
00262 
00263         if ( $status->isOK() ) {
00264             // user created or already existing, switching back to a normal connection
00265             // as the new user has all needed privileges to setup the rest of the schema
00266             // i will be using that user as _InstallUser from this point on
00267             $this->db->close();
00268             $this->db = false;
00269             $this->parent->setVar( '_InstallUser', $this->getVar( 'wgDBuser' ) );
00270             $this->parent->setVar( '_InstallPassword', $this->getVar( 'wgDBpassword' ) );
00271             $this->parent->setVar( '_InstallDBname', $this->getVar( 'wgDBuser' ) );
00272             $status = $this->getConnection();
00273         }
00274 
00275         return $status;
00276     }
00277 
00282     public function createTables() {
00283         $this->setupSchemaVars();
00284         $this->db->setFlag( DBO_DDLMODE );
00285         $this->parent->setVar( 'wgDBname', $this->getVar( 'wgDBuser' ) );
00286         $status = parent::createTables();
00287         $this->db->clearFlag( DBO_DDLMODE );
00288 
00289         $this->db->query( 'BEGIN fill_wiki_info; END;' );
00290 
00291         return $status;
00292     }
00293 
00294     public function getSchemaVars() {
00295         $varNames = array(
00296             # These variables are used by maintenance/oracle/user.sql
00297             '_OracleDefTS',
00298             '_OracleTempTS',
00299             'wgDBuser',
00300             'wgDBpassword',
00301 
00302             # These are used by tables.sql
00303             'wgDBprefix',
00304         );
00305         $vars = array();
00306         foreach ( $varNames as $name ) {
00307             $vars[$name] = $this->getVar( $name );
00308         }
00309 
00310         return $vars;
00311     }
00312 
00313     public function getLocalSettings() {
00314         $prefix = $this->getVar( 'wgDBprefix' );
00315 
00316         return "# Oracle specific settings
00317 \$wgDBprefix = \"{$prefix}\";
00318 ";
00319     }
00320 
00335     public static function checkConnectStringFormat( $connect_string ) {
00336         // @@codingStandardsIgnoreStart Long lines with regular expressions.
00337         // @todo Very long regular expression. Make more readable?
00338         $isValid = preg_match( '/^[[:alpha:]][\w\-]*(?:\.[[:alpha:]][\w\-]*){0,2}$/', $connect_string ); // TNS name
00339         $isValid |= preg_match( '/^(?:\/\/)?[\w\-\.]+(?::[\d]+)?(?:\/(?:[\w\-\.]+(?::(pooled|dedicated|shared))?)?(?:\/[\w\-\.]+)?)?$/', $connect_string ); // EZConnect
00340         // @@codingStandardsIgnoreEnd
00341         return (bool)$isValid;
00342     }
00343 }