MediaWiki  REL1_22
WebInstallerPage.php
Go to the documentation of this file.
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( '&', '&amp;', $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             '&#160;&#160;' .
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 }