Merge "Make runJobs.php treat --json value as case insensitive"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 25 Oct 2017 15:28:07 +0000 (15:28 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 25 Oct 2017 15:28:08 +0000 (15:28 +0000)
18 files changed:
RELEASE-NOTES-1.30
includes/NoLocalSettings.php
includes/PreConfigSetup.php [deleted file]
includes/Setup.php
includes/WebStart.php
includes/api/ApiParse.php
includes/api/ApiPurge.php
includes/deferred/DataUpdate.php
includes/deferred/LinksUpdate.php
includes/filerepo/file/LocalFile.php
includes/installer/i18n/tokipona.json [deleted file]
includes/jobqueue/jobs/RefreshLinksJob.php
includes/page/WikiPage.php
languages/data/Names.php
languages/i18n/tokipona.json [deleted file]
maintenance/doMaintenance.php
tests/phpunit/includes/api/ApiParseTest.php
tests/phpunit/languages/LanguageTest.php

index bcdd436..f79ae83 100644 (file)
@@ -124,6 +124,7 @@ changes to languages because of Phabricator reports.
 * Added: kbp (Kabɩyɛ / Kabiyè)
 * Added: skr (Saraiki, سرائیکی)
 * Added: tay (Tayal / Atayal)
+* Removed: tokipona (Toki Pona)
 
 ==== Pig Latin added ====
 * (T45547) Added Pig Latin, a made-up English variant (en-x-piglatin),
index 50950ef..b8bfd6a 100644 (file)
@@ -50,6 +50,7 @@ $templateParser = new TemplateParser();
 
 # Render error page if no LocalSettings file can be found
 try {
+       global $wgVersion;
        echo $templateParser->processTemplate(
                'NoLocalSettings',
                [
diff --git a/includes/PreConfigSetup.php b/includes/PreConfigSetup.php
deleted file mode 100644 (file)
index bda7886..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/**
- * File-scope setup actions, loaded before LocalSettings.php, shared by
- * WebStart.php and doMaintenance.php
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- *
- * @file
- */
-
-if ( !defined( 'MEDIAWIKI' ) ) {
-       // Not an entry point
-       exit( 1 );
-}
-
-// Grab profiling functions
-require_once "$IP/includes/profiler/ProfilerFunctions.php";
-
-// Start the autoloader, so that extensions can derive classes from core files
-require_once "$IP/includes/AutoLoader.php";
-
-// Load up some global defines.
-require_once "$IP/includes/Defines.php";
-
-// Start the profiler
-$wgProfiler = [];
-if ( file_exists( "$IP/StartProfiler.php" ) ) {
-       require "$IP/StartProfiler.php";
-}
-
-// Load default settings
-require_once "$IP/includes/DefaultSettings.php";
-
-// Load global functions
-require_once "$IP/includes/GlobalFunctions.php";
-
-// Load composer's autoloader if present
-if ( is_readable( "$IP/vendor/autoload.php" ) ) {
-       require_once "$IP/vendor/autoload.php";
-}
index d4612dd..e4396ba 100644 (file)
@@ -33,6 +33,85 @@ if ( !defined( 'MEDIAWIKI' ) ) {
        exit( 1 );
 }
 
+/**
+ * Pre-config setup: Before loading LocalSettings.php
+ */
+
+// Grab profiling functions
+require_once "$IP/includes/profiler/ProfilerFunctions.php";
+
+// Start the autoloader, so that extensions can derive classes from core files
+require_once "$IP/includes/AutoLoader.php";
+
+// Load up some global defines
+require_once "$IP/includes/Defines.php";
+
+// Start the profiler
+$wgProfiler = [];
+if ( file_exists( "$IP/StartProfiler.php" ) ) {
+       require "$IP/StartProfiler.php";
+}
+
+// Load default settings
+require_once "$IP/includes/DefaultSettings.php";
+
+// Load global functions
+require_once "$IP/includes/GlobalFunctions.php";
+
+// Load composer's autoloader if present
+if ( is_readable( "$IP/vendor/autoload.php" ) ) {
+       require_once "$IP/vendor/autoload.php";
+}
+
+// Assert that composer dependencies were successfully loaded
+// Purposely no leading \ due to it breaking HHVM RepoAuthorative mode
+// PHP works fine with both versions
+// See https://github.com/facebook/hhvm/issues/5833
+if ( !interface_exists( 'Psr\Log\LoggerInterface' ) ) {
+       $message = (
+               'MediaWiki requires the <a href="https://github.com/php-fig/log">PSR-3 logging ' .
+               "library</a> to be present. This library is not embedded directly in MediaWiki's " .
+               "git repository and must be installed separately by the end user.\n\n" .
+               'Please see <a href="https://www.mediawiki.org/wiki/Download_from_Git' .
+               '#Fetch_external_libraries">mediawiki.org</a> for help on installing ' .
+               'the required components.'
+       );
+       echo $message;
+       trigger_error( $message, E_USER_ERROR );
+       die( 1 );
+}
+
+// Install a header callback
+MediaWiki\HeaderCallback::register();
+
+/**
+ * Load LocalSettings.php
+ */
+
+if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
+       call_user_func( MW_CONFIG_CALLBACK );
+} else {
+       if ( !defined( 'MW_CONFIG_FILE' ) ) {
+               define( 'MW_CONFIG_FILE', "$IP/LocalSettings.php" );
+       }
+       require_once MW_CONFIG_FILE;
+}
+
+/**
+ * Customization point after all loading (constants, functions, classes,
+ * DefaultSettings, LocalSettings). Specifically, this is before usage of
+ * settings, before instantiation of Profiler (and other singletons), and
+ * before any setup functions or hooks run.
+ */
+
+if ( defined( 'MW_SETUP_CALLBACK' ) ) {
+       call_user_func( MW_SETUP_CALLBACK );
+}
+
+/**
+ * Main setup
+ */
+
 $fname = 'Setup.php';
 $ps_setup = Profiler::instance()->scopedProfileIn( $fname );
 
index 8a58e6f..e4d93f9 100644 (file)
@@ -59,56 +59,39 @@ if ( $IP === false ) {
        $IP = realpath( '.' ) ?: dirname( __DIR__ );
 }
 
-require_once "$IP/includes/PreConfigSetup.php";
-
-# Assert that composer dependencies were successfully loaded
-# Purposely no leading \ due to it breaking HHVM RepoAuthorative mode
-# PHP works fine with both versions
-# See https://github.com/facebook/hhvm/issues/5833
-if ( !interface_exists( 'Psr\Log\LoggerInterface' ) ) {
-       $message = (
-               'MediaWiki requires the <a href="https://github.com/php-fig/log">PSR-3 logging ' .
-               "library</a> to be present. This library is not embedded directly in MediaWiki's " .
-               "git repository and must be installed separately by the end user.\n\n" .
-               'Please see <a href="https://www.mediawiki.org/wiki/Download_from_Git' .
-               '#Fetch_external_libraries">mediawiki.org</a> for help on installing ' .
-               'the required components.'
-       );
-       echo $message;
-       trigger_error( $message, E_USER_ERROR );
-       die( 1 );
-}
-
-# Install a header callback
-MediaWiki\HeaderCallback::register();
-
-if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
-       # Use a callback function to configure MediaWiki
-       call_user_func( MW_CONFIG_CALLBACK );
-} else {
+// If no LocalSettings file exists, try to display an error page
+// (use a callback because it depends on TemplateParser)
+if ( !defined( 'MW_CONFIG_CALLBACK' ) ) {
        if ( !defined( 'MW_CONFIG_FILE' ) ) {
                define( 'MW_CONFIG_FILE', "$IP/LocalSettings.php" );
        }
-
-       # LocalSettings.php is the per site customization file. If it does not exist
-       # the wiki installer needs to be launched or the generated file uploaded to
-       # the root wiki directory. Give a hint, if it is not readable by the server.
        if ( !is_readable( MW_CONFIG_FILE ) ) {
-               require_once "$IP/includes/NoLocalSettings.php";
-               die();
+               function wfWebStartNoLocalSettings() {
+                       # LocalSettings.php is the per-site customization file. If it does not exist
+                       # the wiki installer needs to be launched or the generated file uploaded to
+                       # the root wiki directory. Give a hint, if it is not readable by the server.
+                       global $IP;
+                       require_once "$IP/includes/NoLocalSettings.php";
+                       die();
+               }
+               define( 'MW_CONFIG_CALLBACK', 'wfWebStartNoLocalSettings' );
        }
-
-       # Include site settings. $IP may be changed (hopefully before the AutoLoader is invoked)
-       require_once MW_CONFIG_FILE;
 }
 
-# Initialise output buffering
-# Check that there is no previous output or previously set up buffers, because
-# that would cause us to potentially mix gzip and non-gzip output, creating a
-# big mess.
-if ( ob_get_level() == 0 ) {
-       require_once "$IP/includes/OutputHandler.php";
-       ob_start( 'wfOutputHandler' );
+// Custom setup for WebStart entry point
+if ( !defined( 'MW_SETUP_CALLBACK' ) ) {
+       function wfWebStartSetup() {
+               # Initialise output buffering
+               # Check that there is no previous output or previously set up buffers, because
+               # that would cause us to potentially mix gzip and non-gzip output, creating a
+               # big mess.
+               global $IP;
+               if ( ob_get_level() == 0 ) {
+                       require_once "$IP/includes/OutputHandler.php";
+                       ob_start( 'wfOutputHandler' );
+               }
+       }
+       define( 'MW_SETUP_CALLBACK', 'wfWebStartSetup' );
 }
 
 require_once "$IP/includes/Setup.php";
index 7cbd353..15b94fb 100644 (file)
@@ -329,6 +329,8 @@ class ApiParse extends ApiBase {
                        $context->setOutput( $outputPage );
 
                        if ( $skin ) {
+                               // Based on OutputPage::headElement()
+                               $skin->setupSkinUserCss( $outputPage );
                                // Based on OutputPage::output()
                                foreach ( $skin->getDefaultModules() as $group ) {
                                        $outputPage->addModules( $group );
index 35f93e0..4b8ce7f 100644 (file)
@@ -93,6 +93,7 @@ class ApiPurge extends ApiBase {
                                                $updates = $content->getSecondaryDataUpdates(
                                                        $title, null, $forceRecursiveLinkUpdate, $p_result );
                                                foreach ( $updates as $update ) {
+                                                       $update->setCause( 'api-purge', $this->getUser()->getName() );
                                                        DeferredUpdates::addUpdate( $update, DeferredUpdates::PRESEND );
                                                }
 
index d2d8bd7..ed9a746 100644 (file)
 abstract class DataUpdate implements DeferrableUpdate {
        /** @var mixed Result from LBFactory::getEmptyTransactionTicket() */
        protected $ticket;
+       /** @var string Short update cause action description */
+       protected $causeAction = 'unknown';
+       /** @var string Short update cause user description */
+       protected $causeAgent = 'unknown';
 
        public function __construct() {
                // noop
@@ -41,6 +45,29 @@ abstract class DataUpdate implements DeferrableUpdate {
                $this->ticket = $ticket;
        }
 
+       /**
+        * @param string $action Action type
+        * @param string $user User name
+        */
+       public function setCause( $action, $user ) {
+               $this->causeAction = $action;
+               $this->causeAgent = $user;
+       }
+
+       /**
+        * @return string
+        */
+       public function getCauseAction() {
+               return $this->causeAction;
+       }
+
+       /**
+        * @return string
+        */
+       public function getCauseAgent() {
+               return $this->causeAgent;
+       }
+
        /**
         * Convenience method, calls doUpdate() on every DataUpdate in the array.
         *
index dfe89ba..c27826d 100644 (file)
@@ -306,10 +306,13 @@ class LinksUpdate extends DataUpdate implements EnqueueableDataUpdate {
         * using the job queue.
         */
        protected function queueRecursiveJobs() {
-               self::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks' );
+               $action = $this->getCauseAction();
+               $agent = $this->getCauseAgent();
+
+               self::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks', $action, $agent );
                if ( $this->mTitle->getNamespace() == NS_FILE ) {
                        // Process imagelinks in case the title is or was a redirect
-                       self::queueRecursiveJobsForTable( $this->mTitle, 'imagelinks' );
+                       self::queueRecursiveJobsForTable( $this->mTitle, 'imagelinks', $action, $agent );
                }
 
                $bc = $this->mTitle->getBacklinkCache();
@@ -320,7 +323,13 @@ class LinksUpdate extends DataUpdate implements EnqueueableDataUpdate {
                // Which ever runs first generally no-ops the other one.
                $jobs = [];
                foreach ( $bc->getCascadeProtectedLinks() as $title ) {
-                       $jobs[] = RefreshLinksJob::newPrioritized( $title, [] );
+                       $jobs[] = RefreshLinksJob::newPrioritized(
+                               $title,
+                               [
+                                       'causeAction' => $action,
+                                       'causeAgent' => $agent
+                               ]
+                       );
                }
                JobQueueGroup::singleton()->push( $jobs );
        }
@@ -330,8 +339,12 @@ class LinksUpdate extends DataUpdate implements EnqueueableDataUpdate {
         *
         * @param Title $title Title to do job for
         * @param string $table Table to use (e.g. 'templatelinks')
+        * @param string $action Triggering action
+        * @param string $userName Triggering user name
         */
-       public static function queueRecursiveJobsForTable( Title $title, $table ) {
+       public static function queueRecursiveJobsForTable(
+               Title $title, $table, $action = 'unknown', $userName = 'unknown'
+       ) {
                if ( $title->getBacklinkCache()->hasLinks( $table ) ) {
                        $job = new RefreshLinksJob(
                                $title,
@@ -340,7 +353,7 @@ class LinksUpdate extends DataUpdate implements EnqueueableDataUpdate {
                                        'recursive' => true,
                                ] + Job::newRootJobParams( // "overall" refresh links job info
                                        "refreshlinks:{$table}:{$title->getPrefixedText()}"
-                               )
+                               ) + [ 'causeAction' => $action, 'causeAgent' => $userName ]
                        );
 
                        JobQueueGroup::singleton()->push( $job );
@@ -1156,6 +1169,8 @@ class LinksUpdate extends DataUpdate implements EnqueueableDataUpdate {
                                        'useRecursiveLinksUpdate' => $this->mRecursive,
                                        'triggeringUser' => $userInfo,
                                        'triggeringRevisionId' => $triggeringRevisionId,
+                                       'causeAction' => $this->getCauseAction(),
+                                       'causeAgent' => $this->getCauseAgent()
                                ],
                                [ 'removeDuplicates' => true ],
                                $this->getTitle()
index a36bec3..3271c96 100644 (file)
@@ -1646,7 +1646,12 @@ class LocalFile extends File {
                                                );
                                        } else {
                                                # Update backlink pages pointing to this title if created
-                                               LinksUpdate::queueRecursiveJobsForTable( $this->getTitle(), 'imagelinks' );
+                                               LinksUpdate::queueRecursiveJobsForTable(
+                                                       $this->getTitle(),
+                                                       'imagelinks',
+                                                       'upload-image',
+                                                       $user->getName()
+                                               );
                                        }
 
                                        $this->prerenderThumbnails();
diff --git a/includes/installer/i18n/tokipona.json b/includes/installer/i18n/tokipona.json
deleted file mode 100644 (file)
index 348380f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Robin0van0der0vliet"
-               ]
-       },
-       "config-page-language": "toki"
-}
index 51e964d..8854c65 100644 (file)
@@ -53,6 +53,7 @@ class RefreshLinksJob extends Job {
                        // Multiple pages per job make matches unlikely
                        !( isset( $params['pages'] ) && count( $params['pages'] ) != 1 )
                );
+               $this->params += [ 'causeAction' => 'unknown', 'causeAgent' => 'unknown' ];
        }
 
        /**
@@ -102,6 +103,9 @@ class RefreshLinksJob extends Job {
                        // Carry over information for de-duplication
                        $extraParams = $this->getRootJobParams();
                        $extraParams['triggeredRecursive'] = true;
+                       // Carry over cause information for logging
+                       $extraParams['causeAction'] = $this->params['causeAction'];
+                       $extraParams['causeAgent'] = $this->params['causeAgent'];
                        // Convert this into no more than $wgUpdateRowsPerJob RefreshLinks per-title
                        // jobs and possibly a recursive RefreshLinks job for the rest of the backlinks
                        $jobs = BacklinkJobUtils::partitionBacklinkJob(
@@ -254,6 +258,8 @@ class RefreshLinksJob extends Job {
                $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket );
 
                foreach ( $updates as $update ) {
+                       // Carry over cause in case so the update can do extra logging
+                       $update->setCause( $this->params['causeAction'], $this->params['causeAgent'] );
                        // FIXME: This code probably shouldn't be here?
                        // Needed by things like Echo notifications which need
                        // to know which user caused the links update
@@ -288,6 +294,8 @@ class RefreshLinksJob extends Job {
 
        public function getDeduplicationInfo() {
                $info = parent::getDeduplicationInfo();
+               unset( $info['causeAction'] );
+               unset( $info['causeAgent'] );
                if ( is_array( $info['params'] ) ) {
                        // For per-pages jobs, the job title is that of the template that changed
                        // (or similar), so remove that since it ruins duplicate detection
index d0a04c0..e875df5 100644 (file)
@@ -2171,6 +2171,7 @@ class WikiPage implements Page, IDBAccessObject {
                                $this->getTitle(), null, $recursive, $editInfo->output
                        );
                        foreach ( $updates as $update ) {
+                               $update->setCause( 'edit-page', $user->getName() );
                                if ( $update instanceof LinksUpdate ) {
                                        $update->setRevision( $revision );
                                        $update->setTriggeringUser( $user );
@@ -2913,7 +2914,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                $dbw->endAtomic( __METHOD__ );
 
-               $this->doDeleteUpdates( $id, $content, $revision );
+               $this->doDeleteUpdates( $id, $content, $revision, $user );
 
                Hooks::run( 'ArticleDeleteComplete', [
                        &$wikiPageBeforeDelete,
@@ -2964,8 +2965,11 @@ class WikiPage implements Page, IDBAccessObject {
         *   the required updates. This may be needed because $this->getContent()
         *   may already return null when the page proper was deleted.
         * @param Revision|null $revision The latest page revision
+        * @param User|null $user The user that caused the deletion
         */
-       public function doDeleteUpdates( $id, Content $content = null, Revision $revision = null ) {
+       public function doDeleteUpdates(
+               $id, Content $content = null, Revision $revision = null, User $user = null
+       ) {
                try {
                        $countable = $this->isCountable();
                } catch ( Exception $ex ) {
@@ -2983,12 +2987,14 @@ class WikiPage implements Page, IDBAccessObject {
                        DeferredUpdates::addUpdate( $update );
                }
 
+               $causeAgent = $user ? $user->getName() : 'unknown';
                // Reparse any pages transcluding this page
-               LinksUpdate::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks' );
-
+               LinksUpdate::queueRecursiveJobsForTable(
+                       $this->mTitle, 'templatelinks', 'delete-page', $causeAgent );
                // Reparse any pages including this image
                if ( $this->mTitle->getNamespace() == NS_FILE ) {
-                       LinksUpdate::queueRecursiveJobsForTable( $this->mTitle, 'imagelinks' );
+                       LinksUpdate::queueRecursiveJobsForTable(
+                               $this->mTitle, 'imagelinks', 'delete-page', $causeAgent );
                }
 
                // Clear caches
index 1266561..281be2b 100644 (file)
@@ -418,7 +418,6 @@ class Names {
                'tly' => 'толышә зывон', # Talysh
                'tn' => 'Setswana', # Setswana
                'to' => 'lea faka-Tonga', # Tonga (Tonga Islands)
-               'tokipona' => 'Toki Pona', # Toki Pona
                'tpi' => 'Tok Pisin', # Tok Pisin
                'tr' => 'Türkçe', # Turkish
                'tru' => 'Ṫuroyo', # Turoyo
diff --git a/languages/i18n/tokipona.json b/languages/i18n/tokipona.json
deleted file mode 100644 (file)
index 67f4b5f..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "http://tokipona.wikia.com sysops"
-               ]
-       },
-       "january": "tenpo mun pi nanpa wan",
-       "february": "tenpo mun pi nanpa tu",
-       "march": "tenpo mun pi nanpa tu wan",
-       "april": "tenpo mun pi nanpa tu tu",
-       "may_long": "tenpo mun pi nanpa luka",
-       "june": "tenpo mun pi nanpa luka wan",
-       "july": "tenpo mun pi nanpa luka tu",
-       "august": "tenpo mun pi nanpa luka tu wan",
-       "september": "tenpo mun pi nanpa luka tu tu",
-       "october": "tenpo mun pi nanpa luka luka",
-       "november": "tenpo mun pi nanpa luka luka wan",
-       "december": "tenpo mun pi nanpa luka luka tu",
-       "category_header": "lipu lon kulupu lipu \"$1\"",
-       "subcategories": "kulupu lipu lili",
-       "listingcontinuesabbrev": " li awen",
-       "article": "lipu sona",
-       "newwindow": "(ona li open e lupa sin)",
-       "cancel": "ike",
-       "mytalk": "toki mi",
-       "navigation": "lipu suli",
-       "help": "mi sona ala",
-       "search": "o lukin jo",
-       "go": "o tawa",
-       "history": "o lukin e lipu ni pi tenpo pini",
-       "history_short": "lipu ni pi tenpo pini",
-       "printableversion": "lipu ni o kama lipu len",
-       "permalink": "nimi open kiwen",
-       "edit": "o ante",
-       "editthispage": "o ante e lipu ni",
-       "delete": "o weka",
-       "deletethispage": "o weka e lipu ni",
-       "protect": "mi taso o ken ante",
-       "protectthispage": "mi taso o ken ante e lipu ni",
-       "unprotect": "jan ali o ken ante",
-       "unprotectthispage": "jan ale o ken ante e lipu ni",
-       "talkpage": "Talk page",
-       "specialpage": "lipu suli",
-       "talk": "o toki",
-       "toolbox": "ilo",
-       "otherlanguages": "toki ante",
-       "redirectedfrom": "(tan $1)",
-       "aboutsite": "lipu sona pi toki pona li seme?",
-       "aboutpage": "Project:lipu sona pi toki pona li seme?",
-       "copyright": "lipu ken $1 li lawa e lipu ni.",
-       "currentevents": "seme li sin lon ma?",
-       "disclaimers": "wile ala",
-       "edithelp": "mi sona ala e ante",
-       "mainpage": "lipu lawa",
-       "mainpage-description": "lipu lawa",
-       "portal": "lipu pi kulupu ni",
-       "privacy": "ken pi awen weka",
-       "ok": "pona",
-       "retrievedfrom": "tan $1",
-       "editsection": "o ante",
-       "toc": "poki lawa",
-       "showtoc": "o suli e poki ni.",
-       "hidetoc": "o lili e poki ni",
-       "nstab-main": "lipu sona",
-       "nstab-user": "lipu jan",
-       "nstab-special": "suli",
-       "nstab-image": "lipu nanpa",
-       "nstab-mediawiki": "nimi",
-       "nstab-template": "lipu mama",
-       "nstab-help": "pana pona",
-       "nstab-category": "kulupu lipu",
-       "logout": "mi o tawa",
-       "userlogout": "mi o tawa",
-       "summary": "ante li seme:",
-       "minoredit": "ante ni li lili taso",
-       "watchthis": "mi wile sona e ante ale pi lipu ni lon tenpo kama",
-       "savearticle": "o awen",
-       "preview": "lukin taso",
-       "showpreview": "mi wile lukin taso e ante",
-       "editing": "mi ante e: $1",
-       "editingcomment": "mi ante e lipu $1 (wan sin)",
-       "copyrightwarning": "o sona e ni: ken $2 (o lukin e $1) li lawa tawa ante ali lon {{SITENAME}} li. jan li ken ante e toki sina li ken pana e ona tawa jan ante. sina wile ala e ni la, o sitelen ala lon lipu ni.<br />\nkin la sina toki e ni: toki sina ni li tan sina taso anu lipu pi ken ali.\n'''SINA KEN ALA LA, O PANA ALA E TOKI PI KEN LILI TAWA LIPU NI!'''",
-       "templatesused": "{{PLURAL:$1|Template|Templates}} used on this page:",
-       "histfirst": "pini taso",
-       "histlast": "sin taso",
-       "prevn": "nanpa {{PLURAL:$1|$1}} pini",
-       "nextn": "nanpa {{PLURAL:$1|$1}} kama",
-       "viewprevnext": "o lukin e ($1 {{int:pipe-separator}} $2) ($3).",
-       "preferences": "seme li pona tawa mi",
-       "recentchanges": "lipu seme li ante?",
-       "minoreditletter": "ante lili",
-       "newpageletter": "lipu sin",
-       "recentchangeslinked": "ante sama",
-       "recentchangeslinked-feed": "ante sama",
-       "recentchangeslinked-toolbox": "ante sama",
-       "upload": "o pana e lipu nanpa",
-       "filedesc": "ante li seme",
-       "fileuploadsummary": "ante li seme:",
-       "file-anchor-link": "Lipu nanpa",
-       "randompage": "mi wile lukin e lipu ante",
-       "lonelypages": "lipu ni li jo ala e lipu sama",
-       "move": "o tawa",
-       "movethispage": "o pana e nimi sin",
-       "allpages": "lipu ale",
-       "categories": "kulupu lipu",
-       "watchlist": "mi sona e ante pi lipu seme",
-       "watch": "o sona e ante",
-       "watchthispage": "mi wile sona e ante ale pi lipu ni lon tenpo kama",
-       "unwatchthispage": "mi wile ala sona e ante ale pi lipu ni lon tenpo kama",
-       "mycontris": "mi ante e lipu seme",
-       "whatlinkshere": "lipu seme li tawa ni?",
-       "specialpages": "lipu suli"
-}
index e87e024..b5beef6 100644 (file)
@@ -55,27 +55,30 @@ $maintenance->setup();
 // to $maintenance->mSelf. Keep that here for b/c
 $self = $maintenance->getName();
 
-require_once "$IP/includes/PreConfigSetup.php";
-
-if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
-       # Use a callback function to configure MediaWiki
-       call_user_func( MW_CONFIG_CALLBACK );
-} else {
-       // Require the configuration (probably LocalSettings.php)
-       require $maintenance->loadSettings();
+// Define how settings are loaded (e.g. LocalSettings.php)
+if ( !defined( 'MW_CONFIG_CALLBACK' ) && !defined( 'MW_CONFIG_FILE' ) ) {
+       define( 'MW_CONFIG_FILE', $maintenance->loadSettings() );
 }
 
-if ( $maintenance->getDbType() === Maintenance::DB_NONE ) {
-       if ( $wgLocalisationCacheConf['storeClass'] === false
-               && ( $wgLocalisationCacheConf['store'] == 'db'
-                       || ( $wgLocalisationCacheConf['store'] == 'detect' && !$wgCacheDirectory ) )
-       ) {
-               $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
+// Custom setup for Maintenance entry point
+if ( !defined( 'MW_SETUP_CALLBACK' ) ) {
+       function wfMaintenanceSetup() {
+               // @codingStandardsIgnoreLine MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
+               global $maintenance, $wgLocalisationCacheConf, $wgCacheDirectory;
+               if ( $maintenance->getDbType() === Maintenance::DB_NONE ) {
+                       if ( $wgLocalisationCacheConf['storeClass'] === false
+                               && ( $wgLocalisationCacheConf['store'] == 'db'
+                                       || ( $wgLocalisationCacheConf['store'] == 'detect' && !$wgCacheDirectory ) )
+                       ) {
+                               $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
+                       }
+               }
+
+               $maintenance->finalSetup();
        }
+       define( 'MW_SETUP_CALLBACK', 'wfMaintenanceSetup' );
 }
 
-$maintenance->finalSetup();
-// Some last includes
 require_once "$IP/includes/Setup.php";
 
 // Initialize main config instance
index 028d3b4..07bf299 100644 (file)
@@ -129,4 +129,46 @@ class ApiParseTest extends ApiTestCase {
                        );
                }
        }
+
+       public function testSkinModules() {
+               $factory = new SkinFactory();
+               $factory->register( 'testing', 'Testing', function () {
+                       $skin = $this->getMockBuilder( SkinFallback::class )
+                               ->setMethods( [ 'getDefaultModules', 'setupSkinUserCss' ] )
+                               ->getMock();
+                       $skin->expects( $this->once() )->method( 'getDefaultModules' )
+                               ->willReturn( [
+                                       'core' => [ 'foo', 'bar' ],
+                                       'content' => [ 'baz' ]
+                               ] );
+                       $skin->expects( $this->once() )->method( 'setupSkinUserCss' )
+                               ->will( $this->returnCallback( function ( OutputPage $out ) {
+                                       $out->addModuleStyles( 'foo.styles' );
+                               } ) );
+                       return $skin;
+               } );
+               $this->setService( 'SkinFactory', $factory );
+
+               $res = $this->doApiRequest( [
+                       'action' => 'parse',
+                       'pageid' => self::$pageId,
+                       'useskin' => 'testing',
+                       'prop' => 'modules',
+               ] );
+               $this->assertSame(
+                       [ 'foo', 'bar', 'baz' ],
+                       $res[0]['parse']['modules'],
+                       'resp.parse.modules'
+               );
+               $this->assertSame(
+                       [],
+                       $res[0]['parse']['modulescripts'],
+                       'resp.parse.modulescripts'
+               );
+               $this->assertSame(
+                       [ 'foo.styles' ],
+                       $res[0]['parse']['modulestyles'],
+                       'resp.parse.modulestyles'
+               );
+       }
 }
index a474f20..cd52366 100644 (file)
@@ -479,7 +479,6 @@ class LanguageTest extends LanguageClassesTestCase {
                        [ 'fr', true, 'Two letters, minor case' ],
                        [ 'EN', false, 'Two letters, upper case' ],
                        [ 'tyv', true, 'Three letters' ],
-                       [ 'tokipona', true, 'long language code' ],
                        [ 'be-tarask', true, 'With dash' ],
                        [ 'be-x-old', true, 'With extension (two dashes)' ],
                        [ 'be_tarask', false, 'Reject underscores' ],