Merge "registration: Have cache entries expire after 24 hours"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 19 May 2015 15:23:54 +0000 (15:23 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 19 May 2015 15:23:54 +0000 (15:23 +0000)
RELEASE-NOTES-1.26
includes/DefaultSettings.php
includes/htmlform/HTMLForm.php
includes/objectcache/ObjectCache.php
includes/registration/ExtensionProcessor.php
includes/registration/ExtensionRegistry.php
languages/Names.php
languages/messages/MessagesBh.php [new file with mode: 0644]
tests/phpunit/includes/registration/ExtensionProcessorTest.php

index 61e04b8..6f1120e 100644 (file)
@@ -37,9 +37,6 @@ MediaWiki supports over 350 languages. Many localisations are updated
 regularly. Below only new and removed languages are listed, as well as
 changes to languages because of Bugzilla reports.
 
-* BREAKING CHANGE (T91240): Language code "bh" is not valid in ISO 639 and
-  was removed, so it will no longer alias to "bho". If you used "bh" as your
-  wiki's $wgLanguageCode, you must update your configuration.
 
 === Other changes in 1.26 ===
 * ChangeTags::tagDescription() will return false if the interface message
index 857d69e..2ea8b29 100644 (file)
@@ -2160,7 +2160,7 @@ $wgObjectCaches = array(
 );
 
 /**
- * Main cache Wide-Area-Network cache type. This should be a cache with fast access,
+ * Main Wide-Area-Network cache type. This should be a cache with fast access,
  * but it may have limited space. By default, it is disabled, since the basic stock
  * cache is not fast enough to make it worthwhile. For single data-center setups, this can
  * simply be pointed to a cache in $wgWANObjectCaches that uses a local $wgObjectCaches
@@ -2171,7 +2171,8 @@ $wgObjectCaches = array(
  *                       a relayer (only matters if there are multiple data-centers)
  *   - CACHE_NONE:       Do not cache
  *   - (other):          A string may be used which identifies a cache
- *                       configuration in $wgWANObjectCaches.
+ *                       configuration in $wgWANObjectCaches
+ * @since 1.26
  */
 $wgMainWANCache = false;
 
@@ -2187,6 +2188,8 @@ $wgMainWANCache = false;
  * a cache identifier from $wgObjectCaches. The "relayerConfig" parameter is an
  * array used to construct an EventRelayer object. The "pool" parameter is a
  * string that is used as a PubSub channel prefix.
+ *
+ * @since 1.26
  */
 $wgWANObjectCaches = array(
        CACHE_NONE => array(
@@ -2205,6 +2208,21 @@ $wgWANObjectCaches = array(
        */
 );
 
+/**
+ * Main object stash type. This should be a fast storage system for storing
+ * lightweight data like hit counters and user activity. Sites with multiple
+ * data-centers should have this use a store that replicates all writes. The
+ * store should have enough consistency for CAS operations to be usable.
+ *
+ * The options are:
+ *   - db:      Store cache objects in the DB
+ *   - (other): A string may be used which identifies a cache
+ *              configuration in $wgObjectCaches
+ *
+ * @since 1.26
+ */
+$wgMainStash = 'db';
+
 /**
  * The expiry time for the parser cache, in seconds.
  * The default is 86400 (one day).
index 738fec3..bef4dc0 100644 (file)
  *                             is "wp{$fieldname}".  If you want a different name
  *                             (eg one without the "wp" prefix), specify it here and
  *                             it will be used without modification.
+ *    'hide-if'             -- expression given as an array stating when the field
+ *                             should be hidden. The first array value has to be the
+ *                             expression's logic operator. Supported expressions:
+ *                               'NOT'
+ *                                 [ 'NOT', array $expression ]
+ *                                 To hide a field if a given expression is not true.
+ *                               '==='
+ *                                 [ '===', string $fieldName, string $value ]
+ *                                 To hide a field if another field identified by
+ *                                 $field has the value $value.
+ *                               '!=='
+ *                                 [ '!==', string $fieldName, string $value ]
+ *                                 Same as [ 'NOT', [ '===', $fieldName, $value ]
+ *                               'OR', 'AND', 'NOR', 'NAND'
+ *                                 [ 'XXX', array $expression1, ..., array $expressionN ]
+ *                                 To hide a field if one or more (OR), all (AND),
+ *                                 neither (NOR) or not all (NAND) given expressions
+ *                                 are evaluated as true.
+ *                             The expressions will be given to a JavaScript frontend
+ *                             module which will continually update the field's
+ *                             visibility.
  *
  * Since 1.20, you can chain mutators to ease the form generation:
  * @par Example:
index 5da22f0..7faf4bb 100644 (file)
@@ -26,6 +26,13 @@ use MediaWiki\Logger\LoggerFactory;
 /**
  * Functions to get cache objects
  *
+ * The word "cache" has two main dictionary meanings, and both
+ * are used in this factory class. They are:
+ *   - a) A place to store copies or computations on existing data
+ *     for higher access speeds (the computer science definition)
+ *   - b) A place to store lightweight data that is not canonically
+ *     stored anywhere else (e.g. a "hoard" of objects)
+ *
  * @ingroup Cache
  */
 class ObjectCache {
@@ -227,4 +234,26 @@ class ObjectCache {
 
                return self::getWANInstance( $wgMainWANCache );
        }
+
+       /**
+        * Stash objects are BagOStuff instances suitable for storing light
+        * weight data that is not canonically stored elsewhere (such as RDBMS).
+        * Stashes should be configured to propagate changes to all data-centers.
+        *
+        * Callers should be prepared for:
+        *   - a) Writes to be slower in non-"primary" (e.g. HTTP GET/HEAD only) DCs
+        *   - b) Reads to be eventually consistent, e.g. for get()/getMulti()
+        * In general, this means avoiding updates on idempotent HTTP requests and
+        * avoiding an assumption of perfect serializability (or accepting anomalies).
+        * Reads may be eventually consistent or data might rollback as nodes flap.
+        *
+        *
+        * @return BagOStuff
+        * @since 1.26
+        */
+       static function getMainStashInstance() {
+               global $wgMainStash;
+
+               return self::getInstance( $wgMainStash );
+       }
 }
index 23a2993..bac020d 100644 (file)
@@ -63,6 +63,27 @@ class ExtensionProcessor implements Processor {
                'license-name',
        );
 
+       /**
+        * Things that are not 'attributes', but are not in
+        * $globalSettings or $creditsAttributes.
+        *
+        * @var array
+        */
+       protected static $notAttributes = array(
+               'callback',
+               'Hooks',
+               'namespaces',
+               'ResourceFileModulePaths',
+               'ResourceModules',
+               'ResourceModuleSkinStyles',
+               'ExtensionMessagesFiles',
+               'MessagesDirs',
+               'type',
+               'config',
+               'ParserTestFiles',
+               'AutoloadClasses',
+       );
+
        /**
         * Stuff that is going to be set to $GLOBALS
         *
@@ -102,13 +123,6 @@ class ExtensionProcessor implements Processor {
         */
        protected $attributes = array();
 
-       /**
-        * List of keys that have already been processed
-        *
-        * @var array
-        */
-       protected $processed = array();
-
        /**
         * @param string $path
         * @param array $info
@@ -125,7 +139,6 @@ class ExtensionProcessor implements Processor {
                $this->extractParserTestFiles( $dir, $info );
                if ( isset( $info['callback'] ) ) {
                        $this->callbacks[] = $info['callback'];
-                       $this->processed[] = 'callback';
                }
 
                $this->extractCredits( $path, $info );
@@ -133,11 +146,12 @@ class ExtensionProcessor implements Processor {
                        if ( in_array( $key, self::$globalSettings ) ) {
                                $this->storeToArray( "wg$key", $val, $this->globals );
                        // Ignore anything that starts with a @
-                       } elseif ( $key[0] !== '@' && !in_array( $key, $this->processed ) ) {
+                       } elseif ( $key[0] !== '@' && !in_array( $key, self::$notAttributes )
+                               && !in_array( $key, self::$creditsAttributes )
+                       ) {
                                $this->storeToArray( $key, $val, $this->attributes );
                        }
                }
-
        }
 
        public function getExtractedInfo() {
@@ -157,7 +171,6 @@ class ExtensionProcessor implements Processor {
                                        $this->globals['wgHooks'][$name][] = $callback;
                                }
                        }
-                       $this->processed[] = 'Hooks';
                }
        }
 
@@ -185,7 +198,6 @@ class ExtensionProcessor implements Processor {
                                        $this->globals['wgNamespaceContentModels'][$id] = $ns['defaultcontentmodel'];
                                }
                        }
-                       $this->processed[] = 'namespaces';
                }
        }
 
@@ -217,7 +229,6 @@ class ExtensionProcessor implements Processor {
                        $this->globals["wgExtensionMessagesFiles"] += array_map( function( $file ) use ( $dir ) {
                                return "$dir/$file";
                        }, $info['ExtensionMessagesFiles'] );
-                       $this->processed[] = 'ExtensionMessagesFiles';
                }
        }
 
@@ -235,7 +246,6 @@ class ExtensionProcessor implements Processor {
                                        $this->globals["wgMessagesDirs"][$name][] = "$dir/$file";
                                }
                        }
-                       $this->processed[] = 'MessagesDirs';
                }
        }
 
@@ -244,11 +254,9 @@ class ExtensionProcessor implements Processor {
                        'path' => $path,
                        'type' => isset( $info['type'] ) ? $info['type'] : 'other',
                );
-               $this->processed[] = 'type';
                foreach ( self::$creditsAttributes as $attr ) {
                        if ( isset( $info[$attr] ) ) {
                                $credits[$attr] = $info[$attr];
-                               $this->processed[] = $attr;
                        }
                }
 
@@ -268,7 +276,6 @@ class ExtensionProcessor implements Processor {
                                        $this->globals["wg$key"] = $val;
                                }
                        }
-                       $this->processed[] = 'config';
                }
        }
 
@@ -277,7 +284,6 @@ class ExtensionProcessor implements Processor {
                        foreach ( $info['ParserTestFiles'] as $path ) {
                                $this->globals['wgParserTestFiles'][] = "$dir/$path";
                        }
-                       $this->processed[] = 'ParserTestFiles';
                }
        }
 
index 75d0bb7..4cad259 100644 (file)
@@ -38,13 +38,6 @@ class ExtensionRegistry {
         */
        protected $attributes = array();
 
-       /**
-        * Processors, 'default' should be set by subclasses in the constructor
-        *
-        * @var Processor[]
-        */
-       protected $processors = array();
-
        /**
         * @var ExtensionRegistry
         */
@@ -90,8 +83,6 @@ class ExtensionRegistry {
                        return;
                }
 
-               $this->queued = array_unique( $this->queued );
-
                // See if this queue is in APC
                $key = wfMemcKey( 'registration', md5( json_encode( $this->queued ) ) );
                $data = $this->cache->get( $key );
@@ -119,6 +110,7 @@ class ExtensionRegistry {
        public function readFromQueue( array $queue ) {
                $data = array( 'globals' => array( 'wgAutoloadClasses' => array() ) );
                $autoloadClasses = array();
+               $processor = new ExtensionProcessor();
                foreach ( $queue as $path => $mtime ) {
                        $json = file_get_contents( $path );
                        if ( $json === false ) {
@@ -132,36 +124,18 @@ class ExtensionRegistry {
                        // Set up the autoloader now so custom processors will work
                        $GLOBALS['wgAutoloadClasses'] += $autoload;
                        $autoloadClasses += $autoload;
-                       if ( isset( $info['processor'] ) ) {
-                               $processor = $this->getProcessor( $info['processor'] );
-                       } else {
-                               $processor = $this->getProcessor( 'default' );
-                       }
                        $processor->extractInfo( $path, $info );
                }
-               foreach ( $this->processors as $processor ) {
-                       $data = array_merge_recursive( $data, $processor->getExtractedInfo() );
-               }
+               $data = $processor->getExtractedInfo();
+               // Need to set this so we can += to it later
+               $data['globals']['wgAutoloadClasses'] = array();
                foreach ( $data['credits'] as $credit ) {
                        $data['globals']['wgExtensionCredits'][$credit['type']][] = $credit;
                }
-               $this->processors = array(); // Reset
                $data['autoload'] = $autoloadClasses;
                return $data;
        }
 
-       protected function getProcessor( $type ) {
-               if ( !isset( $this->processors[$type] ) ) {
-                       $processor = $type === 'default' ? new ExtensionProcessor() : new $type();
-                       if ( !$processor instanceof Processor ) {
-                               throw new Exception( "$type is not a Processor" );
-                       }
-                       $this->processors[$type] = $processor;
-               }
-
-               return $this->processors[$type];
-       }
-
        protected function exportExtractedData( array $info ) {
                foreach ( $info['globals'] as $key => $val ) {
                        if ( !isset( $GLOBALS[$key] ) || !$GLOBALS[$key] ) {
index 88d95f2..ddd40f1 100644 (file)
@@ -78,6 +78,7 @@
        'be-x-old' => "беларуская (тарашкевіца)\xE2\x80\x8E",      # (be-tarask compat)
        'bg' => 'български',   # Bulgarian
        'bgn' => 'بلوچی رخشانی', # Western Balochi
+       'bh' => 'भोजपुरी',        # Bihari macro language. Falls back to Bhojpuri (bho)
        'bho' => 'भोजपुरी',       # Bhojpuri
        'bi' => 'Bislama',              # Bislama
        'bjn' => 'Bahasa Banjar',       # Banjarese
diff --git a/languages/messages/MessagesBh.php b/languages/messages/MessagesBh.php
new file mode 100644 (file)
index 0000000..4453bd1
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+/** Bihari (भोजपुरी)
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ */
+
+$fallback = 'bho';
+
index d47ffa9..9474496 100644 (file)
@@ -27,12 +27,14 @@ class ExtensionProcessorTest extends MediaWikiTestCase {
                $processor->extractInfo( $this->dir, self::$default + array(
                        '@metadata' => array( 'foobarbaz' ),
                        'AnAttribute' => array( 'omg' ),
+                       'AutoloadClasses' => array( 'FooBar' => 'includes/FooBar.php' ),
                ) );
 
                $extracted = $processor->getExtractedInfo();
                $attributes = $extracted['attributes'];
                $this->assertArrayHasKey( 'AnAttribute', $attributes );
                $this->assertArrayNotHasKey( '@metadata', $attributes );
+               $this->assertArrayNotHasKey( 'AutoloadClasses', $attributes );
        }
 
        public static function provideRegisterHooks() {