MediaWiki
REL1_24
|
00001 <?php 00030 abstract class DatabaseInstaller { 00031 00039 public $parent; 00040 00046 public $db = null; 00047 00053 protected $internalDefaults = array(); 00054 00060 protected $globalNames = array(); 00061 00065 abstract public function getName(); 00066 00070 abstract public function isCompiled(); 00071 00077 public function checkPrerequisites() { 00078 return Status::newGood(); 00079 } 00080 00088 abstract public function getConnectForm(); 00089 00099 abstract public function submitConnectForm(); 00100 00108 public function getSettingsForm() { 00109 return false; 00110 } 00111 00118 public function submitSettingsForm() { 00119 return Status::newGood(); 00120 } 00121 00130 abstract public function openConnection(); 00131 00138 abstract public function setupDatabase(); 00139 00149 public function getConnection() { 00150 if ( $this->db ) { 00151 return Status::newGood( $this->db ); 00152 } 00153 00154 $status = $this->openConnection(); 00155 if ( $status->isOK() ) { 00156 $this->db = $status->value; 00157 // Enable autocommit 00158 $this->db->clearFlag( DBO_TRX ); 00159 $this->db->commit( __METHOD__ ); 00160 } 00161 00162 return $status; 00163 } 00164 00173 private function stepApplySourceFile( 00174 $sourceFileMethod, 00175 $stepName, 00176 $archiveTableMustNotExist = false 00177 ) { 00178 $status = $this->getConnection(); 00179 if ( !$status->isOK() ) { 00180 return $status; 00181 } 00182 $this->db->selectDB( $this->getVar( 'wgDBname' ) ); 00183 00184 if ( $archiveTableMustNotExist && $this->db->tableExists( 'archive', __METHOD__ ) ) { 00185 $status->warning( "config-$stepName-tables-exist" ); 00186 $this->enableLB(); 00187 00188 return $status; 00189 } 00190 00191 $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files 00192 $this->db->begin( __METHOD__ ); 00193 00194 $error = $this->db->sourceFile( 00195 call_user_func( array( $this->db, $sourceFileMethod ) ) 00196 ); 00197 if ( $error !== true ) { 00198 $this->db->reportQueryError( $error, 0, '', __METHOD__ ); 00199 $this->db->rollback( __METHOD__ ); 00200 $status->fatal( "config-$stepName-tables-failed", $error ); 00201 } else { 00202 $this->db->commit( __METHOD__ ); 00203 } 00204 // Resume normal operations 00205 if ( $status->isOk() ) { 00206 $this->enableLB(); 00207 } 00208 00209 return $status; 00210 } 00211 00217 public function createTables() { 00218 return $this->stepApplySourceFile( 'getSchemaPath', 'install', true ); 00219 } 00220 00226 public function insertUpdateKeys() { 00227 return $this->stepApplySourceFile( 'getUpdateKeysPath', 'updates', false ); 00228 } 00229 00234 public function createExtensionTables() { 00235 $status = $this->getConnection(); 00236 if ( !$status->isOK() ) { 00237 return $status; 00238 } 00239 00240 // Now run updates to create tables for old extensions 00241 DatabaseUpdater::newForDB( $this->db )->doUpdates( array( 'extensions' ) ); 00242 00243 return $status; 00244 } 00245 00251 abstract public function getLocalSettings(); 00252 00258 public function getSchemaVars() { 00259 return array(); 00260 } 00261 00268 public function setupSchemaVars() { 00269 $status = $this->getConnection(); 00270 if ( $status->isOK() ) { 00271 $status->value->setSchemaVars( $this->getSchemaVars() ); 00272 } else { 00273 $msg = __METHOD__ . ': unexpected error while establishing' 00274 . ' a database connection with message: ' 00275 . $status->getMessage()->plain(); 00276 throw new MWException( $msg ); 00277 } 00278 } 00279 00285 public function enableLB() { 00286 $status = $this->getConnection(); 00287 if ( !$status->isOK() ) { 00288 throw new MWException( __METHOD__ . ': unexpected DB connection error' ); 00289 } 00290 LBFactory::setInstance( new LBFactorySingle( array( 00291 'connection' => $status->value ) ) ); 00292 } 00293 00299 public function doUpgrade() { 00300 $this->setupSchemaVars(); 00301 $this->enableLB(); 00302 00303 $ret = true; 00304 ob_start( array( $this, 'outputHandler' ) ); 00305 $up = DatabaseUpdater::newForDB( $this->db ); 00306 try { 00307 $up->doUpdates(); 00308 } catch ( MWException $e ) { 00309 echo "\nAn error occurred:\n"; 00310 echo $e->getText(); 00311 $ret = false; 00312 } 00313 $up->purgeCache(); 00314 ob_end_flush(); 00315 00316 return $ret; 00317 } 00318 00324 public function preInstall() { 00325 } 00326 00330 public function preUpgrade() { 00331 } 00332 00337 public function getGlobalNames() { 00338 return $this->globalNames; 00339 } 00340 00346 public function __construct( $parent ) { 00347 $this->parent = $parent; 00348 } 00349 00357 protected static function checkExtension( $name ) { 00358 return extension_loaded( $name ); 00359 } 00360 00365 public function getReadableName() { 00366 // Messages: config-type-mysql, config-type-postgres, config-type-sqlite, 00367 // config-type-oracle 00368 return wfMessage( 'config-type-' . $this->getName() )->text(); 00369 } 00370 00376 public function getGlobalDefaults() { 00377 return array(); 00378 } 00379 00384 public function getInternalDefaults() { 00385 return $this->internalDefaults; 00386 } 00387 00394 public function getVar( $var, $default = null ) { 00395 $defaults = $this->getGlobalDefaults(); 00396 $internal = $this->getInternalDefaults(); 00397 if ( isset( $defaults[$var] ) ) { 00398 $default = $defaults[$var]; 00399 } elseif ( isset( $internal[$var] ) ) { 00400 $default = $internal[$var]; 00401 } 00402 00403 return $this->parent->getVar( $var, $default ); 00404 } 00405 00411 public function setVar( $name, $value ) { 00412 $this->parent->setVar( $name, $value ); 00413 } 00414 00424 public function getTextBox( $var, $label, $attribs = array(), $helpData = "" ) { 00425 $name = $this->getName() . '_' . $var; 00426 $value = $this->getVar( $var ); 00427 if ( !isset( $attribs ) ) { 00428 $attribs = array(); 00429 } 00430 00431 return $this->parent->getTextBox( array( 00432 'var' => $var, 00433 'label' => $label, 00434 'attribs' => $attribs, 00435 'controlName' => $name, 00436 'value' => $value, 00437 'help' => $helpData 00438 ) ); 00439 } 00440 00451 public function getPasswordBox( $var, $label, $attribs = array(), $helpData = "" ) { 00452 $name = $this->getName() . '_' . $var; 00453 $value = $this->getVar( $var ); 00454 if ( !isset( $attribs ) ) { 00455 $attribs = array(); 00456 } 00457 00458 return $this->parent->getPasswordBox( array( 00459 'var' => $var, 00460 'label' => $label, 00461 'attribs' => $attribs, 00462 'controlName' => $name, 00463 'value' => $value, 00464 'help' => $helpData 00465 ) ); 00466 } 00467 00477 public function getCheckBox( $var, $label, $attribs = array(), $helpData = "" ) { 00478 $name = $this->getName() . '_' . $var; 00479 $value = $this->getVar( $var ); 00480 00481 return $this->parent->getCheckBox( array( 00482 'var' => $var, 00483 'label' => $label, 00484 'attribs' => $attribs, 00485 'controlName' => $name, 00486 'value' => $value, 00487 'help' => $helpData 00488 ) ); 00489 } 00490 00503 public function getRadioSet( $params ) { 00504 $params['controlName'] = $this->getName() . '_' . $params['var']; 00505 $params['value'] = $this->getVar( $params['var'] ); 00506 00507 return $this->parent->getRadioSet( $params ); 00508 } 00509 00517 public function setVarsFromRequest( $varNames ) { 00518 return $this->parent->setVarsFromRequest( $varNames, $this->getName() . '_' ); 00519 } 00520 00531 public function needsUpgrade() { 00532 $status = $this->getConnection(); 00533 if ( !$status->isOK() ) { 00534 return false; 00535 } 00536 00537 if ( !$this->db->selectDB( $this->getVar( 'wgDBname' ) ) ) { 00538 return false; 00539 } 00540 00541 return $this->db->tableExists( 'cur', __METHOD__ ) || 00542 $this->db->tableExists( 'revision', __METHOD__ ); 00543 } 00544 00550 public function getInstallUserBox() { 00551 return Html::openElement( 'fieldset' ) . 00552 Html::element( 'legend', array(), wfMessage( 'config-db-install-account' )->text() ) . 00553 $this->getTextBox( 00554 '_InstallUser', 00555 'config-db-username', 00556 array( 'dir' => 'ltr' ), 00557 $this->parent->getHelpBox( 'config-db-install-username' ) 00558 ) . 00559 $this->getPasswordBox( 00560 '_InstallPassword', 00561 'config-db-password', 00562 array( 'dir' => 'ltr' ), 00563 $this->parent->getHelpBox( 'config-db-install-password' ) 00564 ) . 00565 Html::closeElement( 'fieldset' ); 00566 } 00567 00572 public function submitInstallUserBox() { 00573 $this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword' ) ); 00574 00575 return Status::newGood(); 00576 } 00577 00585 public function getWebUserBox( $noCreateMsg = false ) { 00586 $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : ''; 00587 $s = Html::openElement( 'fieldset' ) . 00588 Html::element( 'legend', array(), wfMessage( 'config-db-web-account' )->text() ) . 00589 $this->getCheckBox( 00590 '_SameAccount', 'config-db-web-account-same', 00591 array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' ) 00592 ) . 00593 Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) . 00594 $this->getTextBox( 'wgDBuser', 'config-db-username' ) . 00595 $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) . 00596 $this->parent->getHelpBox( 'config-db-web-help' ); 00597 if ( $noCreateMsg ) { 00598 $s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() ); 00599 } else { 00600 $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' ); 00601 } 00602 $s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' ); 00603 00604 return $s; 00605 } 00606 00612 public function submitWebUserBox() { 00613 $this->setVarsFromRequest( 00614 array( 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount' ) 00615 ); 00616 00617 if ( $this->getVar( '_SameAccount' ) ) { 00618 $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) ); 00619 $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) ); 00620 } 00621 00622 if ( $this->getVar( '_CreateDBAccount' ) && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) { 00623 return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) ); 00624 } 00625 00626 return Status::newGood(); 00627 } 00628 00634 public function populateInterwikiTable() { 00635 $status = $this->getConnection(); 00636 if ( !$status->isOK() ) { 00637 return $status; 00638 } 00639 $this->db->selectDB( $this->getVar( 'wgDBname' ) ); 00640 00641 if ( $this->db->selectRow( 'interwiki', '*', array(), __METHOD__ ) ) { 00642 $status->warning( 'config-install-interwiki-exists' ); 00643 00644 return $status; 00645 } 00646 global $IP; 00647 wfSuppressWarnings(); 00648 $rows = file( "$IP/maintenance/interwiki.list", 00649 FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); 00650 wfRestoreWarnings(); 00651 $interwikis = array(); 00652 if ( !$rows ) { 00653 return Status::newFatal( 'config-install-interwiki-list' ); 00654 } 00655 foreach ( $rows as $row ) { 00656 $row = preg_replace( '/^\s*([^#]*?)\s*(#.*)?$/', '\\1', $row ); // strip comments - whee 00657 if ( $row == "" ) { 00658 continue; 00659 } 00660 $row .= "||"; 00661 $interwikis[] = array_combine( 00662 array( 'iw_prefix', 'iw_url', 'iw_local', 'iw_api', 'iw_wikiid' ), 00663 explode( '|', $row ) 00664 ); 00665 } 00666 $this->db->insert( 'interwiki', $interwikis, __METHOD__ ); 00667 00668 return Status::newGood(); 00669 } 00670 00671 public function outputHandler( $string ) { 00672 return htmlspecialchars( $string ); 00673 } 00674 }