Merge "Allow closures as HTMLInfoField values"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 4 Aug 2016 19:10:09 +0000 (19:10 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 4 Aug 2016 19:10:09 +0000 (19:10 +0000)
148 files changed:
RELEASE-NOTES-1.28
autoload.php
composer.json
docs/extension.schema.json
docs/extension.schema.v1.json
docs/hooks.txt
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/MediaWikiServices.php
includes/OutputPage.php
includes/Pingback.php
includes/ServiceWiring.php
includes/Status.php
includes/api/i18n/gl.json
includes/auth/LocalPasswordPrimaryAuthenticationProvider.php
includes/content/ContentHandler.php
includes/content/TextContentHandler.php
includes/content/WikiTextStructure.php [new file with mode: 0644]
includes/content/WikitextContentHandler.php
includes/deferred/CdnCacheUpdate.php
includes/filerepo/FileRepoStatus.php
includes/filerepo/file/File.php
includes/installer/i18n/gl.json
includes/media/MediaHandler.php
includes/media/MediaHandlerFactory.php [new file with mode: 0644]
includes/objectcache/ObjectCache.php
includes/page/Article.php
includes/page/WikiPage.php
includes/profiler/ProfileSection.php
includes/profiler/ProfilerFunctions.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderUserModule.php
includes/resourceloader/ResourceLoaderUserStylesModule.php [new file with mode: 0644]
includes/search/SearchEngine.php
includes/site/SiteSQLStore.php
includes/skins/Skin.php
includes/specials/SpecialResetTokens.php
includes/specials/SpecialUpload.php
includes/upload/UploadBase.php
includes/upload/UploadFromStash.php
includes/user/User.php
includes/utils/AutoloadGenerator.php
languages/i18n/ar.json
languages/i18n/be-tarask.json
languages/i18n/cs.json
languages/i18n/diq.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/kiu.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/lt.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/ru.json
languages/i18n/sl.json
languages/i18n/vi.json
languages/i18n/yi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
maintenance/generateLocalAutoload.php
resources/Resources.php
resources/lib/oojs-ui/i18n/cy.json
resources/lib/oojs-ui/i18n/et.json
resources/lib/oojs-ui/i18n/ko.json
resources/lib/oojs-ui/i18n/sq.json
resources/lib/oojs-ui/oojs-ui-apex.js
resources/lib/oojs-ui/oojs-ui-core-apex.css
resources/lib/oojs-ui/oojs-ui-core-mediawiki.css
resources/lib/oojs-ui/oojs-ui-core.js
resources/lib/oojs-ui/oojs-ui-mediawiki.js
resources/lib/oojs-ui/oojs-ui-toolbars-apex.css
resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css
resources/lib/oojs-ui/oojs-ui-toolbars.js
resources/lib/oojs-ui/oojs-ui-widgets-apex.css
resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css
resources/lib/oojs-ui/oojs-ui-widgets.js
resources/lib/oojs-ui/oojs-ui-windows-apex.css
resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css
resources/lib/oojs-ui/oojs-ui-windows.js
resources/lib/oojs-ui/themes/apex/icons-alerts.json [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/bell.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/bell.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/eye.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/eye.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/tray.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/tray.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/icons-alerts.json
resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.svg [new file with mode: 0644]
resources/src/jquery/jquery.accessKeyLabel.js
resources/src/mediawiki.legacy/shared.css
tests/TestsAutoLoader.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/GlobalFunctions/wfThumbIsStandardTest.php
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/content/ContentHandlerTest.php
tests/phpunit/includes/content/TextContentHandlerTest.php
tests/phpunit/includes/content/WikitextContentHandlerTest.php
tests/phpunit/includes/content/WikitextStructureTest.php [new file with mode: 0644]
tests/phpunit/includes/parser/NewParserTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php
tests/phpunit/includes/search/SearchEngineTest.php
tests/phpunit/mocks/media/MockMediaHandlerFactory.php [new file with mode: 0644]
tests/phpunit/structure/AutoLoaderTest.php
tests/phpunit/suites/ExtensionsTestSuite.php

index 9acd1d8..757cec3 100644 (file)
@@ -89,10 +89,19 @@ changes to languages because of Phabricator reports.
   MediaWiki\Linker\LinkRenderer. In addition, the LinkBegin and LinkEnd hooks
   were replaced by HtmlPageLinkRendererBegin and HtmlPageLinkRendererEnd
   respectively. See docs/hooks.txt for the specific changes needed for those hooks.
+* Aliases for Linker methods, deprecated since 1.21, were removed from Skin:
+  * Skin::commentBlock() (use Linker::commentBlock() instead)
+  * Skin::generateRollback() (use Linker::generateRollback() instead)
+  * Skin::link() (use MediaWiki\Linker\LinkRenderer instead)
+  * Skin::linkKnown() (use MediaWiki\Linker\LinkRenderer instead)
+  * Skin::userLink() (use Linker::userLink() instead)
+  * Skin::userToolLinks() (use Linker::userToolLinks() instead)
 * The 'ParserLimitReportFormat' hook was removed.
 * Disabled "bug 2702" HTML tidying of parsed UI messages on wikis where Tidy is
   disabled.
 * DifferenceEngine::generateDiffBody() was removed (deprecated since 1.21).
+* UploadBase::stashFileGetKey() and UploadBase::stashSession() were deprecated.
+  Use ...->stashFile()->getFileKey() instead.
 
 == Compatibility ==
 
index 50d544c..29f986e 100644 (file)
@@ -790,6 +790,7 @@ $wgAutoloadLocalClasses = [
        'MarkpatrolledAction' => __DIR__ . '/includes/actions/MarkpatrolledAction.php',
        'McTest' => __DIR__ . '/maintenance/mctest.php',
        'MediaHandler' => __DIR__ . '/includes/media/MediaHandler.php',
+       'MediaHandlerFactory' => __DIR__ . '/includes/media/MediaHandlerFactory.php',
        'MediaStatisticsPage' => __DIR__ . '/includes/specials/SpecialMediaStatistics.php',
        'MediaTransformError' => __DIR__ . '/includes/media/MediaTransformOutput.php',
        'MediaTransformInvalidParametersException' => __DIR__ . '/includes/media/MediaTransformInvalidParametersException.php',
@@ -1169,6 +1170,7 @@ $wgAutoloadLocalClasses = [
        'ResourceLoaderUserDefaultsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserDefaultsModule.php',
        'ResourceLoaderUserModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserModule.php',
        'ResourceLoaderUserOptionsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserOptionsModule.php',
+       'ResourceLoaderUserStylesModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserStylesModule.php',
        'ResourceLoaderUserTokensModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserTokensModule.php',
        'ResourceLoaderWikiModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderWikiModule.php',
        'RestbaseVirtualRESTService' => __DIR__ . '/includes/libs/virtualrest/RestbaseVirtualRESTService.php',
@@ -1539,6 +1541,7 @@ $wgAutoloadLocalClasses = [
        'WikiReference' => __DIR__ . '/includes/WikiMap.php',
        'WikiRevision' => __DIR__ . '/includes/import/WikiRevision.php',
        'WikiStatsOutput' => __DIR__ . '/maintenance/language/StatOutputs.php',
+       'WikiTextStructure' => __DIR__ . '/includes/content/WikiTextStructure.php',
        'WikitextContent' => __DIR__ . '/includes/content/WikitextContent.php',
        'WikitextContentHandler' => __DIR__ . '/includes/content/WikitextContentHandler.php',
        'WinCacheBagOStuff' => __DIR__ . '/includes/libs/objectcache/WinCacheBagOStuff.php',
index 1bd3d4c..9bd0fa1 100644 (file)
@@ -25,7 +25,7 @@
                "ext-xml": "*",
                "liuggio/statsd-php-client": "1.0.18",
                "mediawiki/at-ease": "1.1.0",
-               "oojs/oojs-ui": "0.17.6",
+               "oojs/oojs-ui": "0.17.7",
                "oyejorge/less.php": "1.7.0.10",
                "php": ">=5.5.9",
                "psr/log": "1.0.0",
index 110e99d..c010014 100644 (file)
                                                                        "type": "string",
                                                                        "description": "Group with which this module should be loaded"
                                                                },
+                                                               "deprecated": {
+                                                                       "type": ["object", "boolean"],
+                                                                       "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
+                                                               },
                                                                "position": {
                                                                        "type": "string",
                                                                        "description": "Position on the page to load this module at",
index 37235e9..d707864 100644 (file)
                                                                        "type": "string",
                                                                        "description": "Group which this module should be loaded together with"
                                                                },
+                                                               "deprecated": {
+                                                                       "type": ["object", "boolean"],
+                                                                       "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
+                                                               },
                                                                "position": {
                                                                        "type": "string",
                                                                        "description": "Position on the page to load this module at",
index 57240c9..89a54d5 100644 (file)
@@ -608,6 +608,7 @@ $reason: the reason the article was deleted
 $id: id of the article that was deleted
 $content: the Content of the deleted page
 $logEntry: the ManualLogEntry used to record the deletion
+$archivedRevisionCount: the number of revisions archived during the deletion
 
 'ArticleEditUpdateNewTalk': Before updating user_newtalk when a user talk page
 was changed.
@@ -2620,6 +2621,18 @@ search results.
 $title: Current Title object being displayed in search results.
 &$id: Revision ID (default is false, for latest)
 
+'SearchIndexFields': Add fields to search index mapping.
+&$fields: Array of fields, all implement SearchIndexField
+$engine: SearchEngine instance for which mapping is being built.
+
+'SearchDataForIndex': Add data to search document. Allows to add any data to
+the field map used to index the document.
+&$fields: Array of name => value pairs for fields
+$handler: ContentHandler for the content being indexed
+$page: WikiPage that is being indexed
+$output: ParserOutput that is produced from the page
+$engine: SearchEngine for which the indexing is intended
+
 'SecondaryDataUpdates': Allows modification of the list of DataUpdates to
 perform when page content is modified. Currently called by
 AbstractContent::getSecondaryDataUpdates.
index 5926328..3c5e2d2 100644 (file)
@@ -945,22 +945,11 @@ $wgTrustedMediaFormats = [
 /**
  * Plugins for media file type handling.
  * Each entry in the array maps a MIME type to a class name
+ *
+ * Core media handlers are listed in MediaHandlerFactory,
+ * and extensions should use extension.json.
  */
-$wgMediaHandlers = [
-       'image/jpeg' => 'JpegHandler',
-       'image/png' => 'PNGHandler',
-       'image/gif' => 'GIFHandler',
-       'image/tiff' => 'TiffHandler',
-       'image/webp' => 'WebPHandler',
-       'image/x-ms-bmp' => 'BmpHandler',
-       'image/x-bmp' => 'BmpHandler',
-       'image/x-xcf' => 'XCFHandler',
-       'image/svg+xml' => 'SvgHandler', // official
-       'image/svg' => 'SvgHandler', // compat
-       'image/vnd.djvu' => 'DjVuHandler', // official
-       'image/x.djvu' => 'DjVuHandler', // compat
-       'image/x-djvu' => 'DjVuHandler', // compat
-];
+$wgMediaHandlers = [];
 
 /**
  * Plugins for page content model handling.
@@ -2524,7 +2513,7 @@ $wgFileCacheDepth = 2;
 
 /**
  * Kept for extension compatibility; see $wgParserCacheType
- * @deprecated 1.26
+ * @deprecated since 1.26
  */
 $wgEnableParserCache = true;
 
index e19c36c..7117f4c 100644 (file)
@@ -2950,7 +2950,7 @@ function wfRelativePath( $path, $from ) {
  * Supports base 2 through 36; digit values 10-36 are represented
  * as lowercase letters a-z. Input is case-insensitive.
  *
- * @deprecated 1.27 Use Wikimedia\base_convert() directly
+ * @deprecated since 1.27 Use Wikimedia\base_convert() directly
  *
  * @param string $input Input number
  * @param int $sourceBase Base of the input number
@@ -3525,7 +3525,7 @@ function wfGetParserCacheStorage() {
  * @param string|null $deprecatedVersion Optionally mark hook as deprecated with version number
  *
  * @return bool True if no handler aborted the hook
- * @deprecated 1.25 - use Hooks::run
+ * @deprecated since 1.25 - use Hooks::run
  */
 function wfRunHooks( $event, array $args = [], $deprecatedVersion = null ) {
        return Hooks::run( $event, $args, $deprecatedVersion );
index ff292cf..ac5fbe0 100644 (file)
@@ -11,6 +11,7 @@ use LBFactory;
 use LinkCache;
 use Liuggio\StatsdClient\Factory\StatsdDataFactory;
 use LoadBalancer;
+use MediaHandlerFactory;
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\Linker\LinkRendererFactory;
 use MediaWiki\Services\SalvageableService;
@@ -511,6 +512,14 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'WatchedItemQueryService' );
        }
 
+       /**
+        * @since 1.28
+        * @return MediaHandlerFactory
+        */
+       public function getMediaHandlerFactory() {
+               return $this->getService( 'MediaHandlerFactory' );
+       }
+
        /**
         * @since 1.28
         * @return GenderCache
index d34ace8..b6c48ab 100644 (file)
@@ -633,7 +633,7 @@ class OutputPage extends ContextSource {
        }
 
        /**
-        * Add or replace an header item to the output
+        * Add or replace a head item to the output
         *
         * Whenever possible, use more specific options like ResourceLoader modules,
         * OutputPage::addLink(), OutputPage::addMetaLink() and OutputPage::addFeedLink()
@@ -648,6 +648,16 @@ class OutputPage extends ContextSource {
                $this->mHeadItems[$name] = $value;
        }
 
+       /**
+        * Add one or more head items to the output
+        *
+        * @since 1.28
+        * @param string|string[] $value Raw HTML
+        */
+       public function addHeadItems( $values ) {
+               $this->mHeadItems = array_merge( $this->mHeadItems, (array)$values );
+       }
+
        /**
         * Check if the header item $name is already set
         *
@@ -3650,7 +3660,7 @@ class OutputPage extends ContextSource {
                ) {
                        // We're on a preview of a CSS subpage
                        // Exclude this page from the user module in case it's in there (bug 26283)
-                       $link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES,
+                       $link = $this->makeResourceLoaderLink( 'user.styles', ResourceLoaderModule::TYPE_STYLES,
                                [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
                        );
                        $otherTags = array_merge( $otherTags, $link['html'] );
@@ -3665,7 +3675,7 @@ class OutputPage extends ContextSource {
                        $otherTags[] = Html::inlineStyle( $previewedCSS );
                } else {
                        // Load the user styles normally
-                       $moduleStyles[] = 'user';
+                       $moduleStyles[] = 'user.styles';
                }
 
                // Per-user preference styles
index 10d2904..dd68102 100644 (file)
@@ -202,7 +202,7 @@ class Pingback {
         * <https://github.com/wikimedia/mediawiki-extensions-EventLogging/
         *   blob/7e5fe4f1ef/includes/EventLogging.php#L32-L74>
         *
-        * @param data Pingback data as an associative array
+        * @param array $data Pingback data as an associative array
         * @return bool true on success, false on failure
         */
        private function postPingback( array $data ) {
index d4f16ee..21c6377 100644 (file)
@@ -158,6 +158,12 @@ return [
                return new WatchedItemQueryService( $services->getDBLoadBalancer() );
        },
 
+       'MediaHandlerFactory' => function( MediaWikiServices $services ) {
+               return new MediaHandlerFactory(
+                       $services->getMainConfig()->get( 'MediaHandlers' )
+               );
+       },
+
        'LinkCache' => function( MediaWikiServices $services ) {
                return new LinkCache(
                        $services->getTitleFormatter()
index 45d8bed..e578873 100644 (file)
@@ -385,7 +385,7 @@ class Status {
         *
         * @return array A list in which each entry is an array with a message key as its first element.
         *         The remaining array elements are the message parameters.
-        * @deprecated 1.25
+        * @deprecated since 1.25
         */
        public function getErrorsArray() {
                return $this->getStatusArray( 'error' );
@@ -396,7 +396,7 @@ class Status {
         *
         * @return array A list in which each entry is an array with a message key as its first element.
         *         The remaining array elements are the message parameters.
-        * @deprecated 1.25
+        * @deprecated since 1.25
         */
        public function getWarningsArray() {
                return $this->getStatusArray( 'warning' );
index 289aa78..c5aef1d 100644 (file)
        "apihelp-parse-paramvalue-prop-sections": "Devolve as seccións do texto wiki analizado.",
        "apihelp-parse-paramvalue-prop-revid": "Engade o identificador de edición do texto wiki analizado.",
        "apihelp-parse-paramvalue-prop-displaytitle": "Engade o título do texto wiki analizado.",
-       "apihelp-parse-paramvalue-prop-headitems": "Devolve os elementos a poñer na <code>&lt;cabeceira&gt;</code> da páxina.",
+       "apihelp-parse-paramvalue-prop-headitems": "<span class=\"apihelp-deprecated\">Obsoleto.</span> Devolve os elementos a poñer na <code>&lt;cabeceira&gt;</code> da páxina.",
        "apihelp-parse-paramvalue-prop-headhtml": "Devolve <code>&lt;cabeceira&gt;</code> analizada da páxina.",
-       "apihelp-parse-paramvalue-prop-modules": "Devolve os módulos ResourceLoader usados na páxina. <kbd>jsconfigvars</kbd> ou <kbd>encodedjsconfigvars</kbd> deben ser solicitados xunto con <kbd>modules</kbd>.",
-       "apihelp-parse-paramvalue-prop-jsconfigvars": "Devolve as variables específicas de configuración JavaScript da páxina.",
+       "apihelp-parse-paramvalue-prop-modules": "Devolve os módulos ResourceLoader usados na páxina. Para cargar, use <code>mw.loader.using()</code>. <kbd>jsconfigvars</kbd> ou <kbd>encodedjsconfigvars</kbd> deben ser solicitados xunto con <kbd>modules</kbd>.",
+       "apihelp-parse-paramvalue-prop-jsconfigvars": "Devolve as variables específicas de configuración JavaScript da páxina. Para aplicalo, use <code>mw.config.set()</code>.",
        "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "Devolve as variables específicas de configuración JavaScript da páxina como unha cadea de texto JSON.",
        "apihelp-parse-paramvalue-prop-indicators": "Devolve o HTML dos indicadores de estado de páxina usados na páxina.",
        "apihelp-parse-paramvalue-prop-iwlinks": "Devolve as ligazóns interwiki do texto wiki analizado.",
        "apihelp-protect-description": "Cambiar o nivel de protección dunha páxina.",
        "apihelp-protect-param-title": "Título da páxina que quere (des)protexer. Non pode usarse xunto con $1pageid.",
        "apihelp-protect-param-pageid": "Identificador da páxina que quere (des)protexer. Non pode usarse xunto con $1title.",
-       "apihelp-protect-param-protections": "Lista dos niveis de protección, con formato <kbd>action=level</kbd> (p.ex. <kbd>edit=sysop</kbd>).\n\n<strong>Nota:</strong> Todas as accións que non estean listadas terán restriccións para ser eliminadas.",
+       "apihelp-protect-param-protections": "Lista dos niveis de protección, con formato <kbd>action=level</kbd> (p.ex. <kbd>edit=sysop</kbd>). Un nivel de <kbd>all</kbd> quere dicir que todo o mundo ten permiso para realizar a acción, sen restricións.\n\n<strong>Nota:</strong> Todas as accións que non estean listadas terán restriccións para ser eliminadas.",
        "apihelp-protect-param-expiry": "Selos de tempo de caducidade. Se só se indica un selo de tempo, usarase para todas as proteccións. Use <kbd>infinite</kbd>, <kbd>indefinite</kbd>, <kbd>infinity</kbd>, ou <kbd>never</kbd>, para unha protección sen caducidade.",
        "apihelp-protect-param-reason": "Razón para (des)protexer.",
        "apihelp-protect-param-tags": "Cambiar as etiquetas a aplicar na entrada do rexistro de protección.",
        "apihelp-protect-param-watch": "Se se define este parámetro, engadir a páxina que se (des)protexe á lista de vixilancia do usuario actual.",
        "apihelp-protect-param-watchlist": "Engadir ou eliminar sen condicións a páxina da lista de vixiancia do usuario actual, use as preferencias ou non cambie a vixiancia.",
        "apihelp-protect-example-protect": "Protexer unha páxina",
-       "apihelp-protect-example-unprotect": "Desprotexer unha páxina poñendo as restricións a <kbd>all</kbd>.",
+       "apihelp-protect-example-unprotect": "Desprotexer unha páxina poñendo as restricións a <kbd>all</kbd>. (isto quere dicir que todo o mundo pode realizar a acción).",
        "apihelp-protect-example-unprotect2": "Desprotexer unha páxina quitando as restricións.",
        "apihelp-purge-description": "Borrar a caché para os títulos indicados.\n\nPrecisa dunha petición POST se o usuario non está conectado.",
        "apihelp-purge-param-forcelinkupdate": "Actualizar as táboas de ligazóns.",
index 5f5ef79..bbc6e8d 100644 (file)
@@ -110,7 +110,7 @@ class LocalPasswordPrimaryAuthenticationProvider
                }
 
                $status = $this->checkPasswordValidity( $username, $req->password );
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        // Fatal, can't log in
                        return AuthenticationResponse::newFail( $status->getMessage() );
                }
index 1ecd614..7184980 100644 (file)
@@ -1270,4 +1270,69 @@ abstract class ContentHandler {
                 */
                return [];
        }
+
+       /**
+        * Add new field definition to array.
+        * @param SearchIndexField[] $fields
+        * @param SearchEngine       $engine
+        * @param string             $name
+        * @param int                $type
+        * @return SearchIndexField[] new field defs
+        * @since 1.28
+        */
+       protected function addSearchField( &$fields, SearchEngine $engine, $name, $type ) {
+               $fields[$name] = $engine->makeSearchFieldMapping( $name, $type );
+               return $fields;
+       }
+
+       /**
+        * Return fields to be indexed by search engine
+        * as representation of this document.
+        * Overriding class should call parent function or take care of calling
+        * the SearchDataForIndex hook.
+        * @param WikiPage     $page Page to index
+        * @param ParserOutput $output
+        * @param SearchEngine $engine Search engine for which we are indexing
+        * @return array Map of name=>value for fields
+        * @since 1.28
+        */
+       public function getDataForSearchIndex( WikiPage $page, ParserOutput $output,
+                                              SearchEngine $engine ) {
+               $fields = [];
+               $content = $page->getContent();
+               if ( $content ) {
+                       $text = $content->getTextForSearchIndex();
+                       $fields['text'] = $text;
+                       $fields['source_text'] = $text;
+                       $fields['text_bytes'] = $content->getSize();
+               }
+               Hooks::run( 'SearchDataForIndex', [ &$fields, $this, $page, $output, $engine ] );
+               return $fields;
+       }
+
+       /**
+        * Produce page output suitable for indexing.
+        *
+        * Specific content handlers may override it if they need different content handling.
+        *
+        * @param WikiPage    $page
+        * @param ParserCache $cache
+        * @return ParserOutput
+        */
+       public function getParserOutputForIndexing( WikiPage $page, ParserCache $cache = null ) {
+               $parserOptions = $page->makeParserOptions( 'canonical' );
+               $revId = $page->getRevision()->getId();
+               if ( $cache ) {
+                       $parserOutput = $cache->get( $page, $parserOptions );
+               }
+               if ( empty( $parserOutput ) ) {
+                       $parserOutput =
+                               $page->getContent()->getParserOutput( $page->getTitle(), $revId, $parserOptions );
+                       if ( $cache ) {
+                               $cache->save( $parserOutput, $page, $parserOptions );
+                       }
+               }
+               return $parserOutput;
+       }
+
 }
index 748c810..d4fad44 100644 (file)
@@ -148,4 +148,13 @@ class TextContentHandler extends ContentHandler {
                        $engine->makeSearchFieldMapping( 'language', SearchIndexField::INDEX_TYPE_KEYWORD );
                return $fields;
        }
+
+       public function getDataForSearchIndex( WikiPage $page, ParserOutput $output,
+                                              SearchEngine $engine ) {
+               $fields = parent::getDataForSearchIndex( $page, $output, $engine );
+               $fields['language'] =
+                       $this->getPageLanguage( $page->getTitle(), $page->getContent() )->getCode();
+               return $fields;
+       }
+
 }
diff --git a/includes/content/WikiTextStructure.php b/includes/content/WikiTextStructure.php
new file mode 100644 (file)
index 0000000..d4ba8a1
--- /dev/null
@@ -0,0 +1,277 @@
+<?php
+
+use HtmlFormatter\HtmlFormatter;
+use MediaWiki\Logger\LoggerFactory;
+
+/**
+ * Class allowing to explore structure of parsed wikitext.
+ */
+class WikiTextStructure {
+       /**
+        * @var string
+        */
+       private $openingText;
+       /**
+        * @var string
+        */
+       private $allText;
+       /**
+        * @var string[]
+        */
+       private $auxText = [];
+       /**
+        * @var ParserOutput
+        */
+       private $parserOutput;
+
+       /**
+        * @var string[] selectors to elements that are excluded entirely from search
+        */
+       private $excludedElementSelectors = [
+               'audio', 'video',       // "it looks like you don't have javascript enabled..."
+                                       // do not need to index
+               'sup.reference',        // The [1] for references
+               '.mw-cite-backlink',    // The ↑ next to references in the references section
+               'h1', 'h2', 'h3',       // Headings are already indexed in their own field.
+               'h5', 'h6', 'h4',
+               '.autocollapse',        // Collapsed fields are hidden by default so we don't want them
+                                                               // showing up.
+       ];
+
+       /**
+        * @var string[] selectors to elements that are considered auxiliary to article text for search
+        */
+       private $auxiliaryElementSelectors = [
+               '.thumbcaption',        // Thumbnail captions aren't really part of the text proper
+               'table',                // Neither are tables
+               '.rellink',             // Common style for "See also:".
+               '.dablink',             // Common style for calling out helpful links at the top
+                                                               // of the article.
+               '.searchaux',           // New class users can use to mark stuff as auxiliary to searches.
+       ];
+
+       /**
+        * WikiTextStructure constructor.
+        * @param ParserOutput $parserOutput
+        */
+       public function __construct( ParserOutput $parserOutput ) {
+               $this->parserOutput = $parserOutput;
+       }
+
+       /**
+        * Get categories in the text.
+        * @return string[]
+        */
+       public function categories() {
+               $categories = [];
+               foreach ( array_keys( $this->parserOutput->getCategories() ) as $key ) {
+                       $categories[] = Category::newFromName( $key )->getTitle()->getText();
+               }
+               return $categories;
+       }
+
+       /**
+        * Get outgoing links.
+        * @return string[]
+        */
+       public function outgoingLinks() {
+               $outgoingLinks = [];
+               foreach ( $this->parserOutput->getLinks() as $linkedNamespace => $namespaceLinks ) {
+                       foreach ( array_keys( $namespaceLinks ) as $linkedDbKey ) {
+                               $outgoingLinks[] =
+                                       Title::makeTitle( $linkedNamespace, $linkedDbKey )->getPrefixedDBkey();
+                       }
+               }
+               return $outgoingLinks;
+       }
+
+       /**
+        * Get templates in the text.
+        * @return string[]
+        */
+       public function templates() {
+               $templates = [];
+               foreach ( $this->parserOutput->getTemplates() as $tNS => $templatesInNS ) {
+                       foreach ( array_keys( $templatesInNS ) as $tDbKey ) {
+                               $templateTitle = Title::makeTitleSafe( $tNS, $tDbKey );
+                               if ( $templateTitle && $templateTitle->exists() ) {
+                                       $templates[] = $templateTitle->getPrefixedText();
+                               }
+                       }
+               }
+               return $templates;
+       }
+
+       /**
+        * Get headings on the page.
+        * @return string[]
+        * First strip out things that look like references.  We can't use HTML filtering because
+        * the references come back as <sup> tags without a class.  To keep from breaking stuff like
+        *  ==Applicability of the strict mass–energy equivalence formula, ''E'' = ''mc''<sup>2</sup>==
+        * we don't remove the whole <sup> tag.  We also don't want to strip the <sup> tag and remove
+        * everything that looks like [2] because, I dunno, maybe there is a band named Word [2] Foo
+        * or something.  Whatever.  So we only strip things that look like <sup> tags wrapping a
+        * reference.  And since the data looks like:
+        *      Reference in heading <sup>&#91;1&#93;</sup><sup>&#91;2&#93;</sup>
+        * we can not really use HtmlFormatter as we have no suitable selector.
+        */
+       public function headings() {
+               $headings = [];
+               $ignoredHeadings = $this->getIgnoredHeadings();
+               foreach ( $this->parserOutput->getSections() as $heading ) {
+                       $heading = $heading[ 'line' ];
+
+                       // Some wikis wrap the brackets in a span:
+                       // http://en.wikipedia.org/wiki/MediaWiki:Cite_reference_link
+                       $heading = preg_replace( '/<\/?span>/', '', $heading );
+                       // Normalize [] so the following regexp would work.
+                       $heading = preg_replace( [ '/&#91;/', '/&#93;/' ], [ '[', ']' ], $heading );
+                       $heading = preg_replace( '/<sup>\s*\[\s*\d+\s*\]\s*<\/sup>/is', '', $heading );
+
+                       // Strip tags from the heading or else we'll display them (escaped) in search results
+                       $heading = trim( Sanitizer::stripAllTags( $heading ) );
+
+                       // Note that we don't take the level of the heading into account - all headings are equal.
+                       // Except the ones we ignore.
+                       if ( !in_array( $heading, $ignoredHeadings ) ) {
+                               $headings[] = $heading;
+                       }
+               }
+               return $headings;
+       }
+
+       /**
+        * Parse a message content into an array. This function is generally used to
+        * parse settings stored as i18n messages (see search-ignored-headings).
+        *
+        * @param string $message
+        * @return string[]
+        */
+       public static function parseSettingsInMessage( $message ) {
+               $lines = explode( "\n", $message );
+               $lines = preg_replace( '/#.*$/', '', $lines ); // Remove comments
+               $lines = array_map( 'trim', $lines );          // Remove extra spaces
+               $lines = array_filter( $lines );               // Remove empty lines
+               return $lines;
+       }
+
+       /**
+        * Get list of heading to ignore.
+        * @return string[]
+        */
+       private function getIgnoredHeadings() {
+               static $ignoredHeadings = null;
+               if ( $ignoredHeadings === null ) {
+                       // FIXME: will be renamed in next patches to search-ignored-headings
+                       $source = wfMessage( 'cirrussearch-ignored-headings' )->inContentLanguage();
+                       $ignoredHeadings = [];
+                       if ( !$source->isDisabled() ) {
+                               $lines = self::parseSettingsInMessage( $source->plain() );
+                               $ignoredHeadings = $lines;               // Now we just have headings!
+                       }
+               }
+               return $ignoredHeadings;
+       }
+
+       /**
+        * Extract parts of the text - opening, main and auxiliary.
+        */
+       private function extractWikitextParts() {
+               if ( !is_null( $this->allText ) ) {
+                       return;
+               }
+               $this->parserOutput->setEditSectionTokens( false );
+               $this->parserOutput->setTOCEnabled( false );
+               $text = $this->parserOutput->getText();
+               if ( strlen( $text ) == 0 ) {
+                       $this->allText = "";
+                       // empty text - nothing to seek here
+                       return;
+               }
+               $opening = null;
+
+               $this->openingText = $this->extractHeadingBeforeFirstHeading( $text );
+
+               // Add extra spacing around break tags so text crammed together like<br>this
+               // doesn't make one word.
+               $text = str_replace( '<br', "\n<br", $text );
+
+               $formatter = new HtmlFormatter( $text );
+
+               // Strip elements from the page that we never want in the search text.
+               $formatter->remove( $this->excludedElementSelectors );
+               $formatter->filterContent();
+
+               // Strip elements from the page that are auxiliary text.  These will still be
+               // searched but matches will be ranked lower and non-auxiliary matches will be
+               // preferred in highlighting.
+               $formatter->remove( $this->auxiliaryElementSelectors );
+               $auxiliaryElements = $formatter->filterContent();
+               $this->allText = trim( Sanitizer::stripAllTags( $formatter->getText() ) );
+               foreach ( $auxiliaryElements as $auxiliaryElement ) {
+                       $this->auxText[] =
+                               trim( Sanitizer::stripAllTags( $formatter->getText( $auxiliaryElement ) ) );
+               }
+       }
+
+       /**
+        * Get text before first heading.
+        * @param string $text
+        * @return string|null
+        */
+       private function extractHeadingBeforeFirstHeading( $text ) {
+               $matches = [];
+               if ( !preg_match( '/<h[123456]>/', $text, $matches, PREG_OFFSET_CAPTURE ) ) {
+                       // There isn't a first heading so we interpret this as the article
+                       // being entirely without heading.
+                       return null;
+               }
+               $text = substr( $text, 0, $matches[ 0 ][ 1 ] );
+               if ( !$text ) {
+                       // There isn't any text before the first heading so we declare there isn't
+                       // a first heading.
+                       return null;
+               }
+
+               $formatter = new HtmlFormatter( $text );
+               $formatter->remove( $this->excludedElementSelectors );
+               $formatter->remove( $this->auxiliaryElementSelectors );
+               $formatter->filterContent();
+               $text = trim( Sanitizer::stripAllTags( $formatter->getText() ) );
+
+               if ( !$text ) {
+                       // There isn't any text after filtering before the first heading so we declare
+                       // that there isn't a first heading.
+                       return null;
+               }
+
+               return $text;
+       }
+
+       /**
+        * Get opening text
+        * @return string
+        */
+       public function getOpeningText() {
+               $this->extractWikitextParts();
+               return $this->openingText;
+       }
+
+       /**
+        * Get main text
+        * @return string
+        */
+       public function getMainText() {
+               $this->extractWikitextParts();
+               return $this->allText;
+       }
+
+       /**
+        * Get auxiliary text
+        * @return string[]
+        */
+       public function getAuxiliaryText() {
+               $this->extractWikitextParts();
+               return $this->auxText;
+       }
+}
index 4e8f0df..5c0a9c8 100644 (file)
@@ -145,4 +145,44 @@ class WikitextContentHandler extends TextContentHandler {
                return $fields;
        }
 
+       /**
+        * Extract text of the file
+        * TODO: probably should go to file handler?
+        * @param Title $title
+        * @return string|null
+        */
+       protected function getFileText( Title $title ) {
+               $file = wfLocalFile( $title );
+               if ( $file && $file->exists() ) {
+                       return $file->getHandler()->getEntireText( $file );
+               }
+
+               return null;
+       }
+
+       public function getDataForSearchIndex( WikiPage $page, ParserOutput $parserOutput,
+                                              SearchEngine $engine ) {
+               $fields = parent::getDataForSearchIndex( $page, $parserOutput, $engine );
+
+               $structure = new WikiTextStructure( $parserOutput );
+               $fields['external_link'] = array_keys( $parserOutput->getExternalLinks() );
+               $fields['category'] = $structure->categories();
+               $fields['heading'] = $structure->headings();
+               $fields['outgoing_link'] = $structure->outgoingLinks();
+               $fields['template'] = $structure->templates();
+               // text fields
+               $fields['opening_text'] = $structure->getOpeningText();
+               $fields['text'] = $structure->getMainText(); // overwrites one from ContentHandler
+               $fields['auxiliary_text'] = $structure->getAuxiliaryText();
+
+               $title = $page->getTitle();
+               if ( NS_FILE == $title->getNamespace() ) {
+                       $fileText = $this->getFileText( $title );
+                       if ( $fileText ) {
+                               $fields['file_text'] = $fileText;
+                       }
+               }
+               return $fields;
+       }
+
 }
index 4ce9e62..470086a 100644 (file)
@@ -65,7 +65,7 @@ class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
        /**
         * @param Title $title
         * @return CdnCacheUpdate
-        * @deprecated 1.27
+        * @deprecated since 1.27
         */
        public static function newSimplePurge( Title $title ) {
                return new CdnCacheUpdate( $title->getCdnUrls() );
index 67080b6..538e9bc 100644 (file)
@@ -24,7 +24,7 @@
 /**
  * Generic operation result class for FileRepo-related operations
  * @ingroup FileRepo
- * @deprecated 1.25
+ * @deprecated since 1.25
  */
 class FileRepoStatus extends Status {
 }
index bbf64f6..425a08c 100644 (file)
@@ -1324,7 +1324,7 @@ abstract class File implements IDBAccessObject {
        /**
         * Creates a temp FS file with the same extension and the thumbnail
         * @param string $thumbPath Thumbnail path
-        * @return TempFSFile
+        * @return TempFSFile|null
         */
        protected function makeTransformTmpFile( $thumbPath ) {
                $thumbExt = FileBackend::extensionFromPath( $thumbPath );
index 326f947..e9e757a 100644 (file)
        "config-subscribe-help": "Esta é unha lista de correos de baixo volume usada para anuncios sobre lanzamentos de novas versións, incluíndo avisos de seguridade importantes.\nDebería subscribirse a ela e actualizar a súa instalación MediaWiki cando saian as novas versións.",
        "config-subscribe-noemail": "Intentou subscribirse á lista de correo dos anuncios de novos lanzamentos sen proporcionar o enderezo de correo electrónico.\nDea un enderezo de correo electrónico se quere efectuar a subscrición á lista de correo.",
        "config-pingback": "Compartir datos de esta instalación cos desenvolvedores de MediaWiki",
-       "config-pingback-help": "Se seleccionas esta opción, MediaWiki enviará periodicamente unha mensaxe a https://www.mediawiki.org con datos básicos sobre esta instancia Mediawiki. Estos datos inclúen, por exemplo, o tipo de sistema, versión de PHP e a base de datos escollida. A Fundación Wikimedia comparte estos datos cos desenvolvedores de MediaWiki para axudar a guiar o traballo futuro de desenvolvemento.",
+       "config-pingback-help": "Se seleccionas esta opción, MediaWiki enviará periodicamente unha mensaxe a https://www.mediawiki.org con datos básicos sobre esta instancia Mediawiki. Estos datos inclúen, por exemplo, o tipo de sistema, versión de PHP e a base de datos escollida. A Fundación Wikimedia comparte estos datos cos desenvolvedores de MediaWiki para axudar a guiar o traballo futuro de desenvolvemento. Serán enviados os seguintes datos do seu sistemaː\n<pre>$1</pre>",
        "config-almost-done": "Xa case rematou!\nNeste paso pode saltar o resto da configuración e instalar o wiki agora mesmo.",
        "config-optional-continue": "Facédeme máis preguntas.",
        "config-optional-skip": "Xa estou canso. Instalade o wiki.",
index 0ebfab7..70a43f2 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup Media
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Base media handler class
@@ -36,9 +37,6 @@ abstract class MediaHandler {
         */
        const MAX_ERR_LOG_SIZE = 65535;
 
-       /** @var MediaHandler[] Instance cache with array of MediaHandler */
-       protected static $handlers = [];
-
        /**
         * Get a MediaHandler for a given MIME type from the instance cache
         *
@@ -46,29 +44,8 @@ abstract class MediaHandler {
         * @return MediaHandler|bool
         */
        static function getHandler( $type ) {
-               global $wgMediaHandlers;
-               if ( !isset( $wgMediaHandlers[$type] ) ) {
-                       wfDebug( __METHOD__ . ": no handler found for $type.\n" );
-
-                       return false;
-               }
-               $class = $wgMediaHandlers[$type];
-               if ( !isset( self::$handlers[$class] ) ) {
-                       self::$handlers[$class] = new $class;
-                       if ( !self::$handlers[$class]->isEnabled() ) {
-                               wfDebug( __METHOD__ . ": $class is not enabled\n" );
-                               self::$handlers[$class] = false;
-                       }
-               }
-
-               return self::$handlers[$class];
-       }
-
-       /**
-        * Resets all static caches
-        */
-       public static function resetCache() {
-               self::$handlers = [];
+               return MediaWikiServices::getInstance()
+                       ->getMediaHandlerFactory()->getHandler( $type );
        }
 
        /**
diff --git a/includes/media/MediaHandlerFactory.php b/includes/media/MediaHandlerFactory.php
new file mode 100644 (file)
index 0000000..543dc80
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Media-handling base classes and generic functionality.
+ *
+ * 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
+ * @ingroup Media
+ */
+
+/**
+ * Class to construct MediaHandler objects
+ *
+ * @since 1.28
+ */
+class MediaHandlerFactory {
+
+       /**
+        * Default, MediaWiki core media handlers
+        *
+        * @var array
+        */
+       private static $coreHandlers = [
+               'image/jpeg' => JpegHandler::class,
+               'image/png' => PNGHandler::class,
+               'image/gif' => GIFHandler::class,
+               'image/tiff' => TiffHandler::class,
+               'image/webp' => WebPHandler::class,
+               'image/x-ms-bmp' => BmpHandler::class,
+               'image/x-bmp' => BmpHandler::class,
+               'image/x-xcf' => XCFHandler::class,
+               'image/svg+xml' => SvgHandler::class, // official
+               'image/svg' => SvgHandler::class, // compat
+               'image/vnd.djvu' => DjVuHandler::class, // official
+               'image/x.djvu' => DjVuHandler::class, // compat
+               'image/x-djvu' => DjVuHandler::class, // compat
+       ];
+
+       /**
+        * @var array
+        */
+       private $registry;
+
+       /**
+        * Instance cache of MediaHandler objects by mimetype
+        *
+        * @var MediaHandler[]
+        */
+       private $handlers;
+
+       public function __construct( array $registry ) {
+               $this->registry = $registry + self::$coreHandlers;
+       }
+
+       protected function getHandlerClass( $type ) {
+               if ( isset( $this->registry[$type] ) ) {
+                       return $this->registry[$type];
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * @param string $type mimetype
+        * @return bool|MediaHandler
+        */
+       public function getHandler( $type ) {
+               if ( isset( $this->handlers[$type] ) ) {
+                       return $this->handlers[$type];
+               }
+
+               $class = $this->getHandlerClass( $type );
+               if ( $class !== false ) {
+                       /** @var MediaHandler $handler */
+                       $handler = new $class;
+                       if ( !$handler->isEnabled() ) {
+                               wfDebug( __METHOD__ . ": $class is not enabled\n" );
+                               $handler = false;
+                       }
+               } else {
+                       wfDebug( __METHOD__ . ": no handler found for $type.\n" );
+                       $handler = false;
+               }
+
+               $this->handlers[$type] = $handler;
+               return $handler;
+       }
+}
index 26f3356..1083393 100644 (file)
@@ -278,7 +278,7 @@ class ObjectCache {
         * @param array $params [optional] Array key 'fallback' for $fallback.
         * @param int|string $fallback Fallback cache, e.g. (CACHE_NONE, "hash") (since 1.24)
         * @return BagOStuff
-        * @deprecated 1.27
+        * @deprecated since 1.27
         */
        public static function newAccelerator( $params = [], $fallback = null ) {
                if ( $fallback === null ) {
index 2a6f88c..6396aaa 100644 (file)
@@ -1438,14 +1438,13 @@ class Article implements Page {
                        : 'revision-info';
 
                $outputPage = $context->getOutput();
-               $outputPage->addSubtitle( "<div id=\"mw-{$infomsg}\">" .
+               $revisionInfo = "<div id=\"mw-{$infomsg}\">" .
                        $context->msg( $infomsg, $td )
                                ->rawParams( $userlinks )
                                ->params( $revision->getId(), $tddate, $tdtime, $revision->getUserText() )
                                ->rawParams( Linker::revComment( $revision, true, true ) )
                                ->parse() .
-                       "</div>"
-               );
+                       "</div>";
 
                $lnk = $current
                        ? $context->msg( 'currentrevisionlink' )->escaped()
@@ -1517,10 +1516,12 @@ class Article implements Page {
                        $cdel .= ' ';
                }
 
-               $outputPage->addSubtitle( "<div id=\"mw-revision-nav\">" . $cdel .
+               // the outer div is need for styling the revision info and nav in MobileFrontend
+               $outputPage->addSubtitle( "<div class=\"mw-revision\">" . $revisionInfo .
+                       "<div id=\"mw-revision-nav\">" . $cdel .
                        $context->msg( 'revision-nav' )->rawParams(
                                $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff
-                       )->escaped() . "</div>" );
+                       )->escaped() . "</div></div>" );
        }
 
        /**
index 26028b1..bded84d 100644 (file)
@@ -1043,14 +1043,16 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @since 1.19
         * @param ParserOptions $parserOptions ParserOptions to use for the parse operation
-        * @param null|int $oldid Revision ID to get the text from, passing null or 0 will
-        *   get the current revision (default value)
-        *
-        * @return ParserOutput|bool ParserOutput or false if the revision was not found
+        * @param null|int      $oldid Revision ID to get the text from, passing null or 0 will
+        *                             get the current revision (default value)
+        * @param bool          $forceParse Force reindexing, regardless of cache settings
+        * @return bool|ParserOutput ParserOutput or false if the revision was not found
         */
-       public function getParserOutput( ParserOptions $parserOptions, $oldid = null ) {
+       public function getParserOutput( ParserOptions $parserOptions, $oldid = null,
+                                        $forceParse = false ) {
 
-               $useParserCache = $this->shouldCheckParserCache( $parserOptions, $oldid );
+               $useParserCache =
+                       ( !$forceParse ) && $this->shouldCheckParserCache( $parserOptions, $oldid );
                wfDebug( __METHOD__ .
                        ': using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
                if ( $parserOptions->getStubThreshold() ) {
@@ -2927,6 +2929,8 @@ class WikiPage implements Page, IDBAccessObject {
                        ],
                        __METHOD__
                );
+               // Save this so we can pass it to the ArticleDeleteComplete hook.
+               $archivedRevisionCount = $dbw->affectedRows();
 
                // Now that it's safely backed up, delete it
                $dbw->delete( 'page', [ 'page_id' => $id ], __METHOD__ );
@@ -2957,7 +2961,7 @@ class WikiPage implements Page, IDBAccessObject {
                $this->doDeleteUpdates( $id, $content );
 
                Hooks::run( 'ArticleDeleteComplete',
-                       [ &$this, &$user, $reason, $id, $content, $logEntry ] );
+                       [ &$this, &$user, $reason, $id, $content, $logEntry, $archivedRevisionCount ] );
                $status->value = $logid;
 
                // Show log excerpt on 404 pages rather than just a link
index d787edb..32daeed 100644 (file)
@@ -25,7 +25,7 @@
  * Class for handling function-scope profiling
  *
  * @since 1.22
- * @deprecated 1.25 No-op now
+ * @deprecated since 1.25 No-op now
  */
 class ProfileSection {
        /**
index 50a77ec..cc71630 100644 (file)
@@ -42,7 +42,7 @@ function wfGetRusage() {
 /**
  * Begin profiling of a function
  * @param string $functionname Name of the function we will profile
- * @deprecated 1.25
+ * @deprecated since 1.25
  */
 function wfProfileIn( $functionname ) {
 }
@@ -50,7 +50,7 @@ function wfProfileIn( $functionname ) {
 /**
  * Stop profiling of a function
  * @param string $functionname Name of the function we have profiled
- * @deprecated 1.25
+ * @deprecated since 1.25
  */
 function wfProfileOut( $functionname = 'missing' ) {
 }
index 6b755d7..2816126 100644 (file)
@@ -255,6 +255,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                                $this->{$member}[$key] = (array)$value;
                                        }
                                        break;
+                               case 'deprecated':
+                                       $this->deprecated = $option;
+                                       break;
                                // Lists of strings
                                case 'dependencies':
                                case 'messages':
@@ -352,7 +355,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         */
        public function getScript( ResourceLoaderContext $context ) {
                $files = $this->getScriptFiles( $context );
-               return $this->readScriptFiles( $files );
+               return $this->getDeprecationInformation() . $this->readScriptFiles( $files );
        }
 
        /**
index 59f9a63..48e7937 100644 (file)
@@ -82,6 +82,11 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         */
        protected $config;
 
+       /**
+        * @var array|bool
+        */
+       protected $deprecated = false;
+
        /**
         * @var LoggerInterface
         */
@@ -130,6 +135,28 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
                return $wgContLang->getDir() !== $context->getDirection();
        }
 
+       /**
+        * Get JS representing deprecation information for the current module if available
+        *
+        * @return string JavaScript code
+        */
+       protected function getDeprecationInformation() {
+               $deprecationInfo = $this->deprecated;
+               if ( $deprecationInfo ) {
+                       $name = $this->getName();
+                       $warning = 'This page is using the deprecated ResourceLoader module "' . $name . '".';
+                       if ( !is_bool( $deprecationInfo ) && isset( $deprecationInfo['message'] ) ) {
+                               $warning .= "\n" . $deprecationInfo['message'];
+                       }
+                       return Xml::encodeJsCall(
+                               'mw.log.warn',
+                               [ $warning ]
+                       );
+               } else {
+                       return '';
+               }
+       }
+
        /**
         * Get all JS for this module for a given language and skin.
         * Includes all relevant JS except loader scripts.
index 8d4f263..8f58040 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 /**
- * ResourceLoader module for user customizations.
- *
  * 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
@@ -23,7 +21,7 @@
  */
 
 /**
- * Module for user customizations
+ * Module for user customizations scripts
  */
 class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
 
@@ -31,8 +29,6 @@ class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
        protected $targets = [ 'desktop', 'mobile' ];
 
        /**
-        * Get list of pages used by this module
-        *
         * @param ResourceLoaderContext $context
         * @return array List of pages
         */
@@ -52,35 +48,20 @@ class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
                        $pages["$userPage/" . $context->getSkin() . '.js'] = [ 'type' => 'script' ];
                }
 
-               if ( $config->get( 'AllowUserCss' ) ) {
-                       $pages["$userPage/common.css"] = [ 'type' => 'style' ];
-                       $pages["$userPage/" . $context->getSkin() . '.css'] = [ 'type' => 'style' ];
-               }
-
-               $useSiteJs = $config->get( 'UseSiteJs' );
-               $useSiteCss = $config->get( 'UseSiteCss' );
                // User group pages are maintained site-wide and enabled with site JS/CSS.
-               if ( $useSiteJs || $useSiteCss ) {
+               if ( $config->get( 'UseSiteJs' ) ) {
                        foreach ( $user->getEffectiveGroups() as $group ) {
                                if ( $group == '*' ) {
                                        continue;
                                }
-                               if ( $useSiteJs ) {
-                                       $pages["MediaWiki:Group-$group.js"] = [ 'type' => 'script' ];
-                               }
-                               if ( $useSiteCss ) {
-                                       $pages["MediaWiki:Group-$group.css"] = [ 'type' => 'style' ];
-                               }
+                               $pages["MediaWiki:Group-$group.js"] = [ 'type' => 'script' ];
                        }
                }
 
-               // Hack for bug 26283: if we're on a preview page for a CSS/JS page,
-               // we need to exclude that page from this module. In that case, the excludepage
-               // parameter will be set to the name of the page we need to exclude.
+               // Hack for T28283: Allow excluding pages for preview on a CSS/JS page.
+               // The excludepage parameter is set by OutputPage.
                $excludepage = $context->getRequest()->getVal( 'excludepage' );
                if ( isset( $pages[$excludepage] ) ) {
-                       // This works because $excludepage is generated with getPrefixedDBkey(),
-                       // just like the keys in $pages[] above
                        unset( $pages[$excludepage] );
                }
 
@@ -95,4 +76,11 @@ class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
        public function getGroup() {
                return 'user';
        }
+
+       /**
+        * @return array
+        */
+       public function getDependencies( ResourceLoaderContext $context = null ) {
+               return [ 'user.styles' ];
+       }
 }
diff --git a/includes/resourceloader/ResourceLoaderUserStylesModule.php b/includes/resourceloader/ResourceLoaderUserStylesModule.php
new file mode 100644 (file)
index 0000000..8d8e008
--- /dev/null
@@ -0,0 +1,86 @@
+<?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
+ * @author Trevor Parscal
+ * @author Roan Kattouw
+ */
+
+/**
+ * Module for user customizations styles
+ */
+class ResourceLoaderUserStylesModule extends ResourceLoaderWikiModule {
+
+       protected $origin = self::ORIGIN_USER_INDIVIDUAL;
+       protected $targets = [ 'desktop', 'mobile' ];
+
+       /**
+        * @param ResourceLoaderContext $context
+        * @return array List of pages
+        */
+       protected function getPages( ResourceLoaderContext $context ) {
+               $config = $this->getConfig();
+               $user = $context->getUserObj();
+               if ( $user->isAnon() ) {
+                       return [];
+               }
+
+               // Use localised/normalised variant to ensure $excludepage matches
+               $userPage = $user->getUserPage()->getPrefixedDBkey();
+               $pages = [];
+
+               if ( $config->get( 'AllowUserCss' ) ) {
+                       $pages["$userPage/common.css"] = [ 'type' => 'style' ];
+                       $pages["$userPage/" . $context->getSkin() . '.css'] = [ 'type' => 'style' ];
+               }
+
+               // User group pages are maintained site-wide and enabled with site JS/CSS.
+               if ( $config->get( 'UseSiteCss' ) ) {
+                       foreach ( $user->getEffectiveGroups() as $group ) {
+                               if ( $group == '*' ) {
+                                       continue;
+                               }
+                               $pages["MediaWiki:Group-$group.css"] = [ 'type' => 'style' ];
+                       }
+               }
+
+               // Hack for T28283: Allow excluding pages for preview on a CSS/JS page.
+               // The excludepage parameter is set by OutputPage.
+               $excludepage = $context->getRequest()->getVal( 'excludepage' );
+               if ( isset( $pages[$excludepage] ) ) {
+                       unset( $pages[$excludepage] );
+               }
+
+               return $pages;
+       }
+
+       /**
+        * @return string
+        */
+       public function getType() {
+               return self::LOAD_STYLES;
+       }
+
+       /**
+        * Get group name
+        *
+        * @return string
+        */
+       public function getGroup() {
+               return 'user';
+       }
+}
index 9168d64..c2ccca0 100644 (file)
@@ -659,7 +659,7 @@ abstract class SearchEngine {
         * Create a search field definition.
         * Specific search engines should override this method to create search fields.
         * @param string $name
-        * @param int    $type
+        * @param int    $type One of the types in SearchIndexField::INDEX_TYPE_*
         * @return SearchIndexField
         * @since 1.28
         */
index a4116ae..2f8a113 100644 (file)
@@ -35,8 +35,8 @@ class SiteSQLStore {
         * @note This does not return an instance of SiteSQLStore!
         *
         * @since 1.21
-        * @deprecated 1.27 use MediaWikiServices::getSiteStore() or MediaWikiServices::getSiteLookup()
-        *             instead.
+        * @deprecated since 1.27 use MediaWikiServices::getSiteStore()
+        *             or MediaWikiServices::getSiteLookup() instead.
         *
         * @param null $sitesTable IGNORED
         * @param null $cache IGNORED
index 64d2f8b..d473251 100644 (file)
@@ -1566,56 +1566,4 @@ abstract class Skin extends ContextSource {
                return $result;
        }
 
-       /** @deprecated in 1.21 */
-       public function commentBlock( $comment, $title = null, $local = false, $wikiId = null ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return Linker::commentBlock( $comment, $title, $local, $wikiId );
-       }
-
-       /** @deprecated in 1.21 */
-       public function generateRollback(
-               $rev,
-               IContextSource $context = null,
-               $options = [ 'verify' ]
-       ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return Linker::generateRollback( $rev, $context, $options );
-       }
-
-       /** @deprecated in 1.21 */
-       public function link( $target, $html = null, $customAttribs = [], $query = [], $options = [] ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return Linker::link( $target, $html, $customAttribs, $query, $options );
-       }
-
-       /** @deprecated in 1.21 */
-       public function linkKnown(
-               $target,
-               $html = null,
-               $customAttribs = [],
-               $query = [],
-               $options = [ 'known', 'noclasses' ]
-       ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return Linker::linkKnown( $target, $html, $customAttribs, $query, $options );
-       }
-
-       /** @deprecated in 1.21 */
-       public function userLink( $userId, $userName, $altUserName = false ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return Linker::userLink( $userId, $userName, $altUserName );
-       }
-
-       /** @deprecated in 1.21 */
-       public function userToolLinks(
-               $userId,
-               $userText,
-               $redContribsWhenNoEdits = false,
-               $flags = 0,
-               $edits = null
-       ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return Linker::userToolLinks( $userId, $userText, $redContribsWhenNoEdits, $flags, $edits );
-       }
-
 }
index a475f05..3e89686 100644 (file)
@@ -25,7 +25,7 @@
  * Let users reset tokens like the watchlist token.
  *
  * @ingroup SpecialPage
- * @deprecated 1.26
+ * @deprecated since 1.26
  */
 class SpecialResetTokens extends FormSpecialPage {
        private $tokensList;
index 0ef6af1..a0e3096 100644 (file)
@@ -336,7 +336,7 @@ class SpecialUpload extends SpecialPage {
         * @param string $message HTML message to be passed to mainUploadForm
         */
        protected function showRecoverableUploadError( $message ) {
-               $sessionKey = $this->mUpload->stashSession();
+               $sessionKey = $this->mUpload->stashFile()->getFileKey();
                $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . "</h2>\n" .
                        '<div class="error">' . $message . "</div>\n";
 
@@ -365,7 +365,7 @@ class SpecialUpload extends SpecialPage {
                        return false;
                }
 
-               $sessionKey = $this->mUpload->stashSession();
+               $sessionKey = $this->mUpload->stashFile()->getFileKey();
 
                // Add styles for the warning, reused from the live preview
                $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' );
index f4bb7ec..5320673 100644 (file)
@@ -960,8 +960,6 @@ abstract class UploadBase {
         * @return UploadStashFile Stashed file
         */
        public function stashFile( User $user = null ) {
-               // was stashSessionFile
-
                $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash( $user );
                $file = $stash->stashFile( $this->mTempPath, $this->getSourceType() );
                $this->mLocalFile = $file;
@@ -973,19 +971,23 @@ abstract class UploadBase {
         * Stash a file in a temporary directory, returning a key which can be used
         * to find the file again. See stashFile().
         *
+        * @deprecated since 1.28
         * @return string File key
         */
        public function stashFileGetKey() {
+               wfDeprecated( __METHOD__, '1.28' );
                return $this->stashFile()->getFileKey();
        }
 
        /**
         * alias for stashFileGetKey, for backwards compatibility
         *
+        * @deprecated since 1.28
         * @return string File key
         */
        public function stashSession() {
-               return $this->stashFileGetKey();
+               wfDeprecated( __METHOD__, '1.28' );
+               return $this->stashFile()->getFileKey();
        }
 
        /**
index 1276842..908c8aa 100644 (file)
@@ -161,14 +161,6 @@ class UploadFromStash extends UploadBase {
                return $this->mLocalFile;
        }
 
-       /**
-        * This should return the key instead of the UploadStashFile instance, for backward compatibility.
-        * @return string
-        */
-       public function stashSession() {
-               return $this->stashFile()->getFileKey();
-       }
-
        /**
         * Remove a temporarily kept file stashed by saveTempUploadedFile().
         * @return bool Success
index 39507af..c46836b 100644 (file)
@@ -3018,7 +3018,7 @@ class User implements IDBAccessObject {
         * @return string|bool User's current value for the option, or false if this option is disabled.
         * @see resetTokenFromOption()
         * @see getOption()
-        * @deprecated 1.26 Applications should use the OAuth extension
+        * @deprecated since 1.26 Applications should use the OAuth extension
         */
        public function getTokenFromOption( $oname ) {
                global $wgHiddenPrefs;
index 916e2f8..de52cd9 100644 (file)
@@ -14,6 +14,9 @@
  *     $gen->generateAutoload();
  */
 class AutoloadGenerator {
+       const FILETYPE_JSON = 'json';
+       const FILETYPE_PHP = 'php';
+
        /**
         * @var string Root path of the project being scanned for classes
         */
@@ -122,11 +125,11 @@ class AutoloadGenerator {
         * Updates the AutoloadClasses field at the given
         * filename.
         *
-        * @param {string} $filename Filename of JSON
+        * @param string $filename Filename of JSON
         *  extension/skin registration file
+        * @return string Updated Json of the file given as the $filename parameter
         */
        protected function generateJsonAutoload( $filename ) {
-               require_once __DIR__ . '/../../includes/json/FormatJson.php';
                $key = 'AutoloadClasses';
                $json = FormatJson::decode( file_get_contents( $filename ), true );
                unset( $json[$key] );
@@ -148,10 +151,8 @@ class AutoloadGenerator {
                // Sorting the list of autoload classes.
                ksort( $json[$key] );
 
-               // Update file, using constants for the required
-               // formatting.
-               file_put_contents( $filename,
-                       FormatJson::encode( $json, true ) . "\n" );
+               // Return the whole JSON file
+               return FormatJson::encode( $json, true ) . "\n";
        }
 
        /**
@@ -198,8 +199,7 @@ class AutoloadGenerator {
                }
 
                $output = implode( "\n\t", $content );
-               file_put_contents(
-                       $filename,
+               return
                        <<<EOD
 <?php
 // This file is generated by $commandName, do not adjust manually
@@ -210,36 +210,60 @@ global \${$this->variableName};
        {$output}
 ];
 
-EOD
-               );
+EOD;
 
        }
 
        /**
-        * Write out all known classes to autoload.php, extension.json, or skin.json in
-        * the provided basedir
+        * Returns all known classes as a string, which can be used to put into a target
+        * file (e.g. extension.json, skin.json or autoload.php)
         *
         * @param string $commandName Value used in file comment to direct
         *  developers towards the appropriate way to update the autoload.
+        * @return string
         */
-       public function generateAutoload( $commandName = 'AutoloadGenerator' ) {
+       public function getAutoload( $commandName = 'AutoloadGenerator' ) {
 
                // We need to check whether an extenson.json or skin.json exists or not, and
                // incase it doesn't, update the autoload.php file.
 
-               $jsonFilename = null;
-               if ( file_exists( $this->basepath . "/extension.json" ) ) {
-                       $jsonFilename = $this->basepath . "/extension.json";
-               } elseif ( file_exists( $this->basepath . "/skin.json" ) ) {
-                       $jsonFilename = $this->basepath . "/skin.json";
-               }
+               $fileinfo = $this->getTargetFileinfo();
 
-               if ( $jsonFilename !== null ) {
-                       $this->generateJsonAutoload( $jsonFilename );
+               if ( $fileinfo['type'] === AutoloadGenerator::FILETYPE_JSON ) {
+                       return $this->generateJsonAutoload( $fileinfo['filename'] );
                } else {
-                       $this->generatePHPAutoload( $commandName, $this->basepath . '/autoload.php' );
+                       return $this->generatePHPAutoload( $commandName, $fileinfo['filename'] );
+               }
+       }
+
+       /**
+        * Returns the filename of the extension.json of skin.json, if there's any, or
+        * otherwise the path to the autoload.php file in an array as the "filename"
+        * key and with the type (AutoloadGenerator::FILETYPE_JSON or AutoloadGenerator::FILETYPE_PHP)
+        * of the file as the "type" key.
+        *
+        * @return array
+        */
+       public function getTargetFileinfo() {
+               $fileinfo = [
+                       'filename' => $this->basepath . '/autoload.php',
+                       'type' => AutoloadGenerator::FILETYPE_PHP
+               ];
+               if ( file_exists( $this->basepath . '/extension.json' ) ) {
+                       $fileinfo = [
+                               'filename' => $this->basepath . '/extension.json',
+                               'type' => AutoloadGenerator::FILETYPE_JSON
+                       ];
+               } elseif ( file_exists( $this->basepath . '/skin.json' ) ) {
+                       $fileinfo = [
+                               'filename' => $this->basepath . '/skin.json',
+                               'type' => AutoloadGenerator::FILETYPE_JSON
+                       ];
                }
+
+               return $fileinfo;
        }
+
        /**
         * Ensure that Unix-style path separators ("/") are used in the path.
         *
@@ -249,6 +273,24 @@ EOD
        protected static function normalizePathSeparator( $path ) {
                return str_replace( '\\', '/', $path );
        }
+
+       /**
+        * Initialize the source files and directories which are used for the MediaWiki default
+        * autoloader in {mw-base-dir}/autoload.php including:
+        *  * includes/
+        *  * languages/
+        *  * maintenance/
+        *  * mw-config/
+        *  * /*.php
+        */
+       public function initMediaWikiDefault() {
+               foreach ( [ 'includes', 'languages', 'maintenance', 'mw-config' ] as $dir ) {
+                       $this->readDir( $this->basepath . '/' . $dir );
+               }
+               foreach ( glob( $this->basepath . '/*.php' ) as $file ) {
+                       $this->readFile( $file );
+               }
+       }
 }
 
 /**
index 350bc20..dfd469c 100644 (file)
@@ -63,7 +63,8 @@
                        "Jdforrester",
                        "Alaa",
                        "Izoozo",
-                       "علاء"
+                       "علاء",
+                       "Hhaboh162002"
                ]
        },
        "tog-underline": "سطر تحت الوصلات:",
        "savearticle": "احفظ الصفحة",
        "savechanges": "احفظ التغييرات",
        "publishpage": "نشر الصفحة",
-       "publishchanges": "انشر التغييرات",
+       "publishchanges": "نشر التغييرات",
        "preview": "عرض مسبق",
        "showpreview": "أظهر معاينة",
        "showdiff": "عرض التغييرات",
        "whatlinkshere-prev": "{{PLURAL:$1|السابق|ال$1 السابقة}}",
        "whatlinkshere-next": "{{PLURAL:$1|التالية|ال$1 التالية}}",
        "whatlinkshere-links": "وصلات",
-       "whatlinkshere-hideredirs": "$1 Ø§Ù\84تحÙ\88Ù\8aÙ\84ات",
-       "whatlinkshere-hidetrans": "$1 Ø§Ù\84تضÙ\85Ù\8aÙ\86ات",
-       "whatlinkshere-hidelinks": "$1 الوصلات",
+       "whatlinkshere-hideredirs": "$1 تحويلات",
+       "whatlinkshere-hidetrans": "$1 تضمينات",
+       "whatlinkshere-hidelinks": "$1 وصلات",
        "whatlinkshere-hideimages": "$1 وصلات الملفات",
        "whatlinkshere-filters": "مرشحات",
        "whatlinkshere-submit": "اذهب",
index 5157ae8..20a026c 100644 (file)
        "action-applychangetags": "дадаваньне метак пры рэдагаваньні",
        "action-changetags": "дадаваньне і выдаленьне адвольных метак да асобных вэрсіяў і запісаў у журнале падзеяў",
        "action-deletechangetags": "выдаленьне метак з базы зьвестак",
+       "action-purge": "ачыстку кэшу гэтай старонкі",
        "nchanges": "$1 {{PLURAL:$1|зьмена|зьмены|зьменаў}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|з апошняга візыту}}",
        "enhancedrc-history": "гісторыя",
        "randomrootpage": "Выпадковая карэнная старонка",
        "log-action-filter-block": "Тып блякаваньня:",
        "log-action-filter-delete": "Тып выдаленьня:",
+       "log-action-filter-import": "Тып імпарту:",
        "changecredentials": "Зьмена ўліковых зьвестак",
        "removecredentials": "Выдаленьне ўліковых зьвестак",
        "removecredentials-submit": "Выдаліць уліковыя зьвесткі",
index c0154f9..aa16b7a 100644 (file)
        "action-applychangetags": "přidávat značky k vlastním změnám",
        "action-changetags": "přidávat libovolné značky na jednotlivé revize a protokolovací záznamy a odebírat je",
        "action-deletechangetags": "mazat značky z databáze",
+       "action-purge": "vyčistit vyrovnávací paměť této stránky",
        "nchanges": "$1 {{PLURAL:$1|změna|změny|změn}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|od poslední návštěvy}}",
        "enhancedrc-history": "historie",
index e8beffd..2322551 100644 (file)
        "april": "Nisane",
        "may_long": "Gulane",
        "june": "Heziran",
-       "july": "Temuz",
+       "july": "Temuze",
        "august": "Tebaxe",
        "september": "Keşkelun",
-       "october": "Cetan",
-       "november": "Kelverdan",
+       "october": "Tışrino Verên",
+       "november": "Tışrino Peyên",
        "december": "Kanun",
        "january-gen": "Çele",
        "february-gen": "Sıbate",
        "morenotlisted": "Vêşi lista nêbi...",
        "mypage": "Pele",
        "mytalk": "Mesac",
-       "anontalk": "Vatenayış",
+       "anontalk": "Werênayış",
        "navigation": "Pusula",
        "and": "&#32;u",
        "qbfind": "Bıvêne",
        "history": "Tarixê pele",
        "history_short": "Tarix",
        "updatedmarker": "cıkewtena mına peyêne ra dıme biyo rocane",
-       "printableversion": "Versiyonê nusterin",
+       "printableversion": "Asayışê çapkerdışi",
        "permalink": "Gıreyo daimi",
        "print": "Çap ke",
        "view": "Bıvêne",
        "copyright": "Zerrekacı $1 bındı not biya.",
        "copyrightpage": "{{ns:project}}:Heqa telifi",
        "currentevents": "Hediseyê rocaneyi",
-       "currentevents-url": "Project:Rocani hadisey",
+       "currentevents-url": "Project:Hediseyê rocaneyi",
        "disclaimers": "Redê mesuliyeti",
        "disclaimerpage": "Project:Reddê mesuliyetê bıngey",
        "edithelp": "Peştdariya vurnayışi",
        "policy-url": "Project:Terzê hereketi",
        "portal": "Portalê cemaeti",
        "portal-url": "Project:Portalê cemaeti",
-       "privacy": "Politikay Nımnayışi",
-       "privacypage": "Project:Xısusiyetê nımtışi",
+       "privacy": "Politikaya nımıteyiye",
+       "privacypage": "Project:Xısusiyetê nımıtışi",
        "badaccess": "Xeta mısadey",
        "badaccess-group0": "Heqa şıma çıniya, karo ke şıma waşt, bıkerê.",
        "badaccess-groups": "No fealiyeto ke şıma waşt, tenya karberanê {{PLURAL:$2|grubi|gruban ra yewi}} rê akerdeyo: $1.",
        "categoriesfrom": "Kategoriyê ke be ninan dest pêkenê, bımocne:",
        "deletedcontributions": "İştırakê karberi esterdi",
        "deletedcontributions-title": "İştırakê karberi esterdi",
-       "sp-deletedcontributions-contribs": "iştıraqi",
+       "sp-deletedcontributions-contribs": "iştiraki",
        "linksearch": "Gıreyê teberi cı geyrê",
        "linksearch-pat": "bıgêr motif:",
        "linksearch-ns": "Heruna nameyi:",
        "blanknamespace": "(Ser)",
        "contributions": "İştiraqê {{GENDER:$1|karber}}i",
        "contributions-title": "Dekerdenê karber de $1",
-       "mycontris": "İştıraqi",
-       "anoncontribs": "İştıraqi",
+       "mycontris": "İştıraki",
+       "anoncontribs": "İştıraki",
        "contribsub2": "Qandê {{GENDER:$3|$1}} ($2)",
        "contributions-userdoesnotexist": "Hesabê karberi \"$1\" qeyd nêbiyo.",
        "nocontribs": "Ena kriteriya de vurnayîş çini yo.",
        "sp-contributions-deleted": "iştırakê karberi esterdi",
        "sp-contributions-uploads": "barkerdey",
        "sp-contributions-logs": "qeydi",
-       "sp-contributions-talk": "Vacenayış",
+       "sp-contributions-talk": "werênayış",
        "sp-contributions-userrights": "idareyê heqanê karberan",
        "sp-contributions-blocked-notice": "verniyê no/na karber/e geriyayo/a\nqê referansi qeydê vernigrewtışi cêr de eşkera biyo:",
        "sp-contributions-blocked-notice-anon": "Eno adresê IPi bloke biyo.\nCıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:",
        "ipb-unblock-addr": "$1 a bik",
        "ipb-unblock": "Yew adresê IPî ya zi nameyê karberî blok bike",
        "ipb-blocklist": "Blokî ke hama estê ey bivîne",
-       "ipb-blocklist-contribs": "Qandê {{GENDER:$1|}} ra iştıraqi",
+       "ipb-blocklist-contribs": "İştirakê {{GENDER:$1|$1}}`i",
        "ipb-blocklist-duration-left": "$1 vet",
        "unblockip": "Hesabê karberî a bike",
        "unblockiptext": "Cıreştışê nuştışê IP ya zi karberio ke ver ra gêriyayo, seba peyser barkerdışi dey rê formê cêrêni bıgurenên.",
        "blocklink": "kılit ke",
        "unblocklink": "bloki wedare",
        "change-blocklink": "kılitkerdışi bıvurne",
-       "contribslink": "iştıraqi",
+       "contribslink": "iştıraki",
        "emaillink": "e-poste bırışe",
        "autoblocker": "Şıma otomatikmen kılit biy, çıke adresa şımaya ''IP''y terefê \"[[User:$1|$1]]\" gureniyena.\nSebebê kılitbiyayışê $1'i \"$2\"o",
        "blocklogpage": "Qeydê astengi",
        "tooltip-n-portal": "Heqa proceyi de, çı şenay bıkerê, çı koti vêniyeno",
        "tooltip-n-currentevents": "Vurnayışanê peyênan de melumatê pey bıvêne",
        "tooltip-n-recentchanges": "Wiki de lista vurnayışanê peyênan",
-       "tooltip-n-randompage": "Perake raşt amé",
+       "tooltip-n-randompage": "Pelê da raştameyiye bar ke",
        "tooltip-n-help": "Cayê peştigırewtışi",
        "tooltip-t-whatlinkshere": "Lista pelanê wikiya pêroina ke tiya gırê bena",
        "tooltip-t-recentchangeslinked": "Vurnayışê peyênê pelanê ke ena pela ra gırê biyê",
index 88aa28b..8d7cb8b 100644 (file)
        "logdelete-selected": "{{PLURAL:$1|Événement d'historique sélectionné|Événements d'historique sélectionnés}} :",
        "revdelete-text-text": "Les révisions supprimées continueront à apparaître dans l’historique de la page, mais une partie de leur contenu sera inaccessible au public.",
        "revdelete-text-file": "Les versions de fichier supprimées continueront à apparaître dans l’historique des fichiers, mais une partie de leur contenu sera indisponible au public.",
-       "logdelete-text": "Les évènements du journal supprimés continueront à apparaître dans les journaux, mais une partie de leur contenu sera indisponible au public.",
+       "logdelete-text": "Les évènements supprimés du journal continueront à apparaître dans les journaux, mais une partie de leur contenu sera indisponible au public.",
        "revdelete-text-others": "Les autres administrateurs seront toujours en mesure d'accéder au contenu caché et le restaurer, à moins que des restrictions supplémentaires soient fixées.",
        "revdelete-confirm": "Confirmez que vous voulez effectuer cette action, que vous en comprenez les conséquences, et que vous le faites en accord avec [[{{MediaWiki:Policy-url}}|les règles]].",
        "revdelete-suppress-text": "La suppression ne doit être utilisée <strong>que</strong> dans les cas suivants :\n* informations potentiellement diffamatoires\n* informations personnelles inappropriées\n*: <em>adresse, numéro de téléphone, numéro de sécurité sociale, …</em>",
        "revdelete-radio-same": "(ne pas changer)",
        "revdelete-radio-set": "Masqué",
        "revdelete-radio-unset": "Visible",
-       "revdelete-suppress": "Masquer également les données pour les administrateurs",
+       "revdelete-suppress": "Supprimer également les données des administrateurs",
        "revdelete-unsuppress": "Enlever les restrictions sur les versions restaurées",
        "revdelete-log": "Motif :",
        "revdelete-submit": "Appliquer {{PLURAL:$1|à la révision sélectionnée|aux révisions sélectionnées}}",
        "revdelete-no-change": "'''Attention :''' L'élément daté du $1 à $2 a déjà les paramètres de visibilité demandés.",
        "revdelete-concurrent-change": "Erreur lors de la modification de l'élément daté du $1 à $2 : son statut a été changé par quelqu'un d'autre pendant que vous le modifiez.\nVérifiez les journaux.",
        "revdelete-only-restricted": "Erreur lors de la suppression de l'entrée datée du $1 à $2 : vous ne pouvez pas supprimer ces éléments aux administrateurs sans également sélectionner les autres options de suppression.",
-       "revdelete-reason-dropdown": "* Raisons courantes de suppression :\n** Violation des droits d'auteurs ;\n** Commentaires ou renseignements personnels inappropriés ;\n** Informations potentiellement diffamatoires.",
+       "revdelete-reason-dropdown": "* Raisons courantes de suppression \n** Violation des droits d'auteurs \n** Commentaires ou renseignements personnels inappropriés \n** Nom d'utilisateur inapproprié\n** Informations potentiellement diffamatoires",
        "revdelete-otherreason": "Autre raison / raison supplémentaire :",
        "revdelete-reasonotherlist": "Autre raison",
        "revdelete-edit-reasonlist": "Modifier les motifs fréquents de suppression",
        "prefs-editwatchlist-clear": "Effacer la liste de suivi",
        "prefs-watchlist-days": "Nombre de jours à afficher dans la liste de suivi :",
        "prefs-watchlist-days-max": "(maximum $1 jour{{PLURAL:$1||s}})",
-       "prefs-watchlist-edits": "Nombre de modifications à afficher dans la liste de suivi étendue :",
+       "prefs-watchlist-edits": "Nombre maximum de modifications à afficher dans la liste de suivi étendue :",
        "prefs-watchlist-edits-max": "Nombre maximum : 1000",
        "prefs-watchlist-token": "Jeton pour la liste de suivi :",
        "prefs-misc": "Préférences diverses",
        "action-applychangetags": "appliquer les balises avec vos modifications",
        "action-changetags": "ajouter et supprimer de façon arbitraire des balises sur des révisions individuelles et des entrées de journal",
        "action-deletechangetags": "supprimer des balises de la base de données",
+       "action-purge": "purger cette page",
        "nchanges": "$1 modification{{PLURAL:$1||s}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|depuis la dernière visite}}",
        "enhancedrc-history": "historique",
index 24b6f55..5ffbe02 100644 (file)
        "action-applychangetags": "aplicar etiquetas xunto cos cambios",
        "action-changetags": "engadir e quitar etiquetas arbitrarias a revisións individuais e entradas do rexistro",
        "action-deletechangetags": "borrar etiquetas da base de datos",
+       "action-purge": "purgar esta páxina",
        "nchanges": "$1 {{PLURAL:$1|modificación|modificacións}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|desde a última visita}}",
        "enhancedrc-history": "historial",
        "notvisiblerev": "A revisión foi borrada",
        "watchlist-details": "Hai {{PLURAL:$1|unha páxina|$1 páxinas}} na súa lista de vixilancia, sen contar as de conversa.",
        "wlheader-enotif": "A notificación por correo electrónico está activada.",
-       "wlheader-showupdated": "As páxinas que cambiaron desde a súa última visita móstranse en '''negra'''.",
+       "wlheader-showupdated": "As páxinas que cambiaron desde a súa última visita móstranse en <strong>letra grosa</strong>.",
        "wlnote": "A continuación {{PLURAL:$1|está a última modificación|están as últimas <strong>$1</strong> modificacións}} {{PLURAL:$2|na última hora|nas últimas <strong>$2</strong> horas}} ata o $3 ás $4.",
        "wlshowlast": "Mostrar as últimas $1 horas e os últimos $2 días",
        "watchlist-hide": "Agochar",
index 52f102f..c49591b 100644 (file)
        "right-reupload-own": "העלאת גרסאות חדשות של קבצים קיימים שהועלו על־ידי המשתמש עצמו",
        "right-reupload-shared": "דריסה מקומית של קבצים מאתר קובצי המדיה המשותף",
        "right-upload_by_url": "העלאת קבצים מכתובת אינטרנט (URL)",
-       "right-purge": "רענ×\95×\9f ×\96×\99×\9bר×\95×\9f ×\94×\9e×\98×\9e×\95×\9f ×©×\9c ×\94×\90תר ללא מעבר בדף אישור",
+       "right-purge": "× ×\99ק×\95×\99 ×\96×\99×\9bר×\95×\9f ×\94×\9e×\98×\9e×\95×\9f ×©×\9c ×\93×£ ללא מעבר בדף אישור",
        "right-autoconfirmed": "עקיפת ההגבלה על קצב הפעולות שניתן לבצע מכתובת IP מסוימת",
        "right-bot": "התייחסות לעריכות כאוטומטיות",
        "right-nominornewtalk": "ביטול שליחת התראה על הודעה חדשה למשתמש בעת עריכה משנית בדף השיחה שלו",
        "action-applychangetags": "להחיל תגיות יחד עם שינויים",
        "action-changetags": "להוסיף או להסיר תגיות מגרסאות ומרשומות יומן",
        "action-deletechangetags": "למחוק תגיות מבסיס הנתונים",
+       "action-purge": "לנקות את זיכרון המטמון של דף זה",
        "nchanges": "{{PLURAL:$1|שינוי אחד|$1 שינויים}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|מאז ביקורך האחרון}}",
        "enhancedrc-history": "היסטוריה",
index 494179e..8abca6a 100644 (file)
        "blanknamespace": "(Ser)",
        "contributions": "İştıraqê {{GENDER:$1|karber}}i",
        "contributions-title": "$1 de iştırakê karberi",
-       "mycontris": "İştıraqi",
+       "mycontris": "İştıraki",
        "contribsub2": "Serba $1 ($2)",
        "uctop": "(rocane)",
        "month": "Asme ra (u ravêr):",
        "blocklink": "kilıt ke",
        "unblocklink": "ra ke",
        "change-blocklink": "mani bıvurne",
-       "contribslink": "iştıraqi",
+       "contribslink": "iştıraki",
        "emaillink": "e-poste bırusne",
        "autoblocker": "Sıma otomatikmen kılit biy, çıke adresa sımawa ''IP''y terefê \"[[User:$1|$1]]\" gurenina.\nSebebê kılitbiyaena $1'i \"$2\"o",
        "blocklogpage": "Protokolê kilıti",
index 940b82f..1e69161 100644 (file)
        "right-applychangetags": "자신이 편집할 때 [[Special:Tags|태그]]를 적용하기",
        "right-changetags": "문서의 특정 판과 특정 기록 항목에 임의의 [[Special:Tags|태그]]를 추가하거나 제거하기",
        "right-deletechangetags": "데이터베이스에서 [[Special:Tags|태그]]를 지우기",
-       "grant-generic": "\"$1\" ê¶\8cí\95\9c ë²\88ë\93¤",
+       "grant-generic": "\"$1\" ê¶\8cí\95\9c ë¬¶ì\9d\8c",
        "grant-group-page-interaction": "문서로 상호 작용",
        "grant-group-file-interaction": "미디어로 상호 작용",
        "grant-group-watchlist-interaction": "당신의 주시문서로 상호작용",
index ef6e3ba..04b8e59 100644 (file)
        "action-viewmyprivateinfo": "Är privat Informatioune kucken",
        "action-editmyprivateinfo": "Är privat Informatiounen änneren",
        "action-editcontentmodel": "de Modell vum Inhalt vun enger Säit änneren",
+       "action-purge": "dës Säit eidelzemaachen",
        "nchanges": "$1 {{PLURAL:$1|Ännerung|Ännerungen}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|zanter dem leschte Passage}}",
        "enhancedrc-history": "Versiounen",
index dbffff9..4d9d764 100644 (file)
@@ -53,6 +53,7 @@
        "tog-watchdefault": "Pridėti puslapius, kuriuos aš redaguoju, į stebimų sąrašą",
        "tog-watchmoves": "Pridėti puslapius, kuriuos aš perkeliu, į stebimų sąrašą",
        "tog-watchdeletion": "Pridėti puslapius, kuriuos aš ištrinu, į stebimų sąrašą",
+       "tog-watchuploads": "Pridėti naujus failus, kurios aš įkeliu, į mano stebimųjų sąrašą",
        "tog-watchrollback": "Pridėti puslapius, kuriuose aš atlikau atmetimus į mano stebėjimo sąrašą",
        "tog-minordefault": "Pagal nutylėjimą pažymėti redagavimus kaip smulkius",
        "tog-previewontop": "Rodyti peržiūrą virš redagavimo lauko",
        "userlogin-resetpassword-link": "Pamiršote savo slaptažodį?",
        "userlogin-helplink2": "Padėti prisijungti",
        "userlogin-loggedin": "Jūs jau prisijungęs kaip {{GENDER:$1|$1}}.\nNaudokite žemiau pateiktą pavidalą, kad prisijungtumėte kaip kitas naudotojas.",
+       "userlogin-reauth": "Turite vėl prisijungti patvirtinimui, kad esate {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Sukurti kitą paskyrą",
        "createacct-emailrequired": "Elektroninio pašto adresas",
        "createacct-emailoptional": "Elektroninio pašto adresas (neprivaloma)",
        "createacct-email-ph": "Įveskite savo elektroninio pašto adresą",
        "createacct-another-email-ph": "Įveskite elektroninio pašto adresą",
        "createaccountmail": "Naudokite laikiną atsitiktinį slaptažodį ir nusiųskite jį į elektroninį paštą, nurodytą žemiau.",
+       "createaccountmail-help": "Gali būti naudojamas paskyros sukūrimui kitam asmeniui, neatskleidžiant slaptažodžio.",
        "createacct-realname": "Vardas (neprivaloma)",
        "createaccountreason": "Priežastis:",
        "createacct-reason": "Priežastis",
        "createacct-reason-ph": "Kodėl kuriate kitą paskyrą",
+       "createacct-reason-help": "Pranešimas rodomas paskyros sukūrimo žurnale",
        "createacct-submit": "Sukurkite savo paskyrą",
        "createacct-another-submit": "Sukurti paskyrą",
        "createacct-continue-submit": "Tęsti paskyros kūrimą",
        "nocookiesnew": "Naudotojo paskyra buvo sukurta, bet jūs nesate prisijungęs. {{SITENAME}} naudoja slapukus, kad prijungtų naudotojus. Jūs esate išjungę slapukus. Prašome įjungti juos, tada prisijunkite su savo naujuoju naudotojo vardu ir slaptažodžiu.",
        "nocookieslogin": "{{SITENAME}} naudoja slapukus, kad prijungtų naudotojus. Jūs esate išjungę slapukus. Prašome įjungti juos ir pamėginkite vėl.",
        "nocookiesfornew": "Paskyra nebuvo sukurta, nes mums nepavyko nustatyti jos šaltinio.\nĮsitikinkite, kad įjungti slapukai (angl. cookies) ir tada bandykite dar kartą.",
+       "createacct-loginerror": "Paskyra buvo sėkmingai sukurta, bet nepavyko jūsų automatiškai prijungti. Prašome tęsti [[Special:UserLogin|prisijungiant rankiniu būdu]].",
        "noname": "Jūs nesate nurodęs teisingo naudotojo vardo.",
        "loginsuccesstitle": "Sėkmingai prisijungėte",
        "loginsuccess": "'''Dabar jūs prisijungęs prie {{SITENAME}} kaip „$1“.'''",
        "noemail": "Nėra jokio el. pašto adreso įvesto naudotojui „$1“.",
        "noemailcreate": "Jūs turite nurodyti veikiantį el. pašto adresą",
        "passwordsent": "Naujas slaptažodis buvo nusiųstas į el. pašto adresą,\nužregistruotą naudotojo „$1“.\nPrašome prisijungti vėl, kai jūs jį gausite.",
-       "blocked-mailpassword": "Jūsų IP adresas yra užblokuotas nuo redagavimo, taigi neleidžiama naudoti slaptažodžio priminimo funkcijos, kad apsisaugotume nuo piktnaudžiavimo.",
+       "blocked-mailpassword": "Jūsų IP adresas yra užblokuotas nuo redagavimo. Kad užkirstume kelią piktnaudžiavimui neleidžiama naudoti slaptažodžio priminimo funkcijos iš šio IP adreso.",
        "eauthentsent": "Patvirtinimo laiškas buvo nusiųstas į paskirtąjį el. pašto adresą.\nPrieš išsiunčiant kitą laišką į jūsų dėžutę, jūs turite vykdyti nurodymus laiške, kad patvirtintumėte, kad dėžutė tikrai yra jūsų.",
        "throttled-mailpassword": "Slaptažodžio priminimas jau buvo išsiųstas, per {{PLURAL:$1|$1 paskutinę valandą|$1 paskutines valandas|$1 paskutinių valandų}}.\n\nNorint apsisaugoti nuo piktnaudžiavimo, slaptažodžio priminimas gali būti išsiųstas tik kas {{PLURAL:$1|$1 valandą|$1 valandas|$1 valandų}}.",
        "mailerror": "Klaida siunčiant laišką: $1",
        "createaccount-title": "{{SITENAME}} paskyros kūrimas",
        "createaccount-text": "Projekte {{SITENAME}} ($4) kažkas sukūrė paskyrą „$2“ su slaptažodžiu „$3“ panaudodamas jūsų el. pašto adresą.\nJūs turėtumėte prisijungti ir pasikeisti savo slaptažodį.\n\nJūs galite nekreipti dėmesio į laišką, jei ši paskyra buvo sukurta per klaidą.",
        "login-throttled": "Jūs pernelyg daug kartų bandėte prisijungti.\nPalaukite $1 prieš bandant vėl.",
-       "login-abort-generic": "Jūsų prisijungimas buvo nesėkmingas - Nutraukta",
+       "login-abort-generic": "Jūsų prisijungimas nepavyko - Nutraukta",
        "login-migrated-generic": "Jūsų paskyra buvo perkelta ir jūsų naudotojo vardo šioje wiki daugiau nebėra.",
        "loginlanguagelabel": "Kalba: $1",
        "suspicious-userlogout": "Jūsų prašymas atsijungti buvo atmestas, nes, atrodo, jį klaidingai išsiuntė naršyklė arba spartinantysis tarpinis serveris.",
        "resetpass-no-info": "Jūs turite būti prisijungęs, kad pasiektumėte puslapį tiesiogiai.",
        "resetpass-submit-loggedin": "Keisti slaptažodį",
        "resetpass-submit-cancel": "Atšaukti",
-       "resetpass-wrong-oldpass": "Klaidingas laikinas ar esamas slaptažodis.\nJūs galbūt jau sėkmingai pakeitėte savo slaptažodį ar gavote naują laikiną slaptažodį.",
+       "resetpass-wrong-oldpass": "Klaidingas laikinas ar esamas slaptažodis.\nJūs galbūt jau sėkmingai pakeitėte savo slaptažodį ar jau prašėte naujo laikino slaptažodžio.",
        "resetpass-recycled": "Atkurkite savo slaptažodį kitokiu, nei buvo prieš tai.",
        "resetpass-temp-emailed": "Jūs prisijungęs laikinu slaptažodžiu, gautu per elektroninį paštą. Kad baigtumėte jungtis, čia turite nustatyti naują slaptažodį:",
        "resetpass-temp-password": "Laikinas slaptažodis:",
        "passwordreset-emailsentusername": "Jeigu buvo el. paštas susietas su šiuo naudotojo vardu, tai slaptažodžio atkūrimo el. laiškas bus išsiųstas.",
        "passwordreset-emailsent-capture": "Slaptažodžio priminimo laiškas bus išsiųstas, toks koks parodytas.",
        "passwordreset-emailerror-capture": "Priminimo elektroninis laiškas buvo sukurtas, toks, koks parodytas žemiau, bet pasiuntimas naudotojui buvo nesėkmingas: $1",
+       "passwordreset-emailsent-capture2": "Slaptažodžio keitimo {{PLURAL:$1|el. laiškas buvo išsiųstas|el. laiškai buvo išsiųsti}}. {{PLURAL:$1|vartotojo vardas ir slaptažodis rodomi|vartotojų vardų ir slaptažodžių sąrašas rodomas}} žemiau.",
+       "passwordreset-emailerror-capture2": "El. laiško siuntimas {{GENDER:$2|vartotojui}} nepavyko: $1 {{PLURAL:$3|vartotojo vardas ir slaptažodis rodomi|vartotojų vardų ir slaptažodžių sąrašas rodomas}} žemiau.",
+       "passwordreset-nocaller": "Skambinantysis turi būti nurodytas",
+       "passwordreset-nosuchcaller": "Skambinantysis neegzistuoja: $1",
        "passwordreset-invalideamil": "Neteisingas el. pašto adresas",
        "passwordreset-nodata": "Vartotojo vardas ir el. paštas buvo nepateikti",
        "changeemail": "Pakeisti ar pašalinti el. pašto adresą",
        "authprovider-confirmlink-ok-help": "Tęsti po susiejimo klaidos žinutės parodymo.",
        "authprovider-resetpass-skip-label": "Praleisti",
        "authprovider-resetpass-skip-help": "Praleisti slaptažodžio perstatymą.",
-       "specialpage-securitylevel-not-allowed-title": "Neleidžiama"
+       "specialpage-securitylevel-not-allowed-title": "Neleidžiama",
+       "cannotauth-not-allowed-title": "Teisė nesuteikta",
+       "cannotauth-not-allowed": "Jūs negalite naudotis šiuo puslapiu",
+       "linkaccounts": "Susieti paskyras",
+       "linkaccounts-success-text": "Paskyra buvo susieta.",
+       "linkaccounts-submit": "Susieti paskyras",
+       "unlinkaccounts": "Atsieti paskyras",
+       "unlinkaccounts-success": "Paskyra buvo atsieta."
 }
index 6589316..47bb5bf 100644 (file)
        "minoredit": "Marcar como edição menor",
        "watchthis": "Vigiar esta página",
        "savearticle": "Salvar página",
+       "publishpage": "Publicar página",
+       "publishchanges": "Publicar alterações",
        "preview": "Pré-visualização",
        "showpreview": "Mostrar previsão",
        "showdiff": "Mostrar alterações",
index d7db370..81b7976 100644 (file)
        "action-managechangetags": "criar e (des)ativar etiquetas",
        "action-applychangetags": "aplicar etiquetas juntamente com as suas alterações",
        "action-changetags": "adicionar e remover etiquetas arbitrárias em revisões e entradas de registo individuais",
+       "action-purge": "recarregar esta página",
        "nchanges": "$1 {{PLURAL:$1|alteração|alterações}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|desde a última visita}}",
        "enhancedrc-history": "histórico",
index 6f60691..649a9d9 100644 (file)
        "action-applychangetags": " применять теги наряду с Вашими изменениями",
        "action-changetags": "Добавлять и удалять произвольные теги на отдельных изменениях и записях в журнале",
        "action-deletechangetags": "удаление меток из базы данных",
+       "action-purge": "очистку кэша этой страницы",
        "nchanges": "$1 {{PLURAL:$1|изменение|изменения|изменений}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|с последнего посещения}}",
        "enhancedrc-history": "история",
index 3c18dc9..81007c5 100644 (file)
        "action-applychangetags": "uveljavitev oznak skupaj z vašimi spremembami",
        "action-changetags": "dodajanje in odstranjevanje poljubnih oznak na posameznih redakcijah in dnevniških vnosih",
        "action-deletechangetags": "izbris oznak iz zbirke podatkov",
+       "action-purge": "počiščenje strani",
        "nchanges": "$1 {{PLURAL:$1|sprememba|spremembi|spremembe|sprememb|sprememb}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|od zadnjega obiska}}",
        "enhancedrc-history": "zgodovina",
index 3715253..d102056 100644 (file)
        "watchthis": "Theo dõi trang này",
        "savearticle": "Lưu trang",
        "savechanges": "Lưu các thay đổi",
-       "publishpage": "Xuất bản trang",
-       "publishchanges": "Xuất bản các thay đổi",
+       "publishpage": "Đăng trang",
+       "publishchanges": "Đăng thay đổi",
        "preview": "Xem trước",
        "showpreview": "Xem trước",
        "showdiff": "Xem thay đổi",
        "content-json-empty-object": "Đối tượng trống",
        "content-json-empty-array": "Mảng trống",
        "deprecated-self-close-category": "Trang có thẻ HTML tự đóng không hợp lệ",
+       "deprecated-self-close-category-desc": "Trang này chứa thẻ HTML tự đóng không hợp lệ, ví dụ <code>&lt;b/></code> hoặc <code>&lt;span/></code>. Tí nữa cách trình bày các thẻ này sẽ thay đổi để tuân theo tiêu chuẩn HTML5, nên sự sử dụng chúng trong mã wiki bị phản đối.",
        "duplicate-args-warning": "<strong>Cảnh báo:</strong> [[:$1]] đang gọi  [[:$2]] với nhiều hơn một giá trị cho thông số “$3”. Chỉ giá trị cuối cùng mới được sử dụng.",
        "duplicate-args-category": "Trang đưa đối số thừa vào bản mẫu",
        "duplicate-args-category-desc": "Trang đưa một đối số nhiều lần vào một bản mẫu được nhúng, thí dụ <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> hoặc <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "action-applychangetags": "áp dụng các thẻ cùng với những thay đổi của bạn",
        "action-changetags": "thêm và loại bỏ các thẻ tùy ý trên các phiên bản riêng và các mục nhật trình",
        "action-deletechangetags": "xóa thẻ khỏi cơ sở dữ liệu",
+       "action-purge": "làm mới trang này",
        "nchanges": "$1 thay đổi",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|sau lần truy cập vừa rồi}}",
        "enhancedrc-history": "lịch sử",
        "log-action-filter-patrol": "Kiểu tuần tra:",
        "log-action-filter-protect": "Loại bảo vệ:",
        "log-action-filter-rights": "Kiểu thay đổi quyền:",
-       "log-action-filter-suppress": "Kiểu ẩn giấu",
+       "log-action-filter-suppress": "Kiểu ẩn giấu:",
        "log-action-filter-upload": "Loại tải lên:",
        "log-action-filter-all": "Tất cả",
        "log-action-filter-block-block": "Khối",
index c025f6e..d807319 100644 (file)
        "content-json-empty-object": "ליידיגער אביעקט",
        "content-json-empty-array": "ליידיגער אריי",
        "duplicate-args-warning": "<strong>ווארענונג:</strong> [[:$1]] רופט [[:$2]] מיט מער ווי איין ווערט פארן פאראמעטער \"$3\". נאר דעם לעצטן ווערט וועט מען ניצן.",
-       "duplicate-args-category": "×\91×\9c×¢×\98ער ×\95×\95×\90ס × ×\99צ×\9f ×\92×¢×\98×\90פ×\9c×\98×¢ ×\90ר×\92×\95×\9e×¢× ×\98×\9f ×\90×\99×\9f ×\9e×\95ס×\98ער ×¨×\95פ×\9f",
+       "duplicate-args-category": "×\91×\9c×¢×\98ער ×\95×\95×\90ס × ×\99צ×\9f ×\92×¢×\98×\90פ×\9c×\98×¢ ×\90ר×\92×\95×\9e×¢× ×\98×\9f ×\90×\99×\9f ×\90 ×\9e×\95ס×\98ער־ר×\95×£",
        "duplicate-args-category-desc": "דער בלאט אנטהאלט מוסטער־אויפרופן וואס ניצן דופליקאטן פון ארגומענטן, ווי למשל <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> or <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''אזהרה:''' דער בלאט אנטהאלט צופיל טייערע פארזירער רופן.\n\nער דארף האבן ווינציגער פון  $2 {{PLURAL:$2|רוף|רופן}}, אבער אצינד {{PLURAL:$1|איז דא $1 רוף|זענען דא $1 רופן}}.",
        "expensive-parserfunction-category": "בלעטער מיט צופֿיל טייערע פאַרזער פֿונקציאן רופֿן",
index d1cba1f..cb8ff2e 100644 (file)
        "action-applychangetags": "连同您的更改应用标签",
        "action-changetags": "在个别修订和日志记录中添加和移除任意标签",
        "action-deletechangetags": "从数据库删除标签",
+       "action-purge": "刷新此页面",
        "nchanges": "$1次更改",
        "enhancedrc-since-last-visit": "{{PLURAL:$1|上次访问后}}$1个",
        "enhancedrc-history": "历史",
index 892ce4d..5d4d1c3 100644 (file)
@@ -73,7 +73,8 @@
                        "Zerng07",
                        "Reke",
                        "Kly",
-                       "Cosine02"
+                       "Cosine02",
+                       "一個正常人"
                ]
        },
        "tog-underline": "底線標示連結:",
        "action-applychangetags": "連同您的變更一起套用標籤",
        "action-changetags": "加入與移除任何於各別修訂與日誌項目的標籤",
        "action-deletechangetags": "從資料庫刪除標籤",
+       "action-purge": "刷新此頁面",
        "nchanges": "$1 次變更",
        "enhancedrc-since-last-visit": "{{PLURAL:$1|自上次拜訪}}已有 $1",
        "enhancedrc-history": "歷史",
index 8b1d86d..0c278bc 100644 (file)
@@ -10,12 +10,11 @@ require_once __DIR__ . '/../includes/utils/AutoloadGenerator.php';
 $base = dirname( __DIR__ );
 
 $generator = new AutoloadGenerator( $base, 'local' );
-foreach ( [ 'includes', 'languages', 'maintenance', 'mw-config' ] as $dir ) {
-       $generator->readDir( $base . '/' . $dir );
-}
-foreach ( glob( $base . '/*.php' ) as $file ) {
-       $generator->readFile( $file );
-}
+$generator->initMediaWikiDefault();
 
 // Write out the autoload
-$generator->generateAutoload( 'maintenance/generateLocalAutoload.php' );
+$fileinfo = $generator->getTargetFileinfo();
+file_put_contents(
+       $fileinfo['filename'],
+       $generator->getAutoload( 'maintenance/generateLocalAutoload.php' )
+);
index 746cbd1..1558ee6 100644 (file)
@@ -52,6 +52,7 @@ return [
 
        // Scripts managed by the current user (stored in their user space)
        'user' => [ 'class' => 'ResourceLoaderUserModule' ],
+       'user.styles' => [ 'class' => 'ResourceLoaderUserStylesModule' ],
 
        // Scripts generated based on the current user's preferences
        'user.cssprefs' => [ 'class' => 'ResourceLoaderUserCSSPrefsModule' ],
@@ -164,6 +165,7 @@ return [
        'jquery.arrowSteps' => [
                'scripts' => 'resources/src/jquery/jquery.arrowSteps.js',
                'styles' => 'resources/src/jquery/jquery.arrowSteps.css',
+               'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.async' => [
                'scripts' => 'resources/lib/jquery/jquery.async.js',
@@ -328,6 +330,7 @@ return [
        'jquery.spinner' => [
                'scripts' => 'resources/src/jquery/jquery.spinner.js',
                'styles' => 'resources/src/jquery/jquery.spinner.css',
+               'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.jStorage' => [
                'scripts' => 'resources/lib/jquery/jquery.jStorage.js',
@@ -939,6 +942,7 @@ return [
                'dependencies' => [
                        'mediawiki.api',
                ],
+               'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.api.rollback' => [
                'scripts' => 'resources/src/mediawiki/api/rollback.js',
@@ -1010,6 +1014,7 @@ return [
                        'feedback-thanks-title',
                        'feedback-useragent'
                ],
+               'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.feedlink' => [
                'position' => 'top',
@@ -1077,6 +1082,7 @@ return [
        ],
        'mediawiki.icon' => [
                'styles' => 'resources/src/mediawiki/mediawiki.icon.less',
+               'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.inspect' => [
                'scripts' => 'resources/src/mediawiki/mediawiki.inspect.js',
@@ -1650,6 +1656,7 @@ return [
 
        'mediawiki.libs.jpegmeta' => [
                'scripts' => 'resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js',
+               'targets' => [ 'desktop', 'mobile' ],
        ],
 
        /* MediaWiki Page */
index b74cd06..f3c7e3c 100644 (file)
@@ -4,11 +4,24 @@
                        "Lloffiwr",
                        "Robin Owain",
                        "ОйЛ",
-                       "DChan (WMF)"
+                       "DChan (WMF)",
+                       "Jdforrester"
                ]
        },
        "ooui-outline-control-move-down": "Symud yr eitem i lawr",
        "ooui-outline-control-move-up": "Symud yr eitem i fyny",
        "ooui-outline-control-remove": "Tynnu'r eitem",
-       "ooui-toolbar-more": "Rhagor"
+       "ooui-toolbar-more": "Rhagor",
+       "ooui-toolgroup-expand": "Mwy",
+       "ooui-toolgroup-collapse": "Llai",
+       "ooui-dialog-message-accept": "Iawn",
+       "ooui-dialog-message-reject": "Canslo",
+       "ooui-dialog-process-error": "Aeth rhywbeth o’i le",
+       "ooui-dialog-process-dismiss": "Gadael",
+       "ooui-dialog-process-retry": "Ailgeisio",
+       "ooui-dialog-process-continue": "Parhau",
+       "ooui-selectfile-button-select": "Dewis ffeil",
+       "ooui-selectfile-not-supported": "Nid oes modd dewis ffeil",
+       "ooui-selectfile-placeholder": "Dim ffeil wedi'i dewis",
+       "ooui-selectfile-dragdrop-placeholder": "Gollwng ffeil yma"
 }
index 59b7ccd..326baaf 100644 (file)
@@ -15,7 +15,7 @@
        "ooui-dialog-message-accept": "Sobib",
        "ooui-dialog-message-reject": "Loobu",
        "ooui-dialog-process-error": "Midagi läks valesti",
-       "ooui-dialog-process-dismiss": "Hülga",
+       "ooui-dialog-process-dismiss": "Sule",
        "ooui-dialog-process-retry": "Proovi uuesti",
        "ooui-dialog-process-continue": "Jätka",
        "ooui-selectfile-button-select": "Vali fail",
index 3894417..0c84bd1 100644 (file)
@@ -13,8 +13,8 @@
                        "Hwangjy9"
                ]
        },
-       "ooui-outline-control-move-down": "í\95­ëª©ì\9d\84 ì\95\84ë\9e\98ë¡\9c ì\98®ê¸°ê¸°",
-       "ooui-outline-control-move-up": "í\95­ëª©ì\9d\84 ì\9c\84ë¡\9c ì\98®ê¸°ê¸°",
+       "ooui-outline-control-move-down": "í\95­ëª©ì\9d\84 ì\95\84ë\9e\98ë¡\9c ì\9d´ë\8f\99",
+       "ooui-outline-control-move-up": "í\95­ëª©ì\9d\84 ì\9c\84ë¡\9c ì\9d´ë\8f\99",
        "ooui-outline-control-remove": "항목 제거",
        "ooui-toolbar-more": "더 보기",
        "ooui-toolgroup-expand": "더 보기",
index 4bf5dac..679f1a6 100644 (file)
@@ -6,7 +6,8 @@
                        "Elioqoshi",
                        "GretaDoci",
                        "Gertakapllani",
-                       "Techlik"
+                       "Techlik",
+                       "Liridon"
                ]
        },
        "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
@@ -21,6 +22,8 @@
        "ooui-dialog-process-dismiss": "Largoje",
        "ooui-dialog-process-retry": "Provo përsëri",
        "ooui-dialog-process-continue": "Vazhdo",
+       "ooui-selectfile-button-select": "Përzgjidhni një skedë",
        "ooui-selectfile-not-supported": "Skedari i përzgjedhur nuk përkrahet",
-       "ooui-selectfile-placeholder": "Nuk është zgjedhur asnjë skedar"
+       "ooui-selectfile-placeholder": "Nuk është zgjedhur asnjë skedar",
+       "ooui-selectfile-dragdrop-placeholder": "Vendose skedën këtu"
 }
index a34432f..6a38d0d 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:03Z
+ * Date: 2016-08-03T16:38:22Z
  */
 ( function ( OO ) {
 
index 152d444..72591cc 100644 (file)
@@ -1,15 +1,16 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-element-hidden {
        display: none !important;
+       /* stylelint-disable-line declaration-no-important */
 }
 .oo-ui-buttonElement > .oo-ui-buttonElement-button {
        cursor: pointer;
        overflow: auto;
        resize: none;
 }
+.oo-ui-textInputWidget [type="number"] {
+       -moz-appearance: textfield;
+}
+.oo-ui-textInputWidget [type="number"]::-webkit-outer-spin-button,
+.oo-ui-textInputWidget [type="number"]::-webkit-inner-spin-button {
+       -webkit-appearance: none;
+       margin: 0;
+}
 .oo-ui-textInputWidget [type="search"] {
        -webkit-appearance: textfield;
 }
 .oo-ui-comboBoxInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
        cursor: pointer;
 }
-.oo-ui-comboBoxInputWidget-php input::-webkit-calendar-picker-indicator {
-       opacity: 0 !important;
+.oo-ui-comboBoxInputWidget-php ::-webkit-calendar-picker-indicator {
+       opacity: 0;
        position: absolute;
        right: 0;
        top: 0;
index a191804..23ecccd 100644 (file)
@@ -1,15 +1,16 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-element-hidden {
        display: none !important;
+       /* stylelint-disable-line declaration-no-important */
 }
 .oo-ui-buttonElement > .oo-ui-buttonElement-button {
        cursor: pointer;
        margin-bottom: 1.25em;
 }
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
-       padding: 0.25em 0.25em 0.25em 1em;
+       padding: 0.25em 0.25em 0.25em 0.5em;
 }
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-top.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
        padding-top: 0.25em;
        margin-top: 2em;
 }
 .oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
-       font-size: 1.1em;
        margin-bottom: 0.5em;
-       padding: 0.25em 0;
+       font-size: 1.1em;
        font-weight: bold;
 }
 .oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-labelElement-label {
        background-color: transparent;
 }
 .oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
-       padding: 0.25em 0.25em 0.25em 1em;
+       padding: 0.25em 0.25em 0.25em 0.5em;
 }
 .oo-ui-radioOptionWidget .oo-ui-radioInputWidget {
        margin-right: 0;
        background-position: center center;
        background-origin: border-box;
        background-size: 0 0;
-       border: 1px solid #777777;
+       border: 1px solid #767676;
        border-radius: 2px;
 }
 .oo-ui-checkboxInputWidget [type="checkbox"]:checked + span {
        background-size: 100% 100%;
 }
 .oo-ui-checkboxInputWidget [type="checkbox"]:active + span {
-       background-color: #cccccc;
-       border-color: #cccccc;
+       background-color: #767676;
+       border-color: #767676;
 }
 .oo-ui-checkboxInputWidget [type="checkbox"]:focus + span {
        border-width: 2px;
        background-position: center center;
        background-origin: border-box;
        background-size: 0 0;
-       border: 1px solid #777777;
+       border: 1px solid #767676;
        border-radius: 100%;
 }
 .oo-ui-radioInputWidget [type="radio"]:checked + span {
        background-size: 100% 100%;
 }
 .oo-ui-radioInputWidget [type="radio"]:active + span {
-       background-color: #cccccc;
-       border-color: #cccccc;
+       background-color: #767676;
+       border-color: #767676;
 }
 .oo-ui-radioInputWidget [type="radio"]:focus + span {
        border-width: 2px;
        overflow: auto;
        resize: none;
 }
+.oo-ui-textInputWidget [type="number"] {
+       -moz-appearance: textfield;
+}
+.oo-ui-textInputWidget [type="number"]::-webkit-outer-spin-button,
+.oo-ui-textInputWidget [type="number"]::-webkit-inner-spin-button {
+       -webkit-appearance: none;
+       margin: 0;
+}
 .oo-ui-textInputWidget [type="search"] {
        -webkit-appearance: textfield;
 }
           -moz-transition: border 200ms cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 200ms cubic-bezier(0.39, 0.575, 0.565, 1);
                transition: border 200ms cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 200ms cubic-bezier(0.39, 0.575, 0.565, 1);
 }
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:hover,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:hover {
+       border-color: #aaaaaa;
+}
 .oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
 .oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
        outline: 0;
        color: #777777;
        text-shadow: 0 1px 1px #ffffff;
 }
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly]:hover,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly]:hover {
+       border-color: #cccccc;
+}
 .oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly]:focus,
 .oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly]:focus {
        border-color: #cccccc;
 .oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea {
        border-color: #ff0000;
 }
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input:hover,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea:hover {
+       border-color: #ff0000;
+}
 .oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input:focus,
 .oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea:focus {
        border-color: #ff0000;
 .oo-ui-comboBoxInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
        cursor: pointer;
 }
-.oo-ui-comboBoxInputWidget-php input::-webkit-calendar-picker-indicator {
-       opacity: 0 !important;
+.oo-ui-comboBoxInputWidget-php ::-webkit-calendar-picker-indicator {
+       opacity: 0;
        position: absolute;
        right: 0;
        top: 0;
        vertical-align: middle;
 }
 .oo-ui-checkboxMultioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
-       padding: 0.25em 0.25em 0.25em 1em;
+       padding: 0.25em 0.25em 0.25em 0.5em;
 }
 .oo-ui-checkboxMultioptionWidget .oo-ui-checkboxInputWidget {
        margin-right: 0;
index 2a1427b..4d32961 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:03Z
+ * Date: 2016-08-03T16:38:22Z
  */
 ( function ( OO ) {
 
@@ -6994,7 +6994,7 @@ OO.ui.CheckboxMultiselectWidget.prototype.getRelativeFocusableItem = function (
  * @param {jQuery.Event} e
  */
 OO.ui.CheckboxMultiselectWidget.prototype.onClick = function ( e ) {
-       var $options, checked,
+       var $options, lastClickedIndex, nowClickedIndex, i, direction, wasSelected, items,
                $lastClicked = this.$lastClicked,
                $nowClicked = $( e.target ).closest( '.oo-ui-checkboxMultioptionWidget' )
                        .not( '.oo-ui-widget-disabled' );
@@ -7002,19 +7002,32 @@ OO.ui.CheckboxMultiselectWidget.prototype.onClick = function ( e ) {
        // Allow selecting multiple options at once by Shift-clicking them
        if ( $lastClicked && $nowClicked.length && e.shiftKey ) {
                $options = this.$group.find( '.oo-ui-checkboxMultioptionWidget' );
-               checked = $nowClicked.find( 'input' ).prop( 'checked' );
-
-               $options
-                       .slice(
-                               Math.min( $options.index( $lastClicked ), $options.index( $nowClicked ) ),
-                               Math.max( $options.index( $lastClicked ), $options.index( $nowClicked ) ) + 1
-                       )
-                       .find( 'input' )
-                       .filter( function () {
-                               return !this.disabled;
-                       } )
-                       .prop( 'checked', checked )
-                       .trigger( 'change' );
+               lastClickedIndex = $options.index( $lastClicked );
+               nowClickedIndex = $options.index( $nowClicked );
+               // If it's the same item, either the user is being silly, or it's a fake event generated by the
+               // browser. In either case we don't need custom handling.
+               if ( nowClickedIndex !== lastClickedIndex ) {
+                       items = this.items;
+                       wasSelected = items[ nowClickedIndex ].isSelected();
+                       direction = nowClickedIndex > lastClickedIndex ? 1 : -1;
+
+                       // This depends on the DOM order of the items and the order of the .items array being the same.
+                       for ( i = lastClickedIndex; i !== nowClickedIndex; i += direction ) {
+                               if ( !items[ i ].isDisabled() ) {
+                                       items[ i ].setSelected( !wasSelected );
+                               }
+                       }
+                       // For the now-clicked element, use immediate timeout to allow the browser to do its own
+                       // handling first, then set our value. The order in which events happen is different for
+                       // clicks on the <input> and on the <label> and there are additional fake clicks fired for
+                       // non-click actions that change the checkboxes.
+                       e.preventDefault();
+                       setTimeout( function () {
+                               if ( !items[ nowClickedIndex ].isDisabled() ) {
+                                       items[ nowClickedIndex ].setSelected( !wasSelected );
+                               }
+                       } );
+               }
        }
 
        if ( $nowClicked.length ) {
index d0de9df..ff18605 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:03Z
+ * Date: 2016-08-03T16:38:22Z
  */
 ( function ( OO ) {
 
index e758f82..d69ebfa 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-popupTool .oo-ui-popupWidget-popup,
 .oo-ui-popupTool .oo-ui-popupWidget-anchor {
index 0c007bb..5b60528 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-popupTool .oo-ui-popupWidget-popup,
 .oo-ui-popupTool .oo-ui-popupWidget-anchor {
@@ -38,8 +38,8 @@
 .oo-ui-toolGroup {
        display: inline-block;
        vertical-align: middle;
+       border-right: 1px solid #cccccc;
        border-radius: 0;
-       border-right: 1px solid #dddddd;
 }
 .oo-ui-toolGroup-empty {
        display: none;
@@ -56,9 +56,6 @@
 .oo-ui-toolbar-narrow .oo-ui-toolGroup + .oo-ui-toolGroup {
        margin-left: 0;
 }
-.oo-ui-toolGroup .oo-ui-toolGroup .oo-ui-widget-enabled {
-       border-right: 0 !important;
-}
 .oo-ui-barToolGroup > .oo-ui-iconElement-icon,
 .oo-ui-barToolGroup > .oo-ui-labelElement-label {
        display: none;
        padding: 0 0.4em;
 }
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover {
-       border-color: rgba(0, 0, 0, 0.2);
        background-color: #eeeeee;
 }
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool > a.oo-ui-tool-link .oo-ui-tool-title {
        color: #555555;
 }
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled {
-       border-color: rgba(0, 0, 0, 0.2);
        box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
        background-color: #e5e5e5;
 }
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled:hover {
        background-color: #eeeeee;
 }
-.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
-       border-left-color: rgba(0, 0, 0, 0.1);
-}
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-tool-title {
        color: #cccccc;
 }
 }
 .oo-ui-popupToolGroup .oo-ui-tool-link {
        padding: 0.4em 0.625em;
-       box-sizing: border-box;
+       -webkit-box-sizing: border-box;
+          -moz-box-sizing: border-box;
+               box-sizing: border-box;
 }
 .oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
        height: 2.5em;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
 }
-.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
-       border-color: rgba(0, 0, 0, 0.2);
-}
 .oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
-       border-color: rgba(0, 0, 0, 0.2);
        background-color: #eeeeee;
 }
 .oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:active {
        opacity: 0.9;
 }
 .oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
-       border-color: rgba(0, 0, 0, 0.1);
        box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
        background-color: #e5e5e5;
 }
-.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
-       border-top-color: rgba(0, 0, 0, 0.1);
-}
 .oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
-       border-color: rgba(0, 0, 0, 0.2);
        background-color: #eeeeee;
 }
 .oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
index 66473ff..5254c76 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:03Z
+ * Date: 2016-08-03T16:38:22Z
  */
 ( function ( OO ) {
 
index e83cce5..a267b7f 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-draggableElement-handle,
 .oo-ui-draggableElement-handle.oo-ui-widget {
@@ -89,6 +89,8 @@
        left: 0;
        right: 0;
        bottom: 0;
+       /* stylelint-disable declaration-no-important */
+       /* stylelint-enable declaration-no-important */
 }
 .oo-ui-menuLayout-menu,
 .oo-ui-menuLayout-content {
 .oo-ui-selectFileWidget .oo-ui-selectFileWidget-clearButton {
        z-index: 2;
 }
-.oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget {
        cursor: default;
        height: 5.5em;
        padding: 0;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
        display: none;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
        height: 5.5em;
        width: 5.5em;
        position: absolute;
        background-size: cover;
        background-position: center center;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
        background-size: auto;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
        opacity: 0.4;
        background-color: #cccccc;
        height: 5.5em;
        width: 5.5em;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
        border: 0;
        background: none;
        display: block;
        width: auto;
        margin-left: 5.5em;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
        position: relative;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileName {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileName {
        display: block;
        padding-right: 2.375em;
        overflow: hidden;
        text-overflow: ellipsis;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileType {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileType {
        display: block;
        float: none;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
        position: absolute;
        right: 0.5em;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
        display: none;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
        display: block;
        margin: 0.7em;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
        text-align: center;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
        margin: 0;
 }
 .oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-clearButton,
 .oo-ui-selectFileWidget-empty.oo-ui-widget-enabled .oo-ui-selectFileWidget-dropLabel {
        display: block;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
        -webkit-touch-callout: none;
        -webkit-user-select: none;
           -moz-user-select: none;
            -ms-user-select: none;
                user-select: none;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
        cursor: no-drop;
 }
 .oo-ui-selectFileWidget:last-child {
 .oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
        right: 2em;
 }
-.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop.oo-ui-selectFileWidget-dropTarget {
        background-color: #e1f3ff;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
        color: #cccccc;
        text-shadow: 0 1px 1px #ffffff;
        border-color: #dddddd;
        background-color: #f3f3f3;
 }
-.oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget {
        background-color: #ffffff;
        border: 1px solid #aaaaaa;
        margin-bottom: 0.5em;
        vertical-align: middle;
        border-radius: 0.25em;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
        border-radius: 0.25em;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget {
        border-style: dashed;
 }
 .oo-ui-outlineOptionWidget {
 .oo-ui-numberInputWidget-field > .oo-ui-textInputWidget {
        width: 100%;
 }
-.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"]::-webkit-outer-spin-button,
-.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"]::-webkit-inner-spin-button {
-       -webkit-appearance: none;
-       margin: 0;
-}
-.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"] {
-       -moz-appearance: textfield;
-}
 .oo-ui-numberInputWidget-field > .oo-ui-buttonWidget {
        white-space: nowrap;
 }
index 375a478..8145ef9 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-draggableElement-handle,
 .oo-ui-draggableElement-handle.oo-ui-widget {
@@ -95,6 +95,8 @@
        left: 0;
        right: 0;
        bottom: 0;
+       /* stylelint-disable declaration-no-important */
+       /* stylelint-enable declaration-no-important */
 }
 .oo-ui-menuLayout-menu,
 .oo-ui-menuLayout-content {
                transform: translateZ(0);
        height: 2em;
        width: 3.5em;
-       border: 1px solid #777777;
+       border: 1px solid #767676;
        border-radius: 1em;
        background-color: #ffffff;
        margin-right: 0.5em;
        min-height: 16px;
        height: 1.2em;
        border-radius: 1.2em;
-       background-color: #555555;
        -webkit-transition: left 100ms, margin-left 100ms;
           -moz-transition: left 100ms, margin-left 100ms;
                transition: left 100ms, margin-left 100ms;
        left: 1.9em;
        margin-left: -2px;
 }
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on {
-       background-color: #347bff;
-       border-color: #347bff;
-}
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
-       background-color: #ffffff;
-       box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled .oo-ui-toggleSwitchWidget-grip {
+       border: 1px solid #767676;
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover {
        border-color: #2962cc;
 }
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover.oo-ui-toggleWidget-on {
-       background-color: #2962cc;
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
        border-color: #2962cc;
 }
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover {
+       background-color: #767676;
+       border-color: #347bff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active .oo-ui-toggleSwitchWidget-grip,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover .oo-ui-toggleSwitchWidget-grip {
+       background-color: #ffffff;
+       border-color: #ffffff;
+       box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+}
 .oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus {
        border-color: #347bff;
        box-shadow: inset 0 0 0 1px #347bff;
        outline: 0;
 }
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus.oo-ui-toggleWidget-on {
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus .oo-ui-toggleSwitchWidget-grip {
        border-color: #347bff;
 }
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus.oo-ui-toggleWidget-on:before {
-       border-color: #ffffff;
-}
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active,
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover {
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on {
        background-color: #347bff;
        border-color: #347bff;
 }
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active .oo-ui-toggleSwitchWidget-grip,
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover .oo-ui-toggleSwitchWidget-grip {
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
        background-color: #ffffff;
+       border-color: #ffffff;
        box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
 }
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:hover {
+       background-color: #2962cc;
+       border-color: #2962cc;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:active,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:active:hover {
+       background-color: #1f4999;
+       border-color: #1f4999;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:focus {
+       border-color: #347bff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:focus:before {
+       border-color: #ffffff;
+}
 .oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
        background-color: #dddddd;
        border-color: #dddddd;
 .oo-ui-selectFileWidget .oo-ui-selectFileWidget-clearButton {
        z-index: 2;
 }
-.oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget {
        cursor: default;
        height: 5.5em;
        padding: 0;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
        display: none;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
        height: 5.5em;
        width: 5.5em;
        position: absolute;
        background-size: cover;
        background-position: center center;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
        background-size: auto;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
        opacity: 0.4;
        background-color: #cccccc;
        height: 5.5em;
        width: 5.5em;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
        border: 0;
        background: none;
        display: block;
        width: auto;
        margin-left: 5.5em;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
        position: relative;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileName {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileName {
        display: block;
        padding-right: 2.375em;
        overflow: hidden;
        text-overflow: ellipsis;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileType {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileType {
        display: block;
        float: none;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
        position: absolute;
        right: 0.5em;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
        display: none;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
        display: block;
        margin: 0.7em;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
        text-align: center;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
        margin: 0;
 }
 .oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-clearButton,
 .oo-ui-selectFileWidget-empty.oo-ui-widget-enabled .oo-ui-selectFileWidget-dropLabel {
        display: block;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
        -webkit-touch-callout: none;
        -webkit-user-select: none;
           -moz-user-select: none;
            -ms-user-select: none;
                user-select: none;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
        cursor: no-drop;
 }
 .oo-ui-selectFileWidget:last-child {
        right: 2em;
        padding-left: 0;
 }
-.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop.oo-ui-selectFileWidget-dropTarget {
        background-color: #ebf2ff;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
        border-color: #dddddd;
        background-color: #f3f3f3;
 }
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
-.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
-.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel {
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel {
        color: #cccccc;
        text-shadow: 0 1px 1px #ffffff;
 }
-.oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget {
        background-color: #ffffff;
        border: 1px solid #cccccc;
        margin-bottom: 0.5em;
        overflow: hidden;
        border-radius: 2px;
 }
-.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
        border-radius: 2px;
 }
-.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget {
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget {
        background-color: #eeeeee;
        border-style: dashed;
 }
 .oo-ui-numberInputWidget-field > .oo-ui-textInputWidget {
        width: 100%;
 }
-.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"]::-webkit-outer-spin-button,
-.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"]::-webkit-inner-spin-button {
-       -webkit-appearance: none;
-       margin: 0;
-}
-.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"] {
-       -moz-appearance: textfield;
-}
 .oo-ui-numberInputWidget-field > .oo-ui-buttonWidget {
        white-space: nowrap;
 }
index 8d93b80..cd62339 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:03Z
+ * Date: 2016-08-03T16:38:22Z
  */
 ( function ( OO ) {
 
@@ -4365,8 +4365,8 @@ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {
                this.selectButton.setIcon( 'upload' );
                this.$thumbnail = $( '<div>' ).addClass( 'oo-ui-selectFileWidget-thumbnail' );
                this.setPendingElement( this.$thumbnail );
-               this.$dropTarget = $( '<div>' )
-                       .addClass( 'oo-ui-selectFileWidget-dropTarget' )
+               this.$element
+                       .addClass( 'oo-ui-selectFileWidget-dropTarget oo-ui-selectFileWidget' )
                        .on( {
                                click: this.onDropTargetClick.bind( this )
                        } )
@@ -4378,7 +4378,6 @@ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {
                                        .addClass( 'oo-ui-selectFileWidget-dropLabel' )
                                        .text( OO.ui.msg( 'ooui-selectfile-dragdrop-placeholder' ) )
                        );
-               this.$element.append( this.$dropTarget );
        } else {
                this.$element
                        .addClass( 'oo-ui-selectFileWidget' )
@@ -4504,12 +4503,12 @@ OO.ui.SelectFileWidget.prototype.updateUI = function () {
                                }.bind( this ) ).always( function () {
                                        this.popPending();
                                }.bind( this ) );
-                               this.$dropTarget.off( 'click' );
+                               this.$element.off( 'click' );
                        }
                } else {
                        if ( this.showDropTarget ) {
-                               this.$dropTarget.off( 'click' );
-                               this.$dropTarget.on( {
+                               this.$element.off( 'click' );
+                               this.$element.on( {
                                        click: this.onDropTargetClick.bind( this )
                                } );
                                this.$thumbnail
@@ -5053,24 +5052,20 @@ OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
                this.minusButton = new OO.ui.ButtonWidget( $.extend(
                        {
                                disabled: this.isDisabled(),
-                               tabIndex: -1
-                       },
-                       config.minusButton,
-                       {
+                               tabIndex: -1,
                                classes: [ 'oo-ui-numberInputWidget-minusButton' ],
                                label: '−'
-                       }
+                       },
+                       config.minusButton
                ) );
                this.plusButton = new OO.ui.ButtonWidget( $.extend(
                        {
                                disabled: this.isDisabled(),
-                               tabIndex: -1
-                       },
-                       config.plusButton,
-                       {
+                               tabIndex: -1,
                                classes: [ 'oo-ui-numberInputWidget-plusButton' ],
                                label: '+'
-                       }
+                       },
+                       config.plusButton
                ) );
        }
 
index 66cd523..55f891a 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-actionWidget.oo-ui-pendingElement-pending {
        background-image: /* @embed */ url(themes/apex/images/textures/pending.gif);
index 30bf1c4..0d3976f 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:07Z
+ * Date: 2016-08-03T16:38:27Z
  */
 .oo-ui-window {
        background: transparent;
        text-align: left;
 }
 .oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
-       border-right: 1px solid #e5e5e5;
+       border-right: 1px solid #cccccc;
        margin: 0;
 }
 .oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
        border-right-width: 0;
 }
 .oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
-       border-bottom: 1px solid #e5e5e5;
+       border-bottom: 1px solid #cccccc;
        margin: 0;
 }
 .oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
index 6446302..0e9dbf1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.17.6
+ * OOjs UI v0.17.7
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-07-12T20:26:03Z
+ * Date: 2016-08-03T16:38:22Z
  */
 ( function ( OO ) {
 
diff --git a/resources/lib/oojs-ui/themes/apex/icons-alerts.json b/resources/lib/oojs-ui/themes/apex/icons-alerts.json
new file mode 100644 (file)
index 0000000..892b8db
--- /dev/null
@@ -0,0 +1,34 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import '../../../../src/styles/common';",
+       "images": {
+               "bell": { "file": "images/icons/bell.svg" },
+               "bellOn": { "file": {
+                       "ltr": "images/icons/bellOn-ltr.svg",
+                       "rtl": "images/icons/bellOn-rtl.svg"
+               } },
+               "eye": { "file": "images/icons/eye.svg" },
+               "eyeClosed": { "file": "images/icons/eyeClosed.svg" },
+               "message": { "file": {
+                       "ltr": "images/icons/message-ltr.svg",
+                       "rtl": "images/icons/message-rtl.svg"
+               } },
+               "signature": { "file": {
+                       "ltr": "images/icons/signature-ltr.svg",
+                       "rtl": "images/icons/signature-rtl.svg"
+               } },
+               "speechBubble": { "file": {
+                       "ltr": "images/icons/speechBubble-ltr.svg",
+                       "rtl": "images/icons/speechBubble-rtl.svg"
+               } },
+               "speechBubbleAdd": { "file": {
+                       "ltr": "images/icons/speechBubbleAdd-ltr.svg",
+                       "rtl": "images/icons/speechBubbleAdd-rtl.svg"
+               } },
+               "speechBubbles": { "file": {
+                       "ltr": "images/icons/speechBubbles-ltr.svg",
+                       "rtl": "images/icons/speechBubbles-rtl.svg"
+               } },
+               "tray": { "file": "images/icons/tray.svg" }
+       }
+}
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/bell.png b/resources/lib/oojs-ui/themes/apex/images/icons/bell.png
new file mode 100644 (file)
index 0000000..91e8397
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/bell.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/bell.svg b/resources/lib/oojs-ui/themes/apex/images/icons/bell.svg
new file mode 100644 (file)
index 0000000..09b65f2
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png
new file mode 100644 (file)
index 0000000..fb13de1
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg
new file mode 100644 (file)
index 0000000..855581b
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png
new file mode 100644 (file)
index 0000000..b05fd4c
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg
new file mode 100644 (file)
index 0000000..e1f2961
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/eye.png b/resources/lib/oojs-ui/themes/apex/images/icons/eye.png
new file mode 100644 (file)
index 0000000..62c82c0
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/eye.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/eye.svg b/resources/lib/oojs-ui/themes/apex/images/icons/eye.svg
new file mode 100644 (file)
index 0000000..343e9cf
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M12 8c-5 0-11 6-11 6s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+    <circle cx="12" cy="14" r="2"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png b/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png
new file mode 100644 (file)
index 0000000..1ac37d6
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg b/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg
new file mode 100644 (file)
index 0000000..d17f2c8
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png
new file mode 100644 (file)
index 0000000..2171c1f
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg
new file mode 100644 (file)
index 0000000..842d312
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png
new file mode 100644 (file)
index 0000000..fba7920
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg
new file mode 100644 (file)
index 0000000..0a22c75
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png
new file mode 100644 (file)
index 0000000..f68a7bf
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg
new file mode 100644 (file)
index 0000000..03b34cf
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png
new file mode 100644 (file)
index 0000000..9166e8d
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg
new file mode 100644 (file)
index 0000000..326281a
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png
new file mode 100644 (file)
index 0000000..2eedf9f
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg
new file mode 100644 (file)
index 0000000..83d47c1
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png
new file mode 100644 (file)
index 0000000..0d14443
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg
new file mode 100644 (file)
index 0000000..e7dd668
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png
new file mode 100644 (file)
index 0000000..aafac18
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg
new file mode 100644 (file)
index 0000000..c7134c3
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png
new file mode 100644 (file)
index 0000000..9254844
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg
new file mode 100644 (file)
index 0000000..08462e0
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png
new file mode 100644 (file)
index 0000000..f2e0564
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg
new file mode 100644 (file)
index 0000000..d683218
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png
new file mode 100644 (file)
index 0000000..9c67f3f
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg
new file mode 100644 (file)
index 0000000..db548a4
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/tray.png b/resources/lib/oojs-ui/themes/apex/images/icons/tray.png
new file mode 100644 (file)
index 0000000..e5c5e8f
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/tray.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/tray.svg b/resources/lib/oojs-ui/themes/apex/images/icons/tray.svg
new file mode 100644 (file)
index 0000000..d7ab69b
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</svg>
index 79f644e..6894d6e 100644 (file)
@@ -35,6 +35,7 @@
                "speechBubbles": { "file": {
                        "ltr": "images/icons/speechBubbles-ltr.svg",
                        "rtl": "images/icons/speechBubbles-rtl.svg"
-               } }
+               } },
+               "tray": { "file": "images/icons/tray.svg" }
        }
 }
index 2f0c960..05911d3 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.png differ
index 7ed3635..645c9cc 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
-    <path d="M17.5 14V9c0-3-2.3-5-5.5-5S6.5 6 6.5 9v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 20H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+    <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
 </svg>
index b86d5f7..91e8397 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.png differ
index 787ed14..09b65f2 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-    <path d="M17.5 14V9c0-3-2.3-5-5.5-5S6.5 6 6.5 9v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 20H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+    <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
 </svg>
index 1c0de72..fb21370 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.png differ
index c032294..07de130 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
-    <path d="M17.8 14.7l1.7-4.7c1-2.8-.5-5.5-3.5-6.6s-5.9 0-6.9 2.8l-1.7 4.7c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 19.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+    <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
 </svg>
index 1f9ae71..fb13de1 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.png differ
index f68a8e0..855581b 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-    <path d="M17.8 14.7l1.7-4.7c1-2.8-.5-5.5-3.5-6.6s-5.9 0-6.9 2.8l-1.7 4.7c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 19.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+    <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
 </svg>
index c21e1c0..d0ebae5 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.png differ
index 34ec94b..30617cb 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
-    <path d="M6.21 14.7L4.51 10c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+    <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
 </svg>
index 81d9a0a..b05fd4c 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.png differ
index 92bcef5..e1f2961 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-    <path d="M6.21 14.7L4.51 10c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+    <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
 </svg>
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.png
new file mode 100644 (file)
index 0000000..6196d39
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray-invert.svg
new file mode 100644 (file)
index 0000000..9cd3854
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+    <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.png
new file mode 100644 (file)
index 0000000..e5c5e8f
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tray.svg
new file mode 100644 (file)
index 0000000..d7ab69b
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</svg>
index 6ff2e01..e52d6a7 100644 (file)
@@ -197,7 +197,7 @@ $.fn.updateTooltipAccessKeys.getAccessKeyLabel = getAccessKeyLabel;
  * getAccessKeyPrefix
  *
  * @method updateTooltipAccessKeys_getAccessKeyPrefix
- * @deprecated 1.27 Use #getAccessKeyModifiers
+ * @deprecated since 1.27 Use #getAccessKeyModifiers
  */
 $.fn.updateTooltipAccessKeys.getAccessKeyPrefix = function ( ua ) {
        return getAccessKeyModifiers( ua ).join( '-' ) + '-';
index fc16377..8fcc667 100644 (file)
@@ -704,7 +704,6 @@ ol:lang(or) li {
 #mw-revision-info-current,
 #mw-revision-nav {
        direction: ltr;
-       display: inline;
 }
 
 /* Images */
index 2bb1d2e..ef540a8 100644 (file)
@@ -134,6 +134,7 @@ $wgAutoloadClasses += [
        'MockSvgHandler' => "$testDir/phpunit/mocks/media/MockSvgHandler.php",
        'MockDjVuHandler' => "$testDir/phpunit/mocks/media/MockDjVuHandler.php",
        'MockOggHandler' => "$testDir/phpunit/mocks/media/MockOggHandler.php",
+       'MockMediaHandlerFactory' => "$testDir/phpunit/mocks/media/MockMediaHandlerFactory.php",
        'MockWebRequest' => "$testDir/phpunit/mocks/MockWebRequest.php",
        'MediaWiki\\Session\\DummySessionBackend'
                => "$testDir/phpunit/mocks/session/DummySessionBackend.php",
index 8dfe628..27f1454 100644 (file)
@@ -341,7 +341,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
 
                // TODO: move global state into MediaWikiServices
                RequestContext::resetMain();
-               MediaHandler::resetCache();
                if ( session_id() !== '' ) {
                        session_write_close();
                        session_id( '' );
@@ -530,7 +529,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
 
                // TODO: move global state into MediaWikiServices
                RequestContext::resetMain();
-               MediaHandler::resetCache();
                if ( session_id() !== '' ) {
                        session_write_close();
                        session_id( '' );
@@ -1775,4 +1773,15 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                return $buffer;
        }
 
+       /**
+        * Create a temporary hook handler which will be reset by tearDown.
+        * This replaces other handlers for the same hook.
+        * @param string $hookName Hook name
+        * @param mixed $handler Value suitable for a hook handler
+        * @since 1.28
+        */
+       protected function setTemporaryHook( $hookName, $handler ) {
+               $this->mergeMwGlobalArrayValue( 'wgHooks', [ $hookName => [ $handler ] ] );
+       }
+
 }
index a61b328..9d9815b 100644 (file)
@@ -18,9 +18,6 @@ class WfThumbIsStandardTest extends MediaWikiTestCase {
                                [ 300, 225 ],
                                [ 800, 600 ],
                        ],
-                       'wgMediaHandlers' => [
-                               'unknown/unknown' => 'MockBitmapHandler',
-                       ],
                ] );
        }
 
@@ -95,6 +92,7 @@ class WfThumbIsStandardTest extends MediaWikiTestCase {
         * @dataProvider provideThumbParams
         */
        public function testIsStandard( $message, $expected, $params ) {
+               $this->setService( 'MediaHandlerFactory', new MockMediaHandlerFactory() );
                $this->assertSame(
                        $expected,
                        wfThumbIsStandard( new FakeDimensionFile( [ 2000, 1800 ] ), $params ),
index d20344d..ac8c43b 100644 (file)
@@ -316,6 +316,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                        'DBLoadBalancer' => [ 'DBLoadBalancer', 'LoadBalancer' ],
                        'WatchedItemStore' => [ 'WatchedItemStore', WatchedItemStore::class ],
                        'WatchedItemQueryService' => [ 'WatchedItemQueryService', WatchedItemQueryService::class ],
+                       'MediaHandlerFactory' => [ 'MediaHandlerFactory', MediaHandlerFactory::class ],
                        'GenderCache' => [ 'GenderCache', GenderCache::class ],
                        'LinkCache' => [ 'LinkCache', LinkCache::class ],
                        'LinkRenderer' => [ 'LinkRenderer', LinkRenderer::class ],
index 545b964..bb9050f 100644 (file)
@@ -3,6 +3,7 @@ use MediaWiki\MediaWikiServices;
 
 /**
  * @group ContentHandler
+ * @group Database
  */
 class ContentHandlerTest extends MediaWikiTestCase {
 
@@ -52,6 +53,11 @@ class ContentHandlerTest extends MediaWikiTestCase {
                parent::tearDown();
        }
 
+       public function addDBDataOnce() {
+               $this->insertPage( 'Not_Main_Page', 'This is not a main page' );
+               $this->insertPage( 'Smithee', 'A smithee is one who smiths. See also [[Alan Smithee]]' );
+       }
+
        public static function dataGetDefaultModelFor() {
                return [
                        [ 'Help:Foo', CONTENT_MODEL_WIKITEXT ],
@@ -409,4 +415,39 @@ class ContentHandlerTest extends MediaWikiTestCase {
                $this->assertInstanceOf( $handlerClass, $handler );
        }
 
+       /**
+        * @covers ContentHandler::getDataForSearchIndex
+        */
+       public function testDataIndexFields() {
+               $mockEngine = $this->getMock( 'SearchEngine' );
+               $title = Title::newFromText( 'Not_Main_Page', NS_MAIN );
+               $page = new WikiPage( $title );
+
+               $this->setTemporaryHook( 'SearchDataForIndex',
+                       function ( &$fields, ContentHandler $handler, WikiPage $page, ParserOutput $output,
+                                  SearchEngine $engine ) {
+                               $fields['testDataField'] = 'test content';
+                       } );
+
+               $output = $page->getContent()->getParserOutput( $title );
+               $data = $page->getContentHandler()->getDataForSearchIndex( $page, $output, $mockEngine );
+               $this->assertArrayHasKey( 'text', $data );
+               $this->assertArrayHasKey( 'text_bytes', $data );
+               $this->assertArrayHasKey( 'language', $data );
+               $this->assertArrayHasKey( 'testDataField', $data );
+               $this->assertEquals( 'test content', $data['testDataField'] );
+       }
+
+       /**
+        * @covers ContentHandler::getParserOutputForIndexing
+        */
+       public function testParserOutputForIndexing() {
+               $title = Title::newFromText( 'Smithee', NS_MAIN );
+               $page = new WikiPage( $title );
+
+               $out = $page->getContentHandler()->getParserOutputForIndexing( $page );
+               $this->assertInstanceOf( ParserOutput::class, $out );
+               $this->assertContains( 'one who smiths', $out->getRawText() );
+       }
+
 }
index e8681c7..918815c 100644 (file)
@@ -49,5 +49,4 @@ class TextContentHandlerTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'test', $mappedFields['language']['testData'] );
                $this->assertEquals( 'language', $mappedFields['language']['name'] );
        }
-
 }
index f632882..9d4abe8 100644 (file)
@@ -243,4 +243,20 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase {
        ) {
        }
        */
+
+       public function testDataIndexFieldsFile() {
+               $mockEngine = $this->getMock( 'SearchEngine' );
+               $title = Title::newFromText( 'Somefile.jpg', NS_FILE );
+               $page = new WikiPage( $title );
+
+               $handler = $this->getMockBuilder( WikitextContentHandler::class )
+                       ->disableOriginalConstructor()
+                       ->setMethods( [ 'getFileText' ] )
+                       ->getMock();
+               $handler->method( 'getFileText' )->will( $this->returnValue( 'This is file content' ) );
+
+               $data = $handler->getDataForSearchIndex( $page, new ParserOutput(), $mockEngine );
+               $this->assertArrayHasKey( 'file_text', $data );
+               $this->assertEquals( 'This is file content', $data['file_text'] );
+       }
 }
diff --git a/tests/phpunit/includes/content/WikitextStructureTest.php b/tests/phpunit/includes/content/WikitextStructureTest.php
new file mode 100644 (file)
index 0000000..d4647f1
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+
+class WikitextStructureTest extends MediaWikiLangTestCase {
+
+       private function getMockTitle() {
+               return Title::newFromText( "TestTitle" );
+       }
+
+       /**
+        * Get parser output for Wiki text
+        * @param $text
+        * @return ParserOutput
+        */
+       private function getParserOutput( $text ) {
+               $content = new WikitextContent( $text );
+               return $content->getParserOutput( $this->getMockTitle() );
+       }
+
+       /**
+        * Get WikitextStructure for given text
+        * @param $text
+        * @return WikiTextStructure
+        */
+       private function getStructure( $text ) {
+               return new WikiTextStructure( $this->getParserOutput( $text ) );
+       }
+
+       public function testCategories() {
+               $text = <<<END
+We also have a {{Template}} and an {{Another template}} in addition. 
+This text also has [[Category:Some Category| ]] and then [[Category:Yet another category]].
+And [[Category:Some Category| this category]] is repeated.
+END;
+               $struct = $this->getStructure( $text );
+               $cats = $struct->categories();
+               $this->assertCount( 2, $cats );
+               $this->assertContains( "Some Category", $cats );
+               $this->assertContains( "Yet another category", $cats );
+       }
+
+       public function testOutgoingLinks() {
+               $text = <<<END
+Here I add link to [[Some Page]]. And [[Some Page|This same page]] gets linked twice. 
+We also have [[File:Image.jpg|image]].
+We also have a {{Template}} and an {{Another template}} in addition. 
+Some templates are {{lowercase}}.
+And [[Some_Page]] is linked again. 
+It also has [[Category:Some Category| ]] and then [[Category:Yet another category]].
+Also link to a [[Talk:TestTitle|talk page]] is here. 
+END;
+               $struct = $this->getStructure( $text );
+               $links = $struct->outgoingLinks();
+               $this->assertContains( "Some_Page", $links );
+               $this->assertContains( "Template:Template", $links );
+               $this->assertContains( "Template:Another_template", $links );
+               $this->assertContains( "Template:Lowercase", $links );
+               $this->assertContains( "Talk:TestTitle", $links );
+               $this->assertCount( 5, $links );
+       }
+
+       public function testTemplates() {
+               $text = <<<END
+We have a {{Template}} and an {{Another template}} in addition. 
+Some templates are {{lowercase}}. And this {{Template}} is repeated. 
+Here is {{another_template|with=argument}}.
+This is a template that {{Xdoes not exist}}.
+END;
+               $this->setTemporaryHook( 'TitleExists', function ( Title $title, &$exists ) {
+                       $txt = $title->getBaseText();
+                       if ( $txt[0] != 'X' ) {
+                               $exists = true;
+                       }
+                       return true;
+               } );
+               $struct = $this->getStructure( $text );
+               $templates = $struct->templates();
+               $this->assertCount( 3, $templates );
+               $this->assertContains( "Template:Template", $templates );
+               $this->assertContains( "Template:Another template", $templates );
+               $this->assertContains( "Template:Lowercase", $templates );
+       }
+
+       public function testHeadings() {
+               $text = <<<END
+Some text here
+== Heading one ==
+Some text
+==== heading two ====
+More text
+=== Applicability of the strict mass-energy equivalence formula, ''E'' = ''mc''<sup>2</sup> ===
+and more text
+== Wikitext '''in''' [[Heading]] and also <b>html</b> ==
+more text
+END;
+// FIXME: add test for ==== See also ==== after cirrussearch-ignored-headings is renamed
+               $struct = $this->getStructure( $text );
+               $headings = $struct->headings();
+               $this->assertCount( 4, $headings );
+               $this->assertContains( "Heading one", $headings );
+               $this->assertContains( "heading two", $headings );
+               $this->assertContains( "Applicability of the strict mass-energy equivalence formula, E = mc2",
+                       $headings );
+               $this->assertContains( "Wikitext in Heading and also html", $headings );
+       }
+
+       public function testHeadingsFirst() {
+               $text = <<<END
+== Heading one ==
+Some text
+==== heading two ====
+END;
+               $struct = $this->getStructure( $text );
+               $headings = $struct->headings();
+               $this->assertCount( 2, $headings );
+               $this->assertContains( "Heading one", $headings );
+               $this->assertContains( "heading two", $headings );
+       }
+
+       public function testHeadingsNone() {
+               $text = "This text is completely devoid of headings.";
+               $struct = $this->getStructure( $text );
+               $headings = $struct->headings();
+               $this->assertArrayEquals( [], $headings );
+       }
+
+       public function testTexts() {
+               $text = <<<END
+Opening text is opening.
+== Then comes header ==
+Then we got more<br>text
+=== And more headers ===
+{| class="wikitable"
+|-
+! Header table
+|-
+| row in table
+|-
+| another row in table
+|}
+END;
+               $struct = $this->getStructure( $text );
+               $this->assertEquals( "Opening text is opening.", $struct->getOpeningText() );
+               $this->assertEquals( "Opening text is opening.   Then we got more text",
+                       $struct->getMainText() );
+               $this->assertEquals( [ "Header table  row in table  another row in table" ],
+                       $struct->getAuxiliaryText() );
+       }
+}
index c56626f..e7abd15 100644 (file)
@@ -1,4 +1,7 @@
 <?php
+
+use MediaWiki\MediaWikiServices;
+
 /**
  * Although marked as a stub, can work independently.
  *
@@ -127,22 +130,6 @@ class NewParserTest extends MediaWikiTestCase {
                        $tmpGlobals['wgStyleDirectory'] = "$IP/skins";
                }
 
-               # Replace all media handlers with a mock. We do not need to generate
-               # actual thumbnails to do parser testing, we only care about receiving
-               # a ThumbnailImage properly initialized.
-               global $wgMediaHandlers;
-               foreach ( $wgMediaHandlers as $type => $handler ) {
-                       $tmpGlobals['wgMediaHandlers'][$type] = 'MockBitmapHandler';
-               }
-               // Vector images have to be handled slightly differently
-               $tmpGlobals['wgMediaHandlers']['image/svg+xml'] = 'MockSvgHandler';
-
-               // DjVu images have to be handled slightly differently
-               $tmpGlobals['wgMediaHandlers']['image/vnd.djvu'] = 'MockDjVuHandler';
-
-               // Ogg video/audio increasingly more differently
-               $tmpGlobals['wgMediaHandlers']['application/ogg'] = 'MockOggHandler';
-
                $tmpHooks = $wgHooks;
                $tmpHooks['ParserTestParser'][] = 'ParserTestParserHook::setup';
                $tmpHooks['ParserGetVariableValueTs'][] = 'ParserTest::getFakeTimestamp';
@@ -177,6 +164,13 @@ class NewParserTest extends MediaWikiTestCase {
                MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
                $wgContLang->resetNamespaces(); # reset namespace cache
                ParserTest::resetTitleServices();
+               MediaWikiServices::getInstance()->disableService( 'MediaHandlerFactory' );
+               MediaWikiServices::getInstance()->redefineService(
+                       'MediaHandlerFactory',
+                       function() {
+                               return new MockMediaHandlerFactory();
+                       }
+               );
        }
 
        protected function tearDown() {
@@ -196,6 +190,7 @@ class NewParserTest extends MediaWikiTestCase {
 
                // Restore message cache (temporary pages and $wgUseDatabaseMessages)
                MessageCache::destroyInstance();
+               MediaWikiServices::getInstance()->resetServiceForTesting( 'MediaHandlerFactory' );
 
                parent::tearDown();
 
index 2dec02b..e216ced 100644 (file)
@@ -27,6 +27,15 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                return [
                        'noTemplateModule' => [],
 
+                       'deprecatedModule' => $base + [
+                               'deprecated' => true,
+                       ],
+                       'deprecatedTomorrow' => $base + [
+                               'deprecated' => [
+                                       'message' => 'Will be removed tomorrow.'
+                               ],
+                       ],
+
                        'htmlTemplateModule' => $base + [
                                'templates' => [
                                        'templates/template.html',
@@ -96,6 +105,34 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                $this->assertEquals( $rl->getDependencies(), $expected );
        }
 
+       public static function providerDeprecatedModules() {
+               return [
+                       [
+                               'deprecatedModule',
+                               'mw.log.warn("This page is using the deprecated ResourceLoader module \"deprecatedModule\".");',
+                       ],
+                       [
+                               'deprecatedTomorrow',
+                               'mw.log.warn(' .
+                                       '"This page is using the deprecated ResourceLoader module \"deprecatedTomorrow\".\\n' .
+                                       "Will be removed tomorrow." .
+                                       '");'
+                       ]
+               ];
+       }
+
+       /**
+        * @dataProvider providerDeprecatedModules
+        * @covers ResourceLoaderFileModule::getScripts
+        */
+       public function testDeprecatedModules( $name, $expected ) {
+               $modules = self::getModules();
+               $rl = new ResourceLoaderFileModule( $modules[$name] );
+               $rl->setName( $name );
+               $ctx = $this->getResourceLoaderContext( 'en', 'ltr' );
+               $this->assertEquals( $rl->getScript( $ctx ), $expected );
+       }
+
        /**
         * @covers ResourceLoaderFileModule::getAllStyleFiles
         * @covers ResourceLoaderFileModule::getAllSkinStyleFiles
index f084c64..081cb38 100644 (file)
@@ -185,8 +185,12 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                        ->willReturnCallback( $mockFieldBuilder );
 
                // Not using mock since PHPUnit mocks do not work properly with references in params
-               $this->mergeMwGlobalArrayValue( 'wgHooks',
-                       [ 'SearchIndexFields' => [ [ $this, 'hookSearchIndexFields', $mockFieldBuilder ] ] ] );
+               $this->setTemporaryHook( 'SearchIndexFields',
+                       function ( &$fields, SearchEngine $engine ) use ( $mockFieldBuilder ) {
+                               $fields['testField'] =
+                                       $mockFieldBuilder( "testField", SearchIndexField::INDEX_TYPE_TEXT );
+                               return true;
+                       } );
 
                $fields = $mockEngine->getSearchIndexFields();
                $this->assertArrayHasKey( 'language', $fields );
@@ -197,9 +201,4 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                $this->assertArrayHasKey( 'testData', $mapping );
                $this->assertEquals( 'test', $mapping['testData'] );
        }
-
-       public function hookSearchIndexFields( $mockFieldBuilder, &$fields, SearchEngine $engine ) {
-               $fields['testField'] = $mockFieldBuilder( "testField", SearchIndexField::INDEX_TYPE_TEXT );
-               return true;
-       }
 }
diff --git a/tests/phpunit/mocks/media/MockMediaHandlerFactory.php b/tests/phpunit/mocks/media/MockMediaHandlerFactory.php
new file mode 100644 (file)
index 0000000..54d46b0
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Media-handling base classes and generic functionality.
+ *
+ * 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
+ * @ingroup Media
+ */
+
+/**
+ * Replace all media handlers with a mock. We do not need to generate
+ * actual thumbnails to do parser testing, we only care about receiving
+ * a ThumbnailImage properly initialized.
+ *
+ * @since 1.28
+ */
+class MockMediaHandlerFactory extends MediaHandlerFactory {
+
+       private static $overrides = [
+               'image/svg+xml' => MockSvgHandler::class,
+               'image/vnd.djvu' => MockDjVuHandler::class,
+               'application/ogg' => MockOggHandler::class,
+       ];
+
+       public function __construct() {
+               // override parent
+       }
+
+       protected function getHandlerClass( $type ) {
+               if ( isset( self::$overrides[$type] ) ) {
+                       return self::$overrides[$type];
+               }
+
+               return MockBitmapHandler::class;
+       }
+
+}
index 58de8e8..f36b51a 100644 (file)
@@ -143,4 +143,15 @@ class AutoLoaderTest extends MediaWikiTestCase {
                $this->assertFalse( $uncerealized instanceof __PHP_Incomplete_Class,
                        "unserialize() can load classes case-insensitively." );
        }
+
+       function testAutoloadOrder() {
+               $path = realpath( __DIR__ . '/../../..' );
+               $oldAutoload = file_get_contents( $path . '/autoload.php' );
+               $generator = new AutoloadGenerator( $path, 'local' );
+               $generator->initMediaWikiDefault();
+               $newAutoload = $generator->getAutoload( 'maintenance/generateLocalAutoload.php' );
+
+               $this->assertEquals( $oldAutoload, $newAutoload, 'autoload.php does not match' .
+                       ' output of generateLocalAutoload.php script.' );
+       }
 }
index 0e23fdd..02934fa 100644 (file)
@@ -8,10 +8,16 @@
 class ExtensionsTestSuite extends PHPUnit_Framework_TestSuite {
        public function __construct() {
                parent::__construct();
+
                $paths = [];
+               // Autodiscover extension unit tests
+               $registry = ExtensionRegistry::getInstance();
+               foreach ( $registry->getAllThings() as $info ) {
+                       $paths[] = dirname( $info['path'] ) . '/tests/phpunit';
+               }
                // Extensions can return a list of files or directories
                Hooks::run( 'UnitTestsList', [ &$paths ] );
-               foreach ( $paths as $path ) {
+               foreach ( array_unique( $paths ) as $path ) {
                        if ( is_dir( $path ) ) {
                                // If the path is a directory, search for test cases.
                                // @since 1.24
@@ -19,7 +25,7 @@ class ExtensionsTestSuite extends PHPUnit_Framework_TestSuite {
                                $fileIterator = new File_Iterator_Facade();
                                $matchingFiles = $fileIterator->getFilesAsArray( $path, $suffixes );
                                $this->addTestFiles( $matchingFiles );
-                       } else {
+                       } elseif ( file_exists( $path ) ) {
                                // Add a single test case or suite class
                                $this->addTestFile( $path );
                        }