Merge "Installer: properly override default $wgLogo value"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 15 May 2014 13:21:21 +0000 (13:21 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 15 May 2014 13:21:21 +0000 (13:21 +0000)
1  2 
RELEASE-NOTES-1.23
includes/installer/Installer.php
includes/installer/WebInstallerPage.php

diff --combined RELEASE-NOTES-1.23
@@@ -9,14 -9,9 +9,14 @@@ MediaWiki 1.23 is an alpha-quality bran
  production.
  
  === Configuration changes in 1.23 ===
 +* Introduced $wgPagePropsHaveSortkey as a backwards-compatibility switch,
 +  for using the old schema of the page_props table, in case the respective
 +  schema update was not applied.
  * When $wgJobRunRate is higher that zero, jobs are now executed via an
    asynchronous HTTP request to a MediaWiki entry point. This may require
 -  increasing the number of server worker threads.
 +  increasing the number of server worker threads. $wgRunJobsAsync has been
 +  added to disable this feature if needed, falling back to executing the job
 +  on the same process but making the execution synchronously.
  * $wgDebugLogGroups values may be set to an associative array with a
    'destination' key specifying the log destination. The array may also contain
    a 'sample' key with a positive integer value N indicating that the log group
  * $wgPasswordSenderName has been removed and is no longer functional. To set a
    custom mailer name, the system message 'emailsender' should be modified
    (default: "{{SITENAME}}").
 +* (bug 63269) Email notifications were not correctly handling the
 +  [[MediaWiki:Helppage]] message being set to a full URL (the default).
 +  If you customized [[MediaWiki:Enotif body]] (the text of email notifications),
 +  you'll need to edit it locally to include the URL via the new variable
 +  $HELPPAGE instead of the parser functions fullurl and canonicalurl; otherwise
 +  you don't have to do anything.
  * $wgDBAhandler was removed as the only class using it was also removed
  * The 'max threads' setting was removed from $wgDBservers.
  * Support for AdminSettings.php has been completely removed. All configuration
    allows more than one value of $wgLocalInterwiki to be specified and
    understood by the parser. The value of $wgLocalInterwiki is automatically
    prepended to the start of this array.
 +* $wgQueryPages has been removed. Query Pages should be added to by using the
 +  wgQueryPages hook.
 +* $wgHttpOnlyBlacklist has been removed.
 +* $wgLicenseTerms has been removed as it was unused.
 +* $wgProfileOnly is now deprecated; set the log file in
 +  $wgDebugLogGroups['profileoutput'] to replace it.
 +* $wgMaxBacklinksInvalidate was removed; use $wgJobBackoffThrottling instead
 +* Deprecated ResourceLoaderGetStartupModules hook.
  
  === New features in 1.23 ===
  * ResourceLoader can utilize the Web Storage API to cache modules client-side.
  * Special:UserLogin/signup now does AJAX checks for invalid and taken usernames,
    displaying the error live.
  * Added BaseTemplateAfterPortlet hook to allow injecting html after portlets in skins.
 +* Support has been added for a JSON based localisation file format. The
 +  installer has been updated to use it.
 +* Changes to content typography (fonts, line-height, etc.). See
 +  https://www.mediawiki.org/wiki/Typography_refresh for further information.
 +* The Vector skin's visual treatment of external links has been simplified to a
 +  single icon (from nine). This should not affect local rules unless they were
 +  re-using these icons, which have now been deleted.
 +* ResourceLoader: mw.loader.using() now implements a Promise interface.
 +* Add new hook ChangesListInitRows accessed via ChangesList::initChangesListRows.
 +  If called by the ChangesList consumer this gives extensions a chance to batch
 +  process the result set prior to rendering.
 +* A PoolCounterRedis class was added which can be make use of in $wgPoolCounterConf.
 +  This requires at least one Redis 2.6+ server.
 +* $wgProfileToDatabase was removed. Set $wgProfiler to ProfilerSimpleDB
 +  in StartProfiler.php instead of using this.
 +* (bug 63444) Made it possible to change the indent string (default: 4 spaces)
 +  used by FormatJson::encode().
  
  === Bug fixes in 1.23 ===
  * (bug 41759) The "updated since last visit" markers (on history pages, recent
    when the email address is already confirmed. Also, consistently use
    "confirmed", rather than "authenticated", when messaging whether or not the
    user has confirmed an email address.
 +* (bug 19415) action=render no longer shows section edit links. This affects
 +  behavior of several other features where (bogus) section edit links will
 +  disappear, such as file description pages loaded via $wgUseInstantCommons or
 +  pages transcluded cross-wiki via $wgEnableScaryTranscluding.
  * (bug 56912) Show correct link color on cached result of Special:DeadendPages.
  * Classes TitleListDependency and TitleDependency have been removed, as they
    have been found unused in core and extensions for a long time.
    no longer applies in such cases.
  * (bug 60960) Avoid doing file_exist() checks on data: URIs, as they cause
    warnings to be printed on Windows due to large path length.
+ * (bug 48084) Fixed a bug in the installer that could cause $wgLogo to hold
+   the wrong path to the placeholder logo (skins/common/images/wiki.png).
  
  === Web API changes in 1.23 ===
  * (bug 54884) action=parse&prop=categories now indicates hidden and missing
  * (bug 42026) Added ucshow={new,!new,top,!top} to list=usercontribs.
    Also added newonly to action=feedcontributions.
  * (bug 42026) Deprecated uctoponly in favor of ucshow=top.
 +* list=search no longer has a "srredirects" parameter. Redirects are now
 +  included in all searches.
 +* Added list=prefixsearch that works like action=opensearch but can be used as
 +  a generator.
 +* (bug 24782) Various modules will now use unique continuation parameters.
 +* (bug 63249) Cache RecentChanges Atom feed in varnish for 15 seconds.
  
  === Languages updated in 1.23 ===
  
@@@ -271,14 -227,9 +273,14 @@@ MediaWiki supports over 350 languages. 
  regularly. Below only new and removed languages are listed, as well as
  changes to languages because of Bugzilla reports.
  
 +* Support was added for Algerian Spoken Arabic (arq).
 +* Support was added for Riograndenser Hunsrückisch (hrx).
  * Support was added for Northern Luri (lrc).
  
  === Other changes in 1.23 ===
 +* Added pp_sortkey column to page_props table, so pages can be efficiently
 +  queried and sorted by property value (bug 58032).
 +  See $wgPagePropsHaveSortkey if you want to postpone the schema change.
  * The rc_type field in the recentchanges table has been superseded by a new
    rc_source field.  The rc_source field is a string representation of the
    change type where rc_type was a numeric constant.  This field is not yet
  * (bug 52812) Removed "Disable search suggestions" from Preference.
  * (bug 52809) Removed "Disable browser page caching" from Preference.
  * Three new modules intended for use by custom skins were added:
 -  'skins.common.elements', 'skins.common.content', and 'skins.common.interface',
 -  representing three levels of standard MediaWiki styling. Previously skin
 -  creators wishing to use them had to refer to the file names of appropriate
 -  files directly, which is now discouraged.
 +  'mediawiki.skinning.elements', 'mediawiki.skinning.content', and
 +  'mediawiki.skinning.interface', representing three levels of standard
 +  MediaWiki styling. Previously skin creators wishing to use them had to refer
 +  to the file names of appropriate files directly, which is now discouraged.
  * The modules 'skins.vector' and 'skins.monobook' have been renamed to
    'skins.vector.styles' and 'skins.monobook.styles', respectively,
    and their definition was changed not to include the common*.css files;
 -  the two skins now load the 'skins.common.interface' module instead.
 +  the two skins now load the 'mediawiki.skinning.interface' module instead.
  * A page_links_updated field has been added to the page table.
  * SpecialPage::getTitle has been deprecated in favor of
    SpecialPage::getPageTitle.
    us to extend parser tests to accommodate additional input/output
    pairs, such as "!!html/parsoid" (for the output of the Parsoid
    parser, where it differs from the PHP parser).
 +* Special:Search no longer has an "include redirects" option on the advanced
 +  tab. Redirects are now included in all searches.
 +* mediawiki.api.category's getCategories() 'async' parameter was deprecated.
 +* The locations of resources have been split between upstream libraries, now in
 +  resources/lib/, local libaries in resources/src/, and local forks of upstream
 +  libraries, also in resources/src/.
 +* BREAKING CHANGE: The automatically-generated function closure with which
 +  ResourceLoader wraps all modules' JavaScript code now binds the identifier
 +  names 'jQuery' and '$' to the jQuery object of the version of jQuery that is
 +  bundled with MediaWiki. If you bind these names to other objects in global
 +  scope (like Zepto.js or document.querySelectorAll, for example) you will need
 +  to use different names to or re-bind them at the top of each
 +  ResourceLoader-loaded module.
 +* (bug 52342) Preference "Remember my login" was removed.
  
  ==== Removed classes ====
  * FakeMemCachedClient (deprecated in 1.18)
@@@ -516,7 -453,7 +518,7 @@@ Don't forget to always back up your dat
  
  See the file UPGRADE for more detailed upgrade instructions.
  
 -For notes on 1.21.x and older releases, see HISTORY.
 +For notes on 1.22.x and older releases, see HISTORY.
  
  == Online documentation ==
  
@@@ -71,7 -71,7 +71,7 @@@ abstract class Installer 
        /**
         * Minimum memory size in MB.
         *
 -       * @var integer
 +       * @var int
         */
        protected $minMemorySize = 50;
  
                'wgMetaNamespace',
                'wgDeletedDirectory',
                'wgEnableUploads',
-               'wgLogo',
                'wgShellLocale',
                'wgSecretKey',
                'wgUseInstantCommons',
                '_NamespaceType' => 'site-name',
                '_AdminName' => '', // will be set later, when the user selects language
                '_AdminPassword' => '',
 -              '_AdminPassword2' => '',
 +              '_AdminPasswordConfirm' => '',
                '_AdminEmail' => '',
                '_Subscribe' => false,
                '_SkipOptional' => 'continue',
                '_MemCachedServers' => '',
                '_UpgradeKeySupplied' => false,
                '_ExistingDBSettings' => false,
+               // $wgLogo is probably wrong (bug 48084); set something that will work.
+               // Single quotes work fine here, as LocalSettingsGenerator outputs this unescaped.
+               'wgLogo' => '$wgStylePath/common/images/wiki.png',
        );
  
        /**
         * The parameters are like parameters to wfMessage().
         * The messages will be in wikitext format, which will be converted to an
         * output format such as HTML or text before being sent to the user.
 -       * @param $msg
 +       * @param string $msg
         */
        abstract public function showMessage( $msg /*, ... */ );
  
        /**
         * Same as showMessage(), but for displaying errors
 -       * @param $msg
 +       * @param string $msg
         */
        abstract public function showError( $msg /*, ... */ );
  
        /**
         * Show a message to the installing user by using a Status object
 -       * @param $status Status
 +       * @param Status $status
         */
        abstract public function showStatusMessage( Status $status );
  
         * Constructor, always call this from child classes.
         */
        public function __construct() {
 -              global $wgExtensionMessagesFiles, $wgUser;
 +              global $wgMessagesDirs, $wgUser;
  
                // Disable the i18n cache and LoadBalancer
                Language::getLocalisationCache()->disableBackend();
                LBFactory::disableBackend();
  
 -              // Load the installer's i18n file.
 -              $wgExtensionMessagesFiles['MediawikiInstaller'] =
 -                      __DIR__ . '/Installer.i18n.php';
 +              // Load the installer's i18n.
 +              $wgMessagesDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
  
                // Having a user with id = 0 safeguards us from DB access via User::loadOptions().
                $wgUser = User::newFromId( 0 );
        /**
         * Set a MW configuration variable, or internal installer configuration variable.
         *
 -       * @param $name String
 -       * @param $value Mixed
 +       * @param string $name
 +       * @param mixed $value
         */
        public function setVar( $name, $value ) {
                $this->settings[$name] = $value;
         * The defaults come from $GLOBALS (ultimately DefaultSettings.php).
         * Installer variables are typically prefixed by an underscore.
         *
 -       * @param $name String
 -       * @param $default Mixed
 +       * @param string $name
 +       * @param mixed $default
         *
         * @return mixed
         */
        /**
         * Get an instance of DatabaseInstaller for the specified DB type.
         *
 -       * @param $type Mixed: DB installer for which is needed, false to use default.
 +       * @param mixed $type DB installer for which is needed, false to use default.
         *
         * @return DatabaseInstaller
         */
        /**
         * Determine if LocalSettings.php exists. If it does, return its variables.
         *
 -       * @return Array
 +       * @return array
         */
        public static function getExistingLocalSettings() {
                global $IP;
         * This is a security mechanism to avoid compromise of the password in the
         * event of session ID compromise.
         *
 -       * @param $realPassword String
 +       * @param string $realPassword
         *
         * @return string
         */
         * Set a variable which stores a password, except if the new value is a
         * fake password in which case leave it as it is.
         *
 -       * @param $name String
 -       * @param $value Mixed
 +       * @param string $name
 +       * @param mixed $value
         */
        public function setPassword( $name, $value ) {
                if ( !preg_match( '/^\*+$/', $value ) ) {
         * whatever, this function is guarded to catch the attempted DB access and to present
         * some fallback text.
         *
 -       * @param $text String
 -       * @param $lineStart Boolean
 -       * @return String
 +       * @param string $text
 +       * @param bool $lineStart
 +       * @return string
         */
        public function parse( $text, $lineStart = false ) {
                global $wgParser;
         * Install step which adds a row to the site_stats table with appropriate
         * initial values.
         *
 -       * @param $installer DatabaseInstaller
 +       * @param DatabaseInstaller $installer
         *
         * @return Status
         */
  
        /**
         * Helper function to be called from envCheckServer()
 -       * @return String
 +       * @return string
         */
        abstract protected function envGetDefaultServer();
  
  
        /**
         * Convert a hex string representing a Unicode code point to that code point.
 -       * @param $c String
 +       * @param string $c
         * @return string
         */
        protected function unicodeChar( $c ) {
         * of known Unix-like defaults, as well as the PATH environment variable
         * (which should maybe make it work for Windows?)
         *
 -       * @return Array
 +       * @return array
         */
        protected static function getPossibleBinPaths() {
                return array_merge(
         *
         * @param string $path path to search
         * @param array $names of executable names
 -       * @param $versionInfo Boolean false or array with two members:
 -       *         0 => Command to run for version check, with $1 for the full executable name
 -       *         1 => String to compare the output with
 +       * @param array|bool $versionInfo False or array with two members:
 +       *   0 => Command to run for version check, with $1 for the full executable name
 +       *   1 => String to compare the output with
         *
         * If $versionInfo is not false, only executables with a version
         * matching $versionInfo[1] will be returned.
         * @see locateExecutable()
         * @param array $names Array of possible names.
         * @param array|bool $versionInfo Default: false or array with two members:
 -       *         0 => Command to run for version check, with $1 for the full executable name
 -       *         1 => String to compare the output with
 +       *   0 => Command to run for version check, with $1 for the full executable name
 +       *   1 => String to compare the output with
         *
         * If $versionInfo is not false, only executables with a version
         * matching $versionInfo[1] will be returned.
         * Checks if scripts located in the given directory can be executed via the given URL.
         *
         * Used only by environment checks.
 -       * @param $dir string
 -       * @param $url string
 +       * @param string $dir
 +       * @param string $url
         * @return bool|int|string
         */
        public function dirIsExecutable( $dir, $url ) {
        /**
         * ParserOptions are constructed before we determined the language, so fix it
         *
 -       * @param $lang Language
 +       * @param Language $lang
         */
        public function setParserLanguage( $lang ) {
                $this->parserOptions->setTargetLanguage( $lang );
  
        /**
         * Overridden by WebInstaller to provide lastPage parameters.
 -       * @param $page string
 +       * @param string $page
         * @return string
         */
        protected function getDocUrl( $page ) {
         * There must be a config-install-$name message defined per step, which will
         * be shown on install.
         *
 -       * @param $installer DatabaseInstaller so we can make callbacks
 +       * @param DatabaseInstaller $installer DatabaseInstaller so we can make callbacks
         * @return array
         */
        protected function getInstallSteps( DatabaseInstaller $installer ) {
         * @param array $startCB A callback array for the beginning of each step
         * @param array $endCB A callback array for the end of each step
         *
 -       * @return Array of Status objects
 +       * @return array Array of Status objects
         */
        public function performInstallation( $startCB, $endCB ) {
                $installResults = array();
         * Generate a secret value for variables using our CryptRand generator.
         * Produce a warning if the random source was insecure.
         *
 -       * @param $keys Array
 +       * @param array $keys
         * @return Status
         */
        protected function doGenerateKeys( $keys ) {
        }
  
        /**
 -       * @param $s Status
 +       * @param Status $s
         */
        private function subscribeToMediaWikiAnnounce( Status $s ) {
                $params = array(
        /**
         * Insert Main Page with default content.
         *
 -       * @param $installer DatabaseInstaller
 +       * @param DatabaseInstaller $installer
         * @return Status
         */
        protected function createMainpage( DatabaseInstaller $installer ) {
         *
         * @param array $callback A valid installation callback array, in this form:
         *    array( 'name' => 'some-unique-name', 'callback' => array( $obj, 'function' ) );
 -       * @param string $findStep the step to find. Omit to put the step at the beginning
 +       * @param string $findStep The step to find. Omit to put the step at the beginning
         */
        public function addInstallStep( $callback, $findStep = 'BEGINNING' ) {
                $this->extraInstallSteps[$findStep][] = $callback;
@@@ -36,13 -36,12 +36,13 @@@ abstract class WebInstallerPage 
         */
        public $parent;
  
 +      /**
 +       * @return string
 +       */
        abstract public function execute();
  
        /**
 -       * Constructor.
 -       *
 -       * @param $parent WebInstaller
 +       * @param WebInstaller $parent
         */
        public function __construct( WebInstaller $parent ) {
                $this->parent = $parent;
         * Is this a slow-running page in the installer? If so, WebInstaller will
         * set_time_limit(0) before calling execute(). Right now this only applies
         * to Install and Upgrade pages
 -       * @return bool
 +       *
 +       * @return bool Always false in this default implementation.
         */
        public function isSlow() {
                return false;
        }
  
 +      /**
 +       * @param string $html
 +       */
        public function addHTML( $html ) {
                $this->parent->output->addHTML( $html );
        }
                $this->addHTML( $s );
        }
  
 +      /**
 +       * @return string
 +       */
        public function getName() {
                return str_replace( 'WebInstaller_', '', get_class( $this ) );
        }
  
 +      /**
 +       * @return string
 +       */
        protected function getId() {
                return array_search( $this->getName(), $this->parent->pageSequence );
        }
  
 +      /**
 +       * @param string $var
 +       *
 +       * @return mixed
 +       */
        public function getVar( $var ) {
                return $this->parent->getVar( $var );
        }
  
 +      /**
 +       * @param string $name
 +       * @param mixed $value
 +       */
        public function setVar( $name, $value ) {
                $this->parent->setVar( $name, $value );
        }
        }
  
        /**
 -       * Opposite to startLiveBox()
 +       * Opposite to WebInstallerPage::startLiveBox
         */
        protected function endLiveBox() {
                $this->addHTML( '</textarea></div>
  <script>jQuery( "#config-spinner" ).hide()</script>' );
                $this->parent->output->flush();
        }
 +
  }
  
  class WebInstaller_Language extends WebInstallerPage {
 +
 +      /**
 +       * @return string|null
 +       */
        public function execute() {
                global $wgLang;
                $r = $this->parent->request;
                                $this->parent->getHelpBox( 'config-wiki-language-help' ) );
                $this->addHTML( $s );
                $this->endForm( 'continue', false );
 +
 +              return null;
        }
  
        /**
         * Get a "<select>" for selecting languages.
         *
 -       * @param $name
 -       * @param $label
 -       * @param $selectedCode
 -       * @param $helpHtml string
 +       * @param string $name
 +       * @param string $label
 +       * @param string $selectedCode
 +       * @param string $helpHtml
 +       *
         * @return string
         */
        public function getLanguageSelector( $name, $label, $selectedCode, $helpHtml = '' ) {
  
                return $this->parent->label( $label, $name, $s );
        }
 +
  }
  
  class WebInstaller_ExistingWiki extends WebInstallerPage {
 +
 +      /**
 +       * @return string
 +       */
        public function execute() {
                // If there is no LocalSettings.php, continue to the installer welcome page
                $vars = Installer::getExistingLocalSettings();
                $this->endForm( 'continue' );
        }
  
 +      /**
 +       * @param string[] $names
 +       * @param mixed[] $vars
 +       *
 +       * @return Status
 +       */
        protected function importVariables( $names, $vars ) {
                $status = Status::newGood();
                foreach ( $names as $name ) {
  
        /**
         * Initiate an upgrade of the existing database
 -       * @param array $vars Variables from LocalSettings.php
 +       *
 +       * @param mixed[] $vars Variables from LocalSettings.php
 +       *
         * @return Status
         */
        protected function handleExistingUpgrade( $vars ) {
  
                return $status;
        }
 +
  }
  
  class WebInstaller_Welcome extends WebInstallerPage {
  
 +      /**
 +       * @return string
 +       */
        public function execute() {
                if ( $this->parent->request->wasPosted() ) {
                        if ( $this->getVar( '_Environment' ) ) {
  
                return '';
        }
 +
  }
  
  class WebInstaller_DBConnect extends WebInstallerPage {
 +
        /**
 -       * @return string|void When string, "skip" or "continue"
 +       * @return string|null When string, "skip" or "continue"
         */
        public function execute() {
                if ( $this->getVar( '_ExistingDBSettings' ) ) {
  
                $this->addHTML( $this->parent->label( 'config-db-type', false, $types ) . $settings );
                $this->endForm();
 +
 +              return null;
        }
  
 +      /**
 +       * @return Status
 +       */
        public function submit() {
                $r = $this->parent->request;
                $type = $r->getVal( 'DBType' );
  
                return $installer->submitConnectForm();
        }
 +
  }
  
  class WebInstaller_Upgrade extends WebInstallerPage {
 +
 +      /**
 +       * @return bool Always true.
 +       */
        public function isSlow() {
                return true;
        }
  
 +      /**
 +       * @return string|null
 +       */
        public function execute() {
                if ( $this->getVar( '_UpgradeDone' ) ) {
                        // Allow regeneration of LocalSettings.php, unless we are working
                $this->addHTML( $this->parent->getInfoBox(
                        wfMessage( 'config-can-upgrade', $GLOBALS['wgVersion'] )->plain() ) );
                $this->endForm();
 +
 +              return null;
        }
  
        public function showDoneMessage() {
                $this->parent->restoreLinkPopups();
                $this->endForm( $regenerate ? 'regenerate' : false, false );
        }
 +
  }
  
  class WebInstaller_DBSettings extends WebInstallerPage {
  
 +      /**
 +       * @return string|null
 +       */
        public function execute() {
                $installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) );
  
                $this->startForm();
                $this->addHTML( $form );
                $this->endForm();
 +
 +              return null;
        }
 +
  }
  
  class WebInstaller_Name extends WebInstallerPage {
  
 +      /**
 +       * @return string
 +       */
        public function execute() {
                $r = $this->parent->request;
                if ( $r->wasPosted() ) {
                                'label' => 'config-admin-password',
                        ) ) .
                        $this->parent->getPasswordBox( array(
 -                              'var' => '_AdminPassword2',
 +                              'var' => '_AdminPasswordConfirm',
                                'label' => 'config-admin-password-confirm'
                        ) ) .
                        $this->parent->getTextBox( array(
                return 'output';
        }
  
 +      /**
 +       * @return bool
 +       */
        public function submit() {
                $retVal = true;
                $this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType',
 -                      '_AdminName', '_AdminPassword', '_AdminPassword2', '_AdminEmail',
 +                      '_AdminName', '_AdminPassword', '_AdminPasswordConfirm', '_AdminEmail',
                        '_Subscribe', '_SkipOptional', 'wgMetaNamespace' ) );
  
                // Validate site name
                        # $user->getPasswordValidity just checks for $wgMinimalPasswordLength.
                        # This message is more specific and helpful.
                        $msg = 'config-admin-password-blank';
 -              } elseif ( $pwd !== $this->getVar( '_AdminPassword2' ) ) {
 +              } elseif ( $pwd !== $this->getVar( '_AdminPasswordConfirm' ) ) {
                        $msg = 'config-admin-password-mismatch';
                } elseif ( $valid !== true ) {
                        $msg = $valid;
                if ( $msg !== false ) {
                        call_user_func_array( array( $this->parent, 'showError' ), (array)$msg );
                        $this->setVar( '_AdminPassword', '' );
 -                      $this->setVar( '_AdminPassword2', '' );
 +                      $this->setVar( '_AdminPasswordConfirm', '' );
                        $retVal = false;
                }
  
  
                return $retVal;
        }
 +
  }
  
  class WebInstaller_Options extends WebInstallerPage {
 +
 +      /**
 +       * @return string|null
 +       */
        public function execute() {
                if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
                        return 'skip';
                                $this->getVar( 'wgDeletedDirectory' )
                        )
                );
-               // If we're using the default, let the user set it relative to $wgScriptPath
-               $curLogo = $this->getVar( 'wgLogo' );
-               $logoString = ( $curLogo == "/wiki/skins/common/images/wiki.png" ) ?
-                       '$wgStylePath/common/images/wiki.png' : $curLogo;
  
                $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none';
                $this->addHTML(
                        '</div>' .
                        $this->parent->getTextBox( array(
                                'var' => 'wgLogo',
-                               'value' => $logoString,
                                'label' => 'config-logo',
                                'attribs' => array( 'dir' => 'ltr' ),
                                'help' => $this->parent->getHelpBox( 'config-logo-help' )
                        $this->getFieldSetEnd()
                );
                $this->endForm();
 +
 +              return null;
        }
  
        /**
                return $iframeUrl;
        }
  
 +      /**
 +       * @return string
 +       */
        public function getCCChooser() {
                $iframeAttribs = array(
                        'class' => 'config-cc-iframe',
                        "</div>\n";
        }
  
 +      /**
 +       * @return string
 +       */
        public function getCCDoneBox() {
                $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';";
                // If you change this height, also change it in config.css
                $this->addHTML( $this->getCCDoneBox() );
        }
  
 +      /**
 +       * @return bool
 +       */
        public function submit() {
                $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode',
                        'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo',
                        'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
                        'wgUseInstantCommons' ) );
  
 -              if ( !in_array( $this->getVar( '_RightsProfile' ),
 -                      array_keys( $this->parent->rightsProfiles ) )
 +              if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles )
                ) {
                        reset( $this->parent->rightsProfiles );
                        $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) );
  
                                return false;
                        }
 -              } elseif ( in_array( $code, array_keys( $this->parent->licenses ) ) ) {
 +              } elseif ( array_key_exists( $code, $this->parent->licenses ) ) {
                        // Messages:
                        // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
                        // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none,
  
                return true;
        }
 +
  }
  
  class WebInstaller_Install extends WebInstallerPage {
 +
 +      /**
 +       * @return bool Always true.
 +       */
        public function isSlow() {
                return true;
        }
  
 +      /**
 +       * @return string|bool
 +       */
        public function execute() {
                if ( $this->getVar( '_UpgradeDone' ) ) {
                        return 'skip';
                return true;
        }
  
 +      /**
 +       * @param string $step
 +       */
        public function startStage( $step ) {
                // Messages: config-install-database, config-install-tables, config-install-interwiki,
                // config-install-stats, config-install-keys, config-install-sysop, config-install-mainpage
        }
  
        /**
 -       * @param $step
 -       * @param $status Status
 +       * @param string $step
 +       * @param Status $status
         */
        public function endStage( $step, $status ) {
                if ( $step == 'extension-tables' ) {
                        $this->parent->showStatusBox( $status );
                }
        }
 +
  }
  
  class WebInstaller_Complete extends WebInstallerPage {
 +
        public function execute() {
                // Pop up a dialog box, to make it difficult for the user to forget
                // to download the file
                $this->parent->restoreLinkPopups();
                $this->endForm( false, false );
        }
 +
  }
  
  class WebInstaller_Restart extends WebInstallerPage {
  
 +      /**
 +       * @return string|null
 +       */
        public function execute() {
                $r = $this->parent->request;
                if ( $r->wasPosted() ) {
                $s = $this->parent->getWarningBox( wfMessage( 'config-help-restart' )->plain() );
                $this->addHTML( $s );
                $this->endForm( 'restart' );
 +
 +              return null;
        }
 +
  }
  
  abstract class WebInstaller_Document extends WebInstallerPage {
  
 +      /**
 +       * @return string
 +       */
        abstract protected function getFileName();
  
        public function execute() {
                $this->endForm( false );
        }
  
 +      /**
 +       * @return string
 +       */
        public function getFileContents() {
                $file = __DIR__ . '/../../' . $this->getFileName();
                if ( !file_exists( $file ) ) {
  
                return file_get_contents( $file );
        }
 +
  }
  
  class WebInstaller_Readme extends WebInstaller_Document {
 +
 +      /**
 +       * @return string
 +       */
        protected function getFileName() {
                return 'README';
        }
 +
  }
  
  class WebInstaller_ReleaseNotes extends WebInstaller_Document {
 +
 +      /**
 +       * @throws MWException
 +       * @return string
 +       */
        protected function getFileName() {
                global $wgVersion;
  
  
                return 'RELEASE-NOTES-' . $result[1] . '.' . $result[2];
        }
 +
  }
  
  class WebInstaller_UpgradeDoc extends WebInstaller_Document {
 +
 +      /**
 +       * @return string
 +       */
        protected function getFileName() {
                return 'UPGRADE';
        }
 +
  }
  
  class WebInstaller_Copying extends WebInstaller_Document {
 +
 +      /**
 +       * @return string
 +       */
        protected function getFileName() {
                return 'COPYING';
        }
 +
  }