MediaWiki
REL1_22
|
00001 <?php 00030 abstract class WebInstallerPage { 00031 00037 public $parent; 00038 00039 abstract public function execute(); 00040 00046 public function __construct( WebInstaller $parent ) { 00047 $this->parent = $parent; 00048 } 00049 00056 public function isSlow() { 00057 return false; 00058 } 00059 00060 public function addHTML( $html ) { 00061 $this->parent->output->addHTML( $html ); 00062 } 00063 00064 public function startForm() { 00065 $this->addHTML( 00066 "<div class=\"config-section\">\n" . 00067 Html::openElement( 00068 'form', 00069 array( 00070 'method' => 'post', 00071 'action' => $this->parent->getUrl( array( 'page' => $this->getName() ) ) 00072 ) 00073 ) . "\n" 00074 ); 00075 } 00076 00081 public function endForm( $continue = 'continue', $back = 'back' ) { 00082 $s = "<div class=\"config-submit\">\n"; 00083 $id = $this->getId(); 00084 00085 if ( $id === false ) { 00086 $s .= Html::hidden( 'lastPage', $this->parent->request->getVal( 'lastPage' ) ); 00087 } 00088 00089 if ( $continue ) { 00090 // Fake submit button for enter keypress (bug 26267) 00091 // Messages: config-continue, config-restart, config-regenerate 00092 $s .= Xml::submitButton( 00093 wfMessage( "config-$continue" )->text(), 00094 array( 00095 'name' => "enter-$continue", 00096 'style' => 'visibility:hidden;overflow:hidden;width:1px;margin:0' 00097 ) 00098 ) . "\n"; 00099 } 00100 00101 if ( $back ) { 00102 // Message: config-back 00103 $s .= Xml::submitButton( 00104 wfMessage( "config-$back" )->text(), 00105 array( 00106 'name' => "submit-$back", 00107 'tabindex' => $this->parent->nextTabIndex() 00108 ) 00109 ) . "\n"; 00110 } 00111 00112 if ( $continue ) { 00113 // Messages: config-continue, config-restart, config-regenerate 00114 $s .= Xml::submitButton( 00115 wfMessage( "config-$continue" )->text(), 00116 array( 00117 'name' => "submit-$continue", 00118 'tabindex' => $this->parent->nextTabIndex(), 00119 ) 00120 ) . "\n"; 00121 } 00122 00123 $s .= "</div></form></div>\n"; 00124 $this->addHTML( $s ); 00125 } 00126 00127 public function getName() { 00128 return str_replace( 'WebInstaller_', '', get_class( $this ) ); 00129 } 00130 00131 protected function getId() { 00132 return array_search( $this->getName(), $this->parent->pageSequence ); 00133 } 00134 00135 public function getVar( $var ) { 00136 return $this->parent->getVar( $var ); 00137 } 00138 00139 public function setVar( $name, $value ) { 00140 $this->parent->setVar( $name, $value ); 00141 } 00142 00150 protected function getFieldsetStart( $legend ) { 00151 return "\n<fieldset><legend>" . wfMessage( $legend )->escaped() . "</legend>\n"; 00152 } 00153 00159 protected function getFieldsetEnd() { 00160 return "</fieldset>\n"; 00161 } 00162 00166 protected function startLiveBox() { 00167 $this->addHTML( 00168 '<div id="config-spinner" style="display:none;">' . 00169 '<img src="../skins/common/images/ajax-loader.gif" /></div>' . 00170 '<script>jQuery( "#config-spinner" ).show();</script>' . 00171 '<div id="config-live-log">' . 00172 '<textarea name="LiveLog" rows="10" cols="30" readonly="readonly">' 00173 ); 00174 $this->parent->output->flush(); 00175 } 00176 00180 protected function endLiveBox() { 00181 $this->addHTML( '</textarea></div> 00182 <script>jQuery( "#config-spinner" ).hide()</script>' ); 00183 $this->parent->output->flush(); 00184 } 00185 } 00186 00187 class WebInstaller_Language extends WebInstallerPage { 00188 00189 public function execute() { 00190 global $wgLang; 00191 $r = $this->parent->request; 00192 $userLang = $r->getVal( 'uselang' ); 00193 $contLang = $r->getVal( 'ContLang' ); 00194 00195 $languages = Language::fetchLanguageNames(); 00196 $lifetime = intval( ini_get( 'session.gc_maxlifetime' ) ); 00197 if ( !$lifetime ) { 00198 $lifetime = 1440; // PHP default 00199 } 00200 00201 if ( $r->wasPosted() ) { 00202 # Do session test 00203 if ( $this->parent->getSession( 'test' ) === null ) { 00204 $requestTime = $r->getVal( 'LanguageRequestTime' ); 00205 if ( !$requestTime ) { 00206 // The most likely explanation is that the user was knocked back 00207 // from another page on POST due to session expiry 00208 $msg = 'config-session-expired'; 00209 } elseif ( time() - $requestTime > $lifetime ) { 00210 $msg = 'config-session-expired'; 00211 } else { 00212 $msg = 'config-no-session'; 00213 } 00214 $this->parent->showError( $msg, $wgLang->formatTimePeriod( $lifetime ) ); 00215 } else { 00216 if ( isset( $languages[$userLang] ) ) { 00217 $this->setVar( '_UserLang', $userLang ); 00218 } 00219 if ( isset( $languages[$contLang] ) ) { 00220 $this->setVar( 'wgLanguageCode', $contLang ); 00221 } 00222 00223 return 'continue'; 00224 } 00225 } elseif ( $this->parent->showSessionWarning ) { 00226 # The user was knocked back from another page to the start 00227 # This probably indicates a session expiry 00228 $this->parent->showError( 'config-session-expired', 00229 $wgLang->formatTimePeriod( $lifetime ) ); 00230 } 00231 00232 $this->parent->setSession( 'test', true ); 00233 00234 if ( !isset( $languages[$userLang] ) ) { 00235 $userLang = $this->getVar( '_UserLang', 'en' ); 00236 } 00237 if ( !isset( $languages[$contLang] ) ) { 00238 $contLang = $this->getVar( 'wgLanguageCode', 'en' ); 00239 } 00240 $this->startForm(); 00241 $s = Html::hidden( 'LanguageRequestTime', time() ) . 00242 $this->getLanguageSelector( 'uselang', 'config-your-language', $userLang, 00243 $this->parent->getHelpBox( 'config-your-language-help' ) ) . 00244 $this->getLanguageSelector( 'ContLang', 'config-wiki-language', $contLang, 00245 $this->parent->getHelpBox( 'config-wiki-language-help' ) ); 00246 $this->addHTML( $s ); 00247 $this->endForm( 'continue', false ); 00248 } 00249 00259 public function getLanguageSelector( $name, $label, $selectedCode, $helpHtml = '' ) { 00260 global $wgDummyLanguageCodes; 00261 00262 $s = $helpHtml; 00263 00264 $s .= Html::openElement( 'select', array( 'id' => $name, 'name' => $name, 00265 'tabindex' => $this->parent->nextTabIndex() ) ) . "\n"; 00266 00267 $languages = Language::fetchLanguageNames(); 00268 ksort( $languages ); 00269 foreach ( $languages as $code => $lang ) { 00270 if ( isset( $wgDummyLanguageCodes[$code] ) ) { 00271 continue; 00272 } 00273 $s .= "\n" . Xml::option( "$code - $lang", $code, $code == $selectedCode ); 00274 } 00275 $s .= "\n</select>\n"; 00276 00277 return $this->parent->label( $label, $name, $s ); 00278 } 00279 } 00280 00281 class WebInstaller_ExistingWiki extends WebInstallerPage { 00282 public function execute() { 00283 // If there is no LocalSettings.php, continue to the installer welcome page 00284 $vars = Installer::getExistingLocalSettings(); 00285 if ( !$vars ) { 00286 return 'skip'; 00287 } 00288 00289 // Check if the upgrade key supplied to the user has appeared in LocalSettings.php 00290 if ( $vars['wgUpgradeKey'] !== false 00291 && $this->getVar( '_UpgradeKeySupplied' ) 00292 && $this->getVar( 'wgUpgradeKey' ) === $vars['wgUpgradeKey'] 00293 ) { 00294 // It's there, so the user is authorized 00295 $status = $this->handleExistingUpgrade( $vars ); 00296 if ( $status->isOK() ) { 00297 return 'skip'; 00298 } else { 00299 $this->startForm(); 00300 $this->parent->showStatusBox( $status ); 00301 $this->endForm( 'continue' ); 00302 00303 return 'output'; 00304 } 00305 } 00306 00307 // If there is no $wgUpgradeKey, tell the user to add one to LocalSettings.php 00308 if ( $vars['wgUpgradeKey'] === false ) { 00309 if ( $this->getVar( 'wgUpgradeKey', false ) === false ) { 00310 $secretKey = $this->getVar( 'wgSecretKey' ); // preserve $wgSecretKey 00311 $this->parent->generateKeys(); 00312 $this->setVar( 'wgSecretKey', $secretKey ); 00313 $this->setVar( '_UpgradeKeySupplied', true ); 00314 } 00315 $this->startForm(); 00316 $this->addHTML( $this->parent->getInfoBox( 00317 wfMessage( 'config-upgrade-key-missing', "<pre dir=\"ltr\">\$wgUpgradeKey = '" . 00318 $this->getVar( 'wgUpgradeKey' ) . "';</pre>" )->plain() 00319 ) ); 00320 $this->endForm( 'continue' ); 00321 00322 return 'output'; 00323 } 00324 00325 // If there is an upgrade key, but it wasn't supplied, prompt the user to enter it 00326 00327 $r = $this->parent->request; 00328 if ( $r->wasPosted() ) { 00329 $key = $r->getText( 'config_wgUpgradeKey' ); 00330 if ( !$key || $key !== $vars['wgUpgradeKey'] ) { 00331 $this->parent->showError( 'config-localsettings-badkey' ); 00332 $this->showKeyForm(); 00333 00334 return 'output'; 00335 } 00336 // Key was OK 00337 $status = $this->handleExistingUpgrade( $vars ); 00338 if ( $status->isOK() ) { 00339 return 'continue'; 00340 } else { 00341 $this->parent->showStatusBox( $status ); 00342 $this->showKeyForm(); 00343 00344 return 'output'; 00345 } 00346 } else { 00347 $this->showKeyForm(); 00348 00349 return 'output'; 00350 } 00351 } 00352 00356 protected function showKeyForm() { 00357 $this->startForm(); 00358 $this->addHTML( 00359 $this->parent->getInfoBox( wfMessage( 'config-localsettings-upgrade' )->plain() ) . 00360 '<br />' . 00361 $this->parent->getTextBox( array( 00362 'var' => 'wgUpgradeKey', 00363 'label' => 'config-localsettings-key', 00364 'attribs' => array( 'autocomplete' => 'off' ), 00365 ) ) 00366 ); 00367 $this->endForm( 'continue' ); 00368 } 00369 00370 protected function importVariables( $names, $vars ) { 00371 $status = Status::newGood(); 00372 foreach ( $names as $name ) { 00373 if ( !isset( $vars[$name] ) ) { 00374 $status->fatal( 'config-localsettings-incomplete', $name ); 00375 } 00376 $this->setVar( $name, $vars[$name] ); 00377 } 00378 00379 return $status; 00380 } 00381 00387 protected function handleExistingUpgrade( $vars ) { 00388 // Check $wgDBtype 00389 if ( !isset( $vars['wgDBtype'] ) || 00390 !in_array( $vars['wgDBtype'], Installer::getDBTypes() ) 00391 ) { 00392 return Status::newFatal( 'config-localsettings-connection-error', '' ); 00393 } 00394 00395 // Set the relevant variables from LocalSettings.php 00396 $requiredVars = array( 'wgDBtype' ); 00397 $status = $this->importVariables( $requiredVars, $vars ); 00398 $installer = $this->parent->getDBInstaller(); 00399 $status->merge( $this->importVariables( $installer->getGlobalNames(), $vars ) ); 00400 if ( !$status->isOK() ) { 00401 return $status; 00402 } 00403 00404 if ( isset( $vars['wgDBadminuser'] ) ) { 00405 $this->setVar( '_InstallUser', $vars['wgDBadminuser'] ); 00406 } else { 00407 $this->setVar( '_InstallUser', $vars['wgDBuser'] ); 00408 } 00409 if ( isset( $vars['wgDBadminpassword'] ) ) { 00410 $this->setVar( '_InstallPassword', $vars['wgDBadminpassword'] ); 00411 } else { 00412 $this->setVar( '_InstallPassword', $vars['wgDBpassword'] ); 00413 } 00414 00415 // Test the database connection 00416 $status = $installer->getConnection(); 00417 if ( !$status->isOK() ) { 00418 // Adjust the error message to explain things correctly 00419 $status->replaceMessage( 'config-connection-error', 00420 'config-localsettings-connection-error' ); 00421 00422 return $status; 00423 } 00424 00425 // All good 00426 $this->setVar( '_ExistingDBSettings', true ); 00427 00428 return $status; 00429 } 00430 } 00431 00432 class WebInstaller_Welcome extends WebInstallerPage { 00433 00434 public function execute() { 00435 if ( $this->parent->request->wasPosted() ) { 00436 if ( $this->getVar( '_Environment' ) ) { 00437 return 'continue'; 00438 } 00439 } 00440 $this->parent->output->addWikiText( wfMessage( 'config-welcome' )->plain() ); 00441 $status = $this->parent->doEnvironmentChecks(); 00442 if ( $status->isGood() ) { 00443 $this->parent->output->addHTML( '<span class="success-message">' . 00444 wfMessage( 'config-env-good' )->escaped() . '</span>' ); 00445 $this->parent->output->addWikiText( wfMessage( 'config-copyright', 00446 SpecialVersion::getCopyrightAndAuthorList() )->plain() ); 00447 $this->startForm(); 00448 $this->endForm(); 00449 } else { 00450 $this->parent->showStatusMessage( $status ); 00451 } 00452 00453 return ''; 00454 } 00455 } 00456 00457 class WebInstaller_DBConnect extends WebInstallerPage { 00458 00459 public function execute() { 00460 if ( $this->getVar( '_ExistingDBSettings' ) ) { 00461 return 'skip'; 00462 } 00463 00464 $r = $this->parent->request; 00465 if ( $r->wasPosted() ) { 00466 $status = $this->submit(); 00467 00468 if ( $status->isGood() ) { 00469 $this->setVar( '_UpgradeDone', false ); 00470 00471 return 'continue'; 00472 } else { 00473 $this->parent->showStatusBox( $status ); 00474 } 00475 } 00476 00477 $this->startForm(); 00478 00479 $types = "<ul class=\"config-settings-block\">\n"; 00480 $settings = ''; 00481 $defaultType = $this->getVar( 'wgDBtype' ); 00482 00483 // Messages: config-dbsupport-mysql, config-dbsupport-postgres, config-dbsupport-oracle, 00484 // config-dbsupport-sqlite 00485 $dbSupport = ''; 00486 foreach ( $this->parent->getDBTypes() as $type ) { 00487 $dbSupport .= wfMessage( "config-dbsupport-$type" )->plain() . "\n"; 00488 } 00489 $this->addHTML( $this->parent->getInfoBox( 00490 wfMessage( 'config-support-info', trim( $dbSupport ) )->text() ) ); 00491 00492 // It's possible that the library for the default DB type is not compiled in. 00493 // In that case, instead select the first supported DB type in the list. 00494 $compiledDBs = $this->parent->getCompiledDBs(); 00495 if ( !in_array( $defaultType, $compiledDBs ) ) { 00496 $defaultType = $compiledDBs[0]; 00497 } 00498 00499 foreach ( $compiledDBs as $type ) { 00500 $installer = $this->parent->getDBInstaller( $type ); 00501 $types .= 00502 '<li>' . 00503 Xml::radioLabel( 00504 $installer->getReadableName(), 00505 'DBType', 00506 $type, 00507 "DBType_$type", 00508 $type == $defaultType, 00509 array( 'class' => 'dbRadio', 'rel' => "DB_wrapper_$type" ) 00510 ) . 00511 "</li>\n"; 00512 00513 // Messages: config-header-mysql, config-header-postgres, config-header-oracle, 00514 // config-header-sqlite 00515 $settings .= Html::openElement( 00516 'div', 00517 array( 00518 'id' => 'DB_wrapper_' . $type, 00519 'class' => 'dbWrapper' 00520 ) 00521 ) . 00522 Html::element( 'h3', array(), wfMessage( 'config-header-' . $type )->text() ) . 00523 $installer->getConnectForm() . 00524 "</div>\n"; 00525 } 00526 00527 $types .= "</ul><br style=\"clear: left\"/>\n"; 00528 00529 $this->addHTML( $this->parent->label( 'config-db-type', false, $types ) . $settings ); 00530 $this->endForm(); 00531 } 00532 00533 public function submit() { 00534 $r = $this->parent->request; 00535 $type = $r->getVal( 'DBType' ); 00536 if ( !$type ) { 00537 return Status::newFatal( 'config-invalid-db-type' ); 00538 } 00539 $this->setVar( 'wgDBtype', $type ); 00540 $installer = $this->parent->getDBInstaller( $type ); 00541 if ( !$installer ) { 00542 return Status::newFatal( 'config-invalid-db-type' ); 00543 } 00544 00545 return $installer->submitConnectForm(); 00546 } 00547 } 00548 00549 class WebInstaller_Upgrade extends WebInstallerPage { 00550 public function isSlow() { 00551 return true; 00552 } 00553 00554 public function execute() { 00555 if ( $this->getVar( '_UpgradeDone' ) ) { 00556 // Allow regeneration of LocalSettings.php, unless we are working 00557 // from a pre-existing LocalSettings.php file and we want to avoid 00558 // leaking its contents 00559 if ( $this->parent->request->wasPosted() && !$this->getVar( '_ExistingDBSettings' ) ) { 00560 // Done message acknowledged 00561 return 'continue'; 00562 } else { 00563 // Back button click 00564 // Show the done message again 00565 // Make them click back again if they want to do the upgrade again 00566 $this->showDoneMessage(); 00567 00568 return 'output'; 00569 } 00570 } 00571 00572 // wgDBtype is generally valid here because otherwise the previous page 00573 // (connect) wouldn't have declared its happiness 00574 $type = $this->getVar( 'wgDBtype' ); 00575 $installer = $this->parent->getDBInstaller( $type ); 00576 00577 if ( !$installer->needsUpgrade() ) { 00578 return 'skip'; 00579 } 00580 00581 if ( $this->parent->request->wasPosted() ) { 00582 $installer->preUpgrade(); 00583 00584 $this->startLiveBox(); 00585 $result = $installer->doUpgrade(); 00586 $this->endLiveBox(); 00587 00588 if ( $result ) { 00589 // If they're going to possibly regenerate LocalSettings, we 00590 // need to create the upgrade/secret keys. Bug 26481 00591 if ( !$this->getVar( '_ExistingDBSettings' ) ) { 00592 $this->parent->generateKeys(); 00593 } 00594 $this->setVar( '_UpgradeDone', true ); 00595 $this->showDoneMessage(); 00596 00597 return 'output'; 00598 } 00599 } 00600 00601 $this->startForm(); 00602 $this->addHTML( $this->parent->getInfoBox( 00603 wfMessage( 'config-can-upgrade', $GLOBALS['wgVersion'] )->plain() ) ); 00604 $this->endForm(); 00605 } 00606 00607 public function showDoneMessage() { 00608 $this->startForm(); 00609 $regenerate = !$this->getVar( '_ExistingDBSettings' ); 00610 if ( $regenerate ) { 00611 $msg = 'config-upgrade-done'; 00612 } else { 00613 $msg = 'config-upgrade-done-no-regenerate'; 00614 } 00615 $this->parent->disableLinkPopups(); 00616 $this->addHTML( 00617 $this->parent->getInfoBox( 00618 wfMessage( $msg, 00619 $this->getVar( 'wgServer' ) . 00620 $this->getVar( 'wgScriptPath' ) . '/index' . 00621 $this->getVar( 'wgScriptExtension' ) 00622 )->plain(), 'tick-32.png' 00623 ) 00624 ); 00625 $this->parent->restoreLinkPopups(); 00626 $this->endForm( $regenerate ? 'regenerate' : false, false ); 00627 } 00628 } 00629 00630 class WebInstaller_DBSettings extends WebInstallerPage { 00631 00632 public function execute() { 00633 $installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) ); 00634 00635 $r = $this->parent->request; 00636 if ( $r->wasPosted() ) { 00637 $status = $installer->submitSettingsForm(); 00638 if ( $status === false ) { 00639 return 'skip'; 00640 } elseif ( $status->isGood() ) { 00641 return 'continue'; 00642 } else { 00643 $this->parent->showStatusBox( $status ); 00644 } 00645 } 00646 00647 $form = $installer->getSettingsForm(); 00648 if ( $form === false ) { 00649 return 'skip'; 00650 } 00651 00652 $this->startForm(); 00653 $this->addHTML( $form ); 00654 $this->endForm(); 00655 } 00656 } 00657 00658 class WebInstaller_Name extends WebInstallerPage { 00659 00660 public function execute() { 00661 $r = $this->parent->request; 00662 if ( $r->wasPosted() ) { 00663 if ( $this->submit() ) { 00664 return 'continue'; 00665 } 00666 } 00667 00668 $this->startForm(); 00669 00670 // Encourage people to not name their site 'MediaWiki' by blanking the 00671 // field. I think that was the intent with the original $GLOBALS['wgSitename'] 00672 // but these two always were the same so had the effect of making the 00673 // installer forget $wgSitename when navigating back to this page. 00674 if ( $this->getVar( 'wgSitename' ) == 'MediaWiki' ) { 00675 $this->setVar( 'wgSitename', '' ); 00676 } 00677 00678 // Set wgMetaNamespace to something valid before we show the form. 00679 // $wgMetaNamespace defaults to $wgSiteName which is 'MediaWiki' 00680 $metaNS = $this->getVar( 'wgMetaNamespace' ); 00681 $this->setVar( 00682 'wgMetaNamespace', 00683 wfMessage( 'config-ns-other-default' )->inContentLanguage()->text() 00684 ); 00685 00686 $this->addHTML( 00687 $this->parent->getTextBox( array( 00688 'var' => 'wgSitename', 00689 'label' => 'config-site-name', 00690 'help' => $this->parent->getHelpBox( 'config-site-name-help' ) 00691 ) ) . 00692 // getRadioSet() builds a set of labeled radio buttons. 00693 // For grep: The following messages are used as the item labels: 00694 // config-ns-site-name, config-ns-generic, config-ns-other 00695 $this->parent->getRadioSet( array( 00696 'var' => '_NamespaceType', 00697 'label' => 'config-project-namespace', 00698 'itemLabelPrefix' => 'config-ns-', 00699 'values' => array( 'site-name', 'generic', 'other' ), 00700 'commonAttribs' => array( 'class' => 'enableForOther', 00701 'rel' => 'config_wgMetaNamespace' ), 00702 'help' => $this->parent->getHelpBox( 'config-project-namespace-help' ) 00703 ) ) . 00704 $this->parent->getTextBox( array( 00705 'var' => 'wgMetaNamespace', 00706 'label' => '', // @todo Needs a label? 00707 'attribs' => array( 'readonly' => 'readonly', 'class' => 'enabledByOther' ) 00708 ) ) . 00709 $this->getFieldSetStart( 'config-admin-box' ) . 00710 $this->parent->getTextBox( array( 00711 'var' => '_AdminName', 00712 'label' => 'config-admin-name', 00713 'help' => $this->parent->getHelpBox( 'config-admin-help' ) 00714 ) ) . 00715 $this->parent->getPasswordBox( array( 00716 'var' => '_AdminPassword', 00717 'label' => 'config-admin-password', 00718 ) ) . 00719 $this->parent->getPasswordBox( array( 00720 'var' => '_AdminPassword2', 00721 'label' => 'config-admin-password-confirm' 00722 ) ) . 00723 $this->parent->getTextBox( array( 00724 'var' => '_AdminEmail', 00725 'label' => 'config-admin-email', 00726 'help' => $this->parent->getHelpBox( 'config-admin-email-help' ) 00727 ) ) . 00728 $this->parent->getCheckBox( array( 00729 'var' => '_Subscribe', 00730 'label' => 'config-subscribe', 00731 'help' => $this->parent->getHelpBox( 'config-subscribe-help' ) 00732 ) ) . 00733 $this->getFieldSetEnd() . 00734 $this->parent->getInfoBox( wfMessage( 'config-almost-done' )->text() ) . 00735 // getRadioSet() builds a set of labeled radio buttons. 00736 // For grep: The following messages are used as the item labels: 00737 // config-optional-continue, config-optional-skip 00738 $this->parent->getRadioSet( array( 00739 'var' => '_SkipOptional', 00740 'itemLabelPrefix' => 'config-optional-', 00741 'values' => array( 'continue', 'skip' ) 00742 ) ) 00743 ); 00744 00745 // Restore the default value 00746 $this->setVar( 'wgMetaNamespace', $metaNS ); 00747 00748 $this->endForm(); 00749 00750 return 'output'; 00751 } 00752 00753 public function submit() { 00754 $retVal = true; 00755 $this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType', 00756 '_AdminName', '_AdminPassword', '_AdminPassword2', '_AdminEmail', 00757 '_Subscribe', '_SkipOptional', 'wgMetaNamespace' ) ); 00758 00759 // Validate site name 00760 if ( strval( $this->getVar( 'wgSitename' ) ) === '' ) { 00761 $this->parent->showError( 'config-site-name-blank' ); 00762 $retVal = false; 00763 } 00764 00765 // Fetch namespace 00766 $nsType = $this->getVar( '_NamespaceType' ); 00767 if ( $nsType == 'site-name' ) { 00768 $name = $this->getVar( 'wgSitename' ); 00769 // Sanitize for namespace 00770 // This algorithm should match the JS one in WebInstallerOutput.php 00771 $name = preg_replace( '/[\[\]\{\}|#<>%+? ]/', '_', $name ); 00772 $name = str_replace( '&', '&', $name ); 00773 $name = preg_replace( '/__+/', '_', $name ); 00774 $name = ucfirst( trim( $name, '_' ) ); 00775 } elseif ( $nsType == 'generic' ) { 00776 $name = wfMessage( 'config-ns-generic' )->text(); 00777 } else { // other 00778 $name = $this->getVar( 'wgMetaNamespace' ); 00779 } 00780 00781 // Validate namespace 00782 if ( strpos( $name, ':' ) !== false ) { 00783 $good = false; 00784 } else { 00785 // Title-style validation 00786 $title = Title::newFromText( $name ); 00787 if ( !$title ) { 00788 $good = $nsType == 'site-name'; 00789 } else { 00790 $name = $title->getDBkey(); 00791 $good = true; 00792 } 00793 } 00794 if ( !$good ) { 00795 $this->parent->showError( 'config-ns-invalid', $name ); 00796 $retVal = false; 00797 } 00798 00799 // Make sure it won't conflict with any existing namespaces 00800 global $wgContLang; 00801 $nsIndex = $wgContLang->getNsIndex( $name ); 00802 if ( $nsIndex !== false && $nsIndex !== NS_PROJECT ) { 00803 $this->parent->showError( 'config-ns-conflict', $name ); 00804 $retVal = false; 00805 } 00806 00807 $this->setVar( 'wgMetaNamespace', $name ); 00808 00809 // Validate username for creation 00810 $name = $this->getVar( '_AdminName' ); 00811 if ( strval( $name ) === '' ) { 00812 $this->parent->showError( 'config-admin-name-blank' ); 00813 $cname = $name; 00814 $retVal = false; 00815 } else { 00816 $cname = User::getCanonicalName( $name, 'creatable' ); 00817 if ( $cname === false ) { 00818 $this->parent->showError( 'config-admin-name-invalid', $name ); 00819 $retVal = false; 00820 } else { 00821 $this->setVar( '_AdminName', $cname ); 00822 } 00823 } 00824 00825 // Validate password 00826 $msg = false; 00827 $pwd = $this->getVar( '_AdminPassword' ); 00828 $user = User::newFromName( $cname ); 00829 $valid = $user && $user->getPasswordValidity( $pwd ); 00830 if ( strval( $pwd ) === '' ) { 00831 # $user->getPasswordValidity just checks for $wgMinimalPasswordLength. 00832 # This message is more specific and helpful. 00833 $msg = 'config-admin-password-blank'; 00834 } elseif ( $pwd !== $this->getVar( '_AdminPassword2' ) ) { 00835 $msg = 'config-admin-password-mismatch'; 00836 } elseif ( $valid !== true ) { 00837 # As of writing this will only catch the username being e.g. 'FOO' and 00838 # the password 'foo' 00839 $msg = $valid; 00840 } 00841 if ( $msg !== false ) { 00842 call_user_func_array( array( $this->parent, 'showError' ), (array)$msg ); 00843 $this->setVar( '_AdminPassword', '' ); 00844 $this->setVar( '_AdminPassword2', '' ); 00845 $retVal = false; 00846 } 00847 00848 // Validate e-mail if provided 00849 $email = $this->getVar( '_AdminEmail' ); 00850 if ( $email && !Sanitizer::validateEmail( $email ) ) { 00851 $this->parent->showError( 'config-admin-error-bademail' ); 00852 $retVal = false; 00853 } 00854 // If they asked to subscribe to mediawiki-announce but didn't give 00855 // an e-mail, show an error. Bug 29332 00856 if ( !$email && $this->getVar( '_Subscribe' ) ) { 00857 $this->parent->showError( 'config-subscribe-noemail' ); 00858 $retVal = false; 00859 } 00860 00861 return $retVal; 00862 } 00863 } 00864 00865 class WebInstaller_Options extends WebInstallerPage { 00866 public function execute() { 00867 if ( $this->getVar( '_SkipOptional' ) == 'skip' ) { 00868 return 'skip'; 00869 } 00870 if ( $this->parent->request->wasPosted() ) { 00871 if ( $this->submit() ) { 00872 return 'continue'; 00873 } 00874 } 00875 00876 $emailwrapperStyle = $this->getVar( 'wgEnableEmail' ) ? '' : 'display: none'; 00877 $this->startForm(); 00878 $this->addHTML( 00879 # User Rights 00880 // getRadioSet() builds a set of labeled radio buttons. 00881 // For grep: The following messages are used as the item labels: 00882 // config-profile-wiki, config-profile-no-anon, config-profile-fishbowl, config-profile-private 00883 $this->parent->getRadioSet( array( 00884 'var' => '_RightsProfile', 00885 'label' => 'config-profile', 00886 'itemLabelPrefix' => 'config-profile-', 00887 'values' => array_keys( $this->parent->rightsProfiles ), 00888 ) ) . 00889 $this->parent->getInfoBox( wfMessage( 'config-profile-help' )->plain() ) . 00890 00891 # Licensing 00892 // getRadioSet() builds a set of labeled radio buttons. 00893 // For grep: The following messages are used as the item labels: 00894 // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa, 00895 // config-license-cc-0, config-license-pd, config-license-gfdl, 00896 // config-license-none, config-license-cc-choose 00897 $this->parent->getRadioSet( array( 00898 'var' => '_LicenseCode', 00899 'label' => 'config-license', 00900 'itemLabelPrefix' => 'config-license-', 00901 'values' => array_keys( $this->parent->licenses ), 00902 'commonAttribs' => array( 'class' => 'licenseRadio' ), 00903 ) ) . 00904 $this->getCCChooser() . 00905 $this->parent->getHelpBox( 'config-license-help' ) . 00906 00907 # E-mail 00908 $this->getFieldSetStart( 'config-email-settings' ) . 00909 $this->parent->getCheckBox( array( 00910 'var' => 'wgEnableEmail', 00911 'label' => 'config-enable-email', 00912 'attribs' => array( 'class' => 'showHideRadio', 'rel' => 'emailwrapper' ), 00913 ) ) . 00914 $this->parent->getHelpBox( 'config-enable-email-help' ) . 00915 "<div id=\"emailwrapper\" style=\"$emailwrapperStyle\">" . 00916 $this->parent->getTextBox( array( 00917 'var' => 'wgPasswordSender', 00918 'label' => 'config-email-sender' 00919 ) ) . 00920 $this->parent->getHelpBox( 'config-email-sender-help' ) . 00921 $this->parent->getCheckBox( array( 00922 'var' => 'wgEnableUserEmail', 00923 'label' => 'config-email-user', 00924 ) ) . 00925 $this->parent->getHelpBox( 'config-email-user-help' ) . 00926 $this->parent->getCheckBox( array( 00927 'var' => 'wgEnotifUserTalk', 00928 'label' => 'config-email-usertalk', 00929 ) ) . 00930 $this->parent->getHelpBox( 'config-email-usertalk-help' ) . 00931 $this->parent->getCheckBox( array( 00932 'var' => 'wgEnotifWatchlist', 00933 'label' => 'config-email-watchlist', 00934 ) ) . 00935 $this->parent->getHelpBox( 'config-email-watchlist-help' ) . 00936 $this->parent->getCheckBox( array( 00937 'var' => 'wgEmailAuthentication', 00938 'label' => 'config-email-auth', 00939 ) ) . 00940 $this->parent->getHelpBox( 'config-email-auth-help' ) . 00941 "</div>" . 00942 $this->getFieldSetEnd() 00943 ); 00944 00945 $extensions = $this->parent->findExtensions(); 00946 00947 if ( $extensions ) { 00948 $extHtml = $this->getFieldSetStart( 'config-extensions' ); 00949 00950 /* Force a recache, so we load extensions descriptions */ 00951 global $wgLang; 00952 $lc = Language::getLocalisationCache(); 00953 $lc->setInitialisedLanguages( array() ); 00954 $lc->getItem( $wgLang->mCode, '' ); 00955 LinkCache::singleton()->useDatabase( false ); 00956 00957 foreach ( $extensions as $ext ) { 00958 if ( isset( $ext['descriptionmsg'] ) ) { 00959 $desc = wfMessage( $ext['descriptionmsg'] )->useDatabase( false )->parse(); 00960 } else { 00961 $desc = ''; 00962 } 00963 $extHtml .= $this->parent->getCheckBox( array( 00964 'var' => "ext-{$ext['name']}", 00965 'rawtext' => "<b>{$ext['name']}</b>: " . 00966 $desc, 00967 ) ); 00968 00969 } 00970 00971 $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) . 00972 $this->getFieldSetEnd(); 00973 $this->addHTML( $extHtml ); 00974 } 00975 00976 // Having / in paths in Windows looks funny :) 00977 $this->setVar( 'wgDeletedDirectory', 00978 str_replace( 00979 '/', DIRECTORY_SEPARATOR, 00980 $this->getVar( 'wgDeletedDirectory' ) 00981 ) 00982 ); 00983 // If we're using the default, let the user set it relative to $wgScriptPath 00984 $curLogo = $this->getVar( 'wgLogo' ); 00985 $logoString = ( $curLogo == "/wiki/skins/common/images/wiki.png" ) ? 00986 '$wgStylePath/common/images/wiki.png' : $curLogo; 00987 00988 $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none'; 00989 $this->addHTML( 00990 # Uploading 00991 $this->getFieldSetStart( 'config-upload-settings' ) . 00992 $this->parent->getCheckBox( array( 00993 'var' => 'wgEnableUploads', 00994 'label' => 'config-upload-enable', 00995 'attribs' => array( 'class' => 'showHideRadio', 'rel' => 'uploadwrapper' ), 00996 'help' => $this->parent->getHelpBox( 'config-upload-help' ) 00997 ) ) . 00998 '<div id="uploadwrapper" style="' . $uploadwrapperStyle . '">' . 00999 $this->parent->getTextBox( array( 01000 'var' => 'wgDeletedDirectory', 01001 'label' => 'config-upload-deleted', 01002 'attribs' => array( 'dir' => 'ltr' ), 01003 'help' => $this->parent->getHelpBox( 'config-upload-deleted-help' ) 01004 ) ) . 01005 '</div>' . 01006 $this->parent->getTextBox( array( 01007 'var' => 'wgLogo', 01008 'value' => $logoString, 01009 'label' => 'config-logo', 01010 'attribs' => array( 'dir' => 'ltr' ), 01011 'help' => $this->parent->getHelpBox( 'config-logo-help' ) 01012 ) ) 01013 ); 01014 $this->addHTML( 01015 $this->parent->getCheckBox( array( 01016 'var' => 'wgUseInstantCommons', 01017 'label' => 'config-instantcommons', 01018 'help' => $this->parent->getHelpBox( 'config-instantcommons-help' ) 01019 ) ) . 01020 $this->getFieldSetEnd() 01021 ); 01022 01023 $caches = array( 'none' ); 01024 if ( count( $this->getVar( '_Caches' ) ) ) { 01025 $caches[] = 'accel'; 01026 } 01027 $caches[] = 'memcached'; 01028 01029 // We'll hide/show this on demand when the value changes, see config.js. 01030 $cacheval = $this->getVar( 'wgMainCacheType' ); 01031 if ( !$cacheval ) { 01032 // We need to set a default here; but don't hardcode it 01033 // or we lose it every time we reload the page for validation 01034 // or going back! 01035 $cacheval = 'none'; 01036 } 01037 $hidden = ( $cacheval == 'memcached' ) ? '' : 'display: none'; 01038 $this->addHTML( 01039 # Advanced settings 01040 $this->getFieldSetStart( 'config-advanced-settings' ) . 01041 # Object cache settings 01042 // getRadioSet() builds a set of labeled radio buttons. 01043 // For grep: The following messages are used as the item labels: 01044 // config-cache-none, config-cache-accel, config-cache-memcached 01045 $this->parent->getRadioSet( array( 01046 'var' => 'wgMainCacheType', 01047 'label' => 'config-cache-options', 01048 'itemLabelPrefix' => 'config-cache-', 01049 'values' => $caches, 01050 'value' => $cacheval, 01051 ) ) . 01052 $this->parent->getHelpBox( 'config-cache-help' ) . 01053 "<div id=\"config-memcachewrapper\" style=\"$hidden\">" . 01054 $this->parent->getTextArea( array( 01055 'var' => '_MemCachedServers', 01056 'label' => 'config-memcached-servers', 01057 'help' => $this->parent->getHelpBox( 'config-memcached-help' ) 01058 ) ) . 01059 '</div>' . 01060 $this->getFieldSetEnd() 01061 ); 01062 $this->endForm(); 01063 } 01064 01068 public function getCCPartnerUrl() { 01069 $server = $this->getVar( 'wgServer' ); 01070 $exitUrl = $server . $this->parent->getUrl( array( 01071 'page' => 'Options', 01072 'SubmitCC' => 'indeed', 01073 'config__LicenseCode' => 'cc', 01074 'config_wgRightsUrl' => '[license_url]', 01075 'config_wgRightsText' => '[license_name]', 01076 'config_wgRightsIcon' => '[license_button]', 01077 ) ); 01078 $styleUrl = $server . dirname( dirname( $this->parent->getUrl() ) ) . 01079 '/skins/common/config-cc.css'; 01080 $iframeUrl = 'http://creativecommons.org/license/?' . 01081 wfArrayToCgi( array( 01082 'partner' => 'MediaWiki', 01083 'exit_url' => $exitUrl, 01084 'lang' => $this->getVar( '_UserLang' ), 01085 'stylesheet' => $styleUrl, 01086 ) ); 01087 01088 return $iframeUrl; 01089 } 01090 01091 public function getCCChooser() { 01092 $iframeAttribs = array( 01093 'class' => 'config-cc-iframe', 01094 'name' => 'config-cc-iframe', 01095 'id' => 'config-cc-iframe', 01096 'frameborder' => 0, 01097 'width' => '100%', 01098 'height' => '100%', 01099 ); 01100 if ( $this->getVar( '_CCDone' ) ) { 01101 $iframeAttribs['src'] = $this->parent->getUrl( array( 'ShowCC' => 'yes' ) ); 01102 } else { 01103 $iframeAttribs['src'] = $this->getCCPartnerUrl(); 01104 } 01105 $wrapperStyle = ( $this->getVar( '_LicenseCode' ) == 'cc-choose' ) ? '' : 'display: none'; 01106 01107 return "<div class=\"config-cc-wrapper\" id=\"config-cc-wrapper\" style=\"$wrapperStyle\">\n" . 01108 Html::element( 'iframe', $iframeAttribs, '', false /* not short */ ) . 01109 "</div>\n"; 01110 } 01111 01112 public function getCCDoneBox() { 01113 $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';"; 01114 // If you change this height, also change it in config.css 01115 $expandJs = str_replace( '$1', '54em', $js ); 01116 $reduceJs = str_replace( '$1', '70px', $js ); 01117 01118 return '<p>' . 01119 Html::element( 'img', array( 'src' => $this->getVar( 'wgRightsIcon' ) ) ) . 01120 '  ' . 01121 htmlspecialchars( $this->getVar( 'wgRightsText' ) ) . 01122 "</p>\n" . 01123 "<p style=\"text-align: center;\">" . 01124 Html::element( 'a', 01125 array( 01126 'href' => $this->getCCPartnerUrl(), 01127 'onclick' => $expandJs, 01128 ), 01129 wfMessage( 'config-cc-again' )->text() 01130 ) . 01131 "</p>\n" . 01132 "<script>\n" . 01133 # Reduce the wrapper div height 01134 htmlspecialchars( $reduceJs ) . 01135 "\n" . 01136 "</script>\n"; 01137 } 01138 01139 public function submitCC() { 01140 $newValues = $this->parent->setVarsFromRequest( 01141 array( 'wgRightsUrl', 'wgRightsText', 'wgRightsIcon' ) ); 01142 if ( count( $newValues ) != 3 ) { 01143 $this->parent->showError( 'config-cc-error' ); 01144 01145 return; 01146 } 01147 $this->setVar( '_CCDone', true ); 01148 $this->addHTML( $this->getCCDoneBox() ); 01149 } 01150 01151 public function submit() { 01152 $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode', 01153 'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo', 01154 'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist', 01155 'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers', 01156 'wgUseInstantCommons' ) ); 01157 01158 if ( !in_array( $this->getVar( '_RightsProfile' ), 01159 array_keys( $this->parent->rightsProfiles ) ) 01160 ) { 01161 reset( $this->parent->rightsProfiles ); 01162 $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) ); 01163 } 01164 01165 $code = $this->getVar( '_LicenseCode' ); 01166 if ( $code == 'cc-choose' ) { 01167 if ( !$this->getVar( '_CCDone' ) ) { 01168 $this->parent->showError( 'config-cc-not-chosen' ); 01169 01170 return false; 01171 } 01172 } elseif ( in_array( $code, array_keys( $this->parent->licenses ) ) ) { 01173 // Messages: 01174 // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa, 01175 // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none, 01176 // config-license-cc-choose 01177 $entry = $this->parent->licenses[$code]; 01178 if ( isset( $entry['text'] ) ) { 01179 $this->setVar( 'wgRightsText', $entry['text'] ); 01180 } else { 01181 $this->setVar( 'wgRightsText', wfMessage( 'config-license-' . $code )->text() ); 01182 } 01183 $this->setVar( 'wgRightsUrl', $entry['url'] ); 01184 $this->setVar( 'wgRightsIcon', $entry['icon'] ); 01185 } else { 01186 $this->setVar( 'wgRightsText', '' ); 01187 $this->setVar( 'wgRightsUrl', '' ); 01188 $this->setVar( 'wgRightsIcon', '' ); 01189 } 01190 01191 $extsAvailable = array_map( 01192 function( $e ) { 01193 if( isset( $e['name'] ) ) { 01194 return $e['name']; 01195 } 01196 }, $this->parent->findExtensions() ); 01197 $extsToInstall = array(); 01198 foreach ( $extsAvailable as $key => $ext ) { 01199 if ( $this->parent->request->getCheck( 'config_ext-' . $ext ) ) { 01200 $extsToInstall[] = $extsAvailable[ $key ]; 01201 } 01202 } 01203 $this->parent->setVar( '_Extensions', $extsToInstall ); 01204 01205 if ( $this->getVar( 'wgMainCacheType' ) == 'memcached' ) { 01206 $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) ); 01207 if ( !$memcServers ) { 01208 $this->parent->showError( 'config-memcache-needservers' ); 01209 01210 return false; 01211 } 01212 01213 foreach ( $memcServers as $server ) { 01214 $memcParts = explode( ":", $server, 2 ); 01215 if ( !isset( $memcParts[0] ) 01216 || ( !IP::isValid( $memcParts[0] ) 01217 && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) ) 01218 ) { 01219 $this->parent->showError( 'config-memcache-badip', $memcParts[0] ); 01220 01221 return false; 01222 } elseif ( !isset( $memcParts[1] ) ) { 01223 $this->parent->showError( 'config-memcache-noport', $memcParts[0] ); 01224 01225 return false; 01226 } elseif ( $memcParts[1] < 1 || $memcParts[1] > 65535 ) { 01227 $this->parent->showError( 'config-memcache-badport', 1, 65535 ); 01228 01229 return false; 01230 } 01231 } 01232 } 01233 01234 return true; 01235 } 01236 } 01237 01238 class WebInstaller_Install extends WebInstallerPage { 01239 public function isSlow() { 01240 return true; 01241 } 01242 01243 public function execute() { 01244 if ( $this->getVar( '_UpgradeDone' ) ) { 01245 return 'skip'; 01246 } elseif ( $this->getVar( '_InstallDone' ) ) { 01247 return 'continue'; 01248 } elseif ( $this->parent->request->wasPosted() ) { 01249 $this->startForm(); 01250 $this->addHTML( "<ul>" ); 01251 $results = $this->parent->performInstallation( 01252 array( $this, 'startStage' ), 01253 array( $this, 'endStage' ) 01254 ); 01255 $this->addHTML( "</ul>" ); 01256 // PerformInstallation bails on a fatal, so make sure the last item 01257 // completed before giving 'next.' Likewise, only provide back on failure 01258 $lastStep = end( $results ); 01259 $continue = $lastStep->isOK() ? 'continue' : false; 01260 $back = $lastStep->isOK() ? false : 'back'; 01261 $this->endForm( $continue, $back ); 01262 } else { 01263 $this->startForm(); 01264 $this->addHTML( $this->parent->getInfoBox( wfMessage( 'config-install-begin' )->plain() ) ); 01265 $this->endForm(); 01266 } 01267 01268 return true; 01269 } 01270 01271 public function startStage( $step ) { 01272 // Messages: config-install-database, config-install-tables, config-install-interwiki, 01273 // config-install-stats, config-install-keys, config-install-sysop, config-install-mainpage 01274 $this->addHTML( "<li>" . wfMessage( "config-install-$step" )->escaped() . 01275 wfMessage( 'ellipsis' )->escaped() ); 01276 01277 if ( $step == 'extension-tables' ) { 01278 $this->startLiveBox(); 01279 } 01280 } 01281 01286 public function endStage( $step, $status ) { 01287 if ( $step == 'extension-tables' ) { 01288 $this->endLiveBox(); 01289 } 01290 $msg = $status->isOk() ? 'config-install-step-done' : 'config-install-step-failed'; 01291 $html = wfMessage( 'word-separator' )->escaped() . wfMessage( $msg )->escaped(); 01292 if ( !$status->isOk() ) { 01293 $html = "<span class=\"error\">$html</span>"; 01294 } 01295 $this->addHTML( $html . "</li>\n" ); 01296 if ( !$status->isGood() ) { 01297 $this->parent->showStatusBox( $status ); 01298 } 01299 } 01300 } 01301 01302 class WebInstaller_Complete extends WebInstallerPage { 01303 public function execute() { 01304 // Pop up a dialog box, to make it difficult for the user to forget 01305 // to download the file 01306 $lsUrl = $this->getVar( 'wgServer' ) . $this->parent->getURL( array( 'localsettings' => 1 ) ); 01307 if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && 01308 strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) !== false 01309 ) { 01310 // JS appears to be the only method that works consistently with IE7+ 01311 $this->addHtml( "\n<script>jQuery( function () { document.location = " . 01312 Xml::encodeJsVar( $lsUrl ) . "; } );</script>\n" ); 01313 } else { 01314 $this->parent->request->response()->header( "Refresh: 0;url=$lsUrl" ); 01315 } 01316 01317 $this->startForm(); 01318 $this->parent->disableLinkPopups(); 01319 $this->addHTML( 01320 $this->parent->getInfoBox( 01321 wfMessage( 'config-install-done', 01322 $lsUrl, 01323 $this->getVar( 'wgServer' ) . 01324 $this->getVar( 'wgScriptPath' ) . '/index' . 01325 $this->getVar( 'wgScriptExtension' ), 01326 '<downloadlink/>' 01327 )->plain(), 'tick-32.png' 01328 ) 01329 ); 01330 $this->addHTML( $this->parent->getInfoBox( 01331 wfMessage( 'config-extension-link' )->text() ) ); 01332 01333 $this->parent->restoreLinkPopups(); 01334 $this->endForm( false, false ); 01335 } 01336 } 01337 01338 class WebInstaller_Restart extends WebInstallerPage { 01339 01340 public function execute() { 01341 $r = $this->parent->request; 01342 if ( $r->wasPosted() ) { 01343 $really = $r->getVal( 'submit-restart' ); 01344 if ( $really ) { 01345 $this->parent->reset(); 01346 } 01347 01348 return 'continue'; 01349 } 01350 01351 $this->startForm(); 01352 $s = $this->parent->getWarningBox( wfMessage( 'config-help-restart' )->plain() ); 01353 $this->addHTML( $s ); 01354 $this->endForm( 'restart' ); 01355 } 01356 } 01357 01358 abstract class WebInstaller_Document extends WebInstallerPage { 01359 01360 abstract protected function getFileName(); 01361 01362 public function execute() { 01363 $text = $this->getFileContents(); 01364 $text = InstallDocFormatter::format( $text ); 01365 $this->parent->output->addWikiText( $text ); 01366 $this->startForm(); 01367 $this->endForm( false ); 01368 } 01369 01370 public function getFileContents() { 01371 $file = __DIR__ . '/../../' . $this->getFileName(); 01372 if ( !file_exists( $file ) ) { 01373 return wfMessage( 'config-nofile', $file )->plain(); 01374 } 01375 01376 return file_get_contents( $file ); 01377 } 01378 } 01379 01380 class WebInstaller_Readme extends WebInstaller_Document { 01381 protected function getFileName() { 01382 return 'README'; 01383 } 01384 } 01385 01386 class WebInstaller_ReleaseNotes extends WebInstaller_Document { 01387 protected function getFileName() { 01388 global $wgVersion; 01389 01390 if ( !preg_match( '/^(\d+)\.(\d+).*/i', $wgVersion, $result ) ) { 01391 throw new MWException( 'Variable $wgVersion has an invalid value.' ); 01392 } 01393 01394 return 'RELEASE-NOTES-' . $result[1] . '.' . $result[2]; 01395 } 01396 } 01397 01398 class WebInstaller_UpgradeDoc extends WebInstaller_Document { 01399 protected function getFileName() { 01400 return 'UPGRADE'; 01401 } 01402 } 01403 01404 class WebInstaller_Copying extends WebInstaller_Document { 01405 protected function getFileName() { 01406 return 'COPYING'; 01407 } 01408 }