Merge "Convert Title::getTitleCache() to using MapCacheLRU (again)"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 19 Jul 2018 18:19:56 +0000 (18:19 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 19 Jul 2018 18:19:56 +0000 (18:19 +0000)
12 files changed:
autoload.php
docs/uidesign/table-layout.html [deleted file]
includes/DefaultSettings.php
includes/MediaWikiServices.php
includes/ServiceWiring.php
includes/config/ConfigRepository.php [new file with mode: 0644]
includes/registration/ExtensionProcessor.php
includes/registration/ExtensionRegistry.php
includes/registration/Processor.php
maintenance/mysql.php
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less
tests/phpunit/includes/MediaWikiServicesTest.php

index 5fb5ae0..64c34b5 100644 (file)
@@ -888,6 +888,7 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Auth\\Throttler' => __DIR__ . '/includes/auth/Throttler.php',
        'MediaWiki\\Auth\\UserDataAuthenticationRequest' => __DIR__ . '/includes/auth/UserDataAuthenticationRequest.php',
        'MediaWiki\\Auth\\UsernameAuthenticationRequest' => __DIR__ . '/includes/auth/UsernameAuthenticationRequest.php',
+       'MediaWiki\\Config\\ConfigRepository' => __DIR__ . '/includes/config/ConfigRepository.php',
        'MediaWiki\\DB\\PatchFileLocation' => __DIR__ . '/includes/db/PatchFileLocation.php',
        'MediaWiki\\Diff\\ComplexityException' => __DIR__ . '/includes/diff/ComplexityException.php',
        'MediaWiki\\Diff\\WordAccumulator' => __DIR__ . '/includes/diff/WordAccumulator.php',
diff --git a/docs/uidesign/table-layout.html b/docs/uidesign/table-layout.html
deleted file mode 100644 (file)
index 2c26819..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-       <style>
-               /** This is just for coloring: */
-               table { border: 1px solid #CC0; }
-               td { border: 1px solid  #CCC; }
-
-               table {
-                       width: 100%;
-                       table-layout: fixed;
-               }
-
-               #first {
-                       width: 300px;
-               }
-       </style>
-</head>
-<body>
-
-<p>
-This play with table-layout:fixed; and applying the width to colgroup or col element. Firefox only recongize the width if it is applied on col element!</p>
-<p>
-On a perfect browser, both tables should look the same</p>
-
-<dl>
-       <dt>colgroup</dt>
-       <dd>300 px width is applied to the first colgroup element</dd>
-</dl>
-<div style="width: 400px;">
-<table>
-       <colgroup id="first" /></colgroup>
-       <colgroup id="second"/></colgroup>
-       <colgroup id="third" /></colgroup>
-       <tr>
-               <td>Very long?</td>
-               <td>#</td>
-               <td>$</td>
-       </tr>
-</table>
-</div>
-
-<dl>
-       <dt>col</dt>
-       <dd>Each colgroup has an additional col element. The first col element is applied the 300 px width</dd>
-</dl>
-
-<div style="width: 400px;">
-<table>
-       <colgroup><col id="first" /></colgroup>
-       <colgroup><col id="second"/></colgroup>
-       <colgroup><col id="third" /></colgroup>
-       <tr>
-               <td>Very long?</td>
-               <td>#</td>
-               <td>$</td>
-       </tr>
-</table>
-</div>
index 9a08c8c..2811613 100644 (file)
@@ -8975,7 +8975,7 @@ $wgCommentTableSchemaMigrationStage = MIGRATION_OLD;
  * @since 1.32
  * @var int An appropriate combination of SCHEMA_COMPAT_XXX flags.
  */
-$wgMultiContentRevisionSchemaMigrationStage = MIGRATION_OLD;
+$wgMultiContentRevisionSchemaMigrationStage = SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD;
 
 /**
  * Actor table schema migration stage.
index a756d50..7a4c2df 100644 (file)
@@ -27,6 +27,7 @@ use Wikimedia\Rdbms\LBFactory;
 use LinkCache;
 use Wikimedia\Rdbms\LoadBalancer;
 use MediaHandlerFactory;
+use MediaWiki\Config\ConfigRepository;
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\Linker\LinkRendererFactory;
 use MediaWiki\Services\SalvageableService;
@@ -855,6 +856,13 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'OldRevisionImporter' );
        }
 
+       /**
+        * @return ConfigRepository
+        */
+       public function getConfigRepository() {
+               return $this->getService( 'ConfigRepository' );
+       }
+
        ///////////////////////////////////////////////////////////////////////////
        // NOTE: When adding a service getter here, don't forget to add a test
        // case for it in MediaWikiServicesTest::provideGetters() and in
index 6da537d..7d49080 100644 (file)
@@ -38,6 +38,7 @@
  */
 
 use MediaWiki\Auth\AuthManager;
+use MediaWiki\Config\ConfigRepository;
 use MediaWiki\Interwiki\ClassicInterwikiLookup;
 use MediaWiki\Linker\LinkRendererFactory;
 use MediaWiki\Logger\LoggerFactory;
@@ -104,6 +105,10 @@ return [
                return $factory;
        },
 
+       'ConfigRepository' => function ( MediaWikiServices $services ) {
+               return new ConfigRepository( $services->getConfigFactory() );
+       },
+
        'MainConfig' => function ( MediaWikiServices $services ) {
                // Use the 'main' config from the ConfigFactory service.
                return $services->getConfigFactory()->makeConfig( 'main' );
diff --git a/includes/config/ConfigRepository.php b/includes/config/ConfigRepository.php
new file mode 100644 (file)
index 0000000..c87a344
--- /dev/null
@@ -0,0 +1,224 @@
+<?php
+/**
+ * Copyright 2016
+ *
+ * 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
+ */
+
+namespace MediaWiki\Config;
+
+use MediaWiki\Services\SalvageableService;
+use Wikimedia\Assert\Assert;
+
+/**
+ * Object which holds currently registered configuration options.
+ *
+ * @since 1.32
+ */
+class ConfigRepository implements SalvageableService {
+       /** @var \ConfigFactory */
+       private $configFactory;
+
+       /** @var array */
+       private $configItems = [
+               'private' => [],
+               'public' => [],
+       ];
+
+       /**
+        * @param \ConfigFactory $configFactory
+        */
+       public function __construct( \ConfigFactory $configFactory ) {
+               $this->configFactory = $configFactory;
+       }
+
+       /**
+        * Returns true, if this repository contains a configuration with a specific name.
+        *
+        * @param string $name The name of the config to check the existence of
+        * @param bool $alsoPrivate If set to true, will check the private config options, too
+        * @return bool
+        */
+       public function has( $name, $alsoPrivate = false ) {
+               return isset( $this->configItems['public'][$name] ) ||
+                       ( $alsoPrivate && isset( $this->configItems['private'][$name] ) );
+       }
+
+       /**
+        * Returns the ConfigItem with the given name, if there's one. Throws a ConfigException
+        * otherwise.
+        *
+        * @param string $name The name of the configuration option to get
+        * @return array
+        * @throws \ConfigException
+        */
+       public function get( $name ) {
+               if ( !$this->has( $name, true ) ) {
+                       throw new \ConfigException( 'The configuration option ' . $name . ' does not exist.' );
+               }
+               if ( isset( $this->configItems['public'][$name] ) ) {
+                       return $this->configItems['public'][$name];
+               }
+               return $this->configItems['private'][$name];
+       }
+
+       /**
+        * Returns an array of all configuration items saved in this ConfigRepository. This includes
+        * all configuration options, including the ones marked as private and public.
+        *
+        * Note: This function does not do any permission checks or something similar. You should not
+        * use this function, if the output will be available to the public audience! Use
+        * ConfigRepository::getPublic() instead.
+        *
+        * @return array
+        */
+       public function getAll() {
+               return array_merge( $this->configItems['private'], $this->configItems['public'] );
+       }
+
+       /**
+        * Returns an array of all public configuration options saved in this ConfigRepository.
+        *
+        * @return array
+        */
+       public function getPublic() {
+               return $this->configItems['public'];
+       }
+
+       /**
+        * Returns the current value of the configuration option. If no ConfigRegistry was provided
+        * when the config was added to the repository, the default value will be returned.
+        *
+        * @param string $name The name of the configuration option to get the value of
+        * @return mixed
+        * @throws \ConfigException
+        */
+       public function getValueOf( $name ) {
+               $config = $this->get( $name );
+               if ( !isset( $config['configregistry'] ) ) {
+                       return $config['value'];
+               }
+
+               return $this->configFactory->makeConfig( $config['configregistry'] )->get( $name );
+       }
+
+       /**
+        * Returns the description of the given config option, This can be either a localized
+        * description, if one such, or the (maybe english only) description provided in the
+        * definition of the configuration. If both is not provided an empty string is returned.
+        *
+        * @param string $name The name of the configuration option to get the description of
+        * @return string HTML-escaped string
+        */
+       public function getDescriptionOf( $name ) {
+               $config = $this->get( $name );
+               if ( isset( $config['descriptionmsg'] ) ) {
+                       return wfMessage( $config['descriptionmsg'] )->escaped();
+               }
+               if ( isset( $config['description'] ) ) {
+                       return htmlspecialchars( $config['description'] );
+               }
+               return '';
+       }
+
+       /**
+        * Adds the definition of a configuration to this repository.
+        *
+        * @param string $name the name of the config
+        * @param array $config Options of this config. Values are:
+        *  - value: The default value of this configuration, required
+        *  - providedby: The name of the provider of this config (an extension, core, ...), required
+        *  - configregistry: The name of the config to retrieve the value with, required
+        *  - public: whether this option is public or not, if not set, the option is considered as
+        *    "private", optional
+        *  - description: the not localized description of this config option, optional
+        *  - descriptionmsg: The message key of the localized description of this configuration
+        *    option, optional
+        * @throws \ConfigException
+        */
+       public function add( $name, array $config ) {
+               if ( $this->has( $name ) ) {
+                       throw new \ConfigException( 'A configuration with the name ' . $name .
+                               'does already exist. It is provided by: ' .
+                               $this->get( $name )['providedby'] );
+               }
+               if ( isset( $config['public'] ) && $config['public'] ) {
+                       $this->configItems['public'][$name] = $config;
+               } else {
+                       $this->configItems['private'][$name] = $config;
+               }
+       }
+
+       /**
+        * Returns true, if there're no elements in this instance, otherwise false.
+        *
+        * @param bool $includePrivate Whether configuration options, that are marked as private
+        * should be included in this check.
+        * @return bool
+        */
+       public function isEmpty( $includePrivate = false ) {
+               if ( $includePrivate ) {
+                       return empty( $this->configItems['private'] ) &&
+                               empty( $this->configItems[ 'public'] );
+               }
+               return empty( $this->configItems['public'] );
+       }
+
+       /**
+        * Re-uses existing Cache objects from $other. Cache objects are only re-used if the
+        * registered factory function for both is the same.
+        *
+        * @see SalvageableService::salvage()
+        *
+        * @param SalvageableService $other The object to salvage state from. $other must have the
+        * exact same type as $this.
+        */
+       public function salvage( SalvageableService $other ) {
+               Assert::parameterType( self::class, $other, '$other' );
+
+               /** @var ConfigRepository $other */
+               $otherCurrentObj = $other->current();
+               foreach ( $other->configItems['public'] as $name => $otherConfig ) {
+                       if ( isset( $this->configItems['public'][$name] ) ) {
+                               continue;
+                       }
+
+                       $this->add( $name, $otherConfig );
+
+                       // recover the pointer of the other config repository
+                       if ( $otherCurrentObj === $otherConfig ) {
+                               end( $this->configItems['public'] );
+                       }
+               }
+               foreach ( $other->configItems['private'] as $name => $otherConfig ) {
+                       if ( isset( $this->configItems['private'][$name] ) ) {
+                               continue;
+                       }
+
+                       $this->add( $name, $otherConfig );
+
+                       // recover the pointer of the other config repository
+                       if ( $otherCurrentObj === $otherConfig ) {
+                               end( $this->configItems['private'] );
+                       }
+               }
+
+               // disable $other
+               $other->configItems = [];
+       }
+}
index a803e3a..d0a9871 100644 (file)
@@ -162,6 +162,11 @@ class ExtensionProcessor implements Processor {
         */
        protected $credits = [];
 
+       /**
+        * @var array
+        */
+       protected $config = [];
+
        /**
         * Any thing else in the $info that hasn't
         * already been processed
@@ -290,6 +295,7 @@ class ExtensionProcessor implements Processor {
 
                return [
                        'globals' => $this->globals,
+                       'config' => $this->config,
                        'defines' => $this->defines,
                        'callbacks' => $this->callbacks,
                        'credits' => $this->credits,
@@ -493,6 +499,11 @@ class ExtensionProcessor implements Processor {
                                        $value = "$dir/$value";
                                }
                                $this->addConfigGlobal( "$prefix$key", $value, $info['name'] );
+                               $data['providedby'] = $info['name'];
+                               if ( isset( $info['ConfigRegistry'][0] ) ) {
+                                       $data['configregistry'] = array_keys( $info['ConfigRegistry'] )[0];
+                               }
+                               $this->config[$key] = $data;
                        }
                }
        }
index c58b55e..d21ae41 100644 (file)
@@ -36,7 +36,7 @@ class ExtensionRegistry {
        /**
         * Bump whenever the registration cache needs resetting
         */
-       const CACHE_VERSION = 6;
+       const CACHE_VERSION = 7;
 
        /**
         * Special key that defines the merge strategy
index 210deb1..636d3b3 100644 (file)
@@ -25,6 +25,7 @@ interface Processor {
         * @return array With following keys:
         *     'globals' - variables to be set to $GLOBALS
         *     'defines' - constants to define
+        *     'config' - configuration information
         *     'callbacks' - functions to be executed by the registry
         *     'credits' - metadata to be stored by registry
         *     'attributes' - registration info which isn't a global variable
index 6d0882a..1b575bb 100644 (file)
@@ -165,6 +165,12 @@ class MysqlMaintenance extends Maintenance {
 
                $args = array_merge( $args, $this->mArgs );
 
+               // Ignore SIGINT if possible, otherwise the wrapper terminates when the user presses
+               // ctrl-C to kill a query.
+               if ( function_exists( 'pcntl_signal' ) ) {
+                       pcntl_signal( SIGINT, SIG_IGN );
+               }
+
                $pipes = [];
                $proc = proc_open( Shell::escape( $args ), $desc, $pipes );
                if ( $proc === false ) {
index ad0bc4a..1cc48e2 100644 (file)
                        display: block;
                        padding-top: 1em;
                }
+
+               label {
+                       // Workaround for Chrome browser bug (T199932)
+                       // Override padding rule from FieldLayout
+                       padding-left: 0 !important; /* stylelint-disable-line declaration-no-important */
+               }
        }
 
        .mw-rcfilters-ui-cell {
index 093cb07..7763aff 100644 (file)
@@ -364,6 +364,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                        'ExternalStoreFactory' => [ 'ExternalStoreFactory', ExternalStoreFactory::class ],
                        'PreferencesFactory' => [ 'PreferencesFactory', PreferencesFactory::class ],
                        'ActorMigration' => [ 'ActorMigration', ActorMigration::class ],
+                       'ConfigRepository' => [ 'ConfigRepository', \MediaWiki\Config\ConfigRepository::class ],
                ];
        }