Merge "Wrap revision info and nav in a div for easy formatting in MobileFrontend"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 3 Aug 2016 21:17:02 +0000 (21:17 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 3 Aug 2016 21:17:02 +0000 (21:17 +0000)
185 files changed:
RELEASE-NOTES-1.28
autoload.php
composer.json
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/OutputPage.php
includes/Pingback.php
includes/Status.php
includes/api/i18n/gl.json
includes/auth/LocalPasswordPrimaryAuthenticationProvider.php
includes/deferred/CdnCacheUpdate.php
includes/filerepo/FileRepoStatus.php
includes/htmlform/HTMLApiField.php [deleted file]
includes/htmlform/HTMLAutoCompleteSelectField.php [deleted file]
includes/htmlform/HTMLButtonField.php [deleted file]
includes/htmlform/HTMLCheckField.php [deleted file]
includes/htmlform/HTMLCheckMatrix.php [deleted file]
includes/htmlform/HTMLComboboxField.php [deleted file]
includes/htmlform/HTMLEditTools.php [deleted file]
includes/htmlform/HTMLFloatField.php [deleted file]
includes/htmlform/HTMLFormFieldCloner.php [deleted file]
includes/htmlform/HTMLFormFieldWithButton.php [deleted file]
includes/htmlform/HTMLHiddenField.php [deleted file]
includes/htmlform/HTMLInfoField.php [deleted file]
includes/htmlform/HTMLIntField.php [deleted file]
includes/htmlform/HTMLMultiSelectField.php [deleted file]
includes/htmlform/HTMLRadioField.php [deleted file]
includes/htmlform/HTMLSelectAndOtherField.php [deleted file]
includes/htmlform/HTMLSelectField.php [deleted file]
includes/htmlform/HTMLSelectLimitField.php [deleted file]
includes/htmlform/HTMLSelectNamespace.php [deleted file]
includes/htmlform/HTMLSelectNamespaceWithButton.php [deleted file]
includes/htmlform/HTMLSelectOrOtherField.php [deleted file]
includes/htmlform/HTMLSubmitField.php [deleted file]
includes/htmlform/HTMLTagFilter.php [deleted file]
includes/htmlform/HTMLTextAreaField.php [deleted file]
includes/htmlform/HTMLTextField.php [deleted file]
includes/htmlform/HTMLTextFieldWithButton.php [deleted file]
includes/htmlform/HTMLTitleTextField.php [deleted file]
includes/htmlform/HTMLUserTextField.php [deleted file]
includes/htmlform/fields/HTMLApiField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLAutoCompleteSelectField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLButtonField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLCheckField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLCheckMatrix.php [new file with mode: 0644]
includes/htmlform/fields/HTMLComboboxField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLEditTools.php [new file with mode: 0644]
includes/htmlform/fields/HTMLFloatField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLFormFieldCloner.php [new file with mode: 0644]
includes/htmlform/fields/HTMLFormFieldWithButton.php [new file with mode: 0644]
includes/htmlform/fields/HTMLHiddenField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLInfoField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLIntField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLMultiSelectField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLRadioField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSelectAndOtherField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSelectField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSelectLimitField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSelectNamespace.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSelectNamespaceWithButton.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSelectOrOtherField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLSubmitField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLTagFilter.php [new file with mode: 0644]
includes/htmlform/fields/HTMLTextAreaField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLTextField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLTextFieldWithButton.php [new file with mode: 0644]
includes/htmlform/fields/HTMLTitleTextField.php [new file with mode: 0644]
includes/htmlform/fields/HTMLUserTextField.php [new file with mode: 0644]
includes/installer/i18n/gl.json
includes/objectcache/ObjectCache.php
includes/profiler/ProfileSection.php
includes/profiler/ProfilerFunctions.php
includes/resourceloader/ResourceLoaderUserModule.php
includes/resourceloader/ResourceLoaderUserStylesModule.php [new file with mode: 0644]
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/de.json
languages/i18n/diq.json
languages/i18n/en.json
languages/i18n/fa.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/gu.json
languages/i18n/he.json
languages/i18n/hu.json
languages/i18n/kiu.json
languages/i18n/ko.json
languages/i18n/krl.json
languages/i18n/lb.json
languages/i18n/lt.json
languages/i18n/mk.json
languages/i18n/nb.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/sl.json
languages/i18n/sq.json
languages/i18n/tyv.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
tests/phpunit/data/templates/conds.mustache [deleted file]
tests/phpunit/structure/AutoLoaderTest.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 5808040..2587add 100644 (file)
@@ -514,41 +514,41 @@ $wgAutoloadLocalClasses = [
        'GitInfo' => __DIR__ . '/includes/GitInfo.php',
        'GlobalDependency' => __DIR__ . '/includes/cache/CacheDependency.php',
        'GlobalVarConfig' => __DIR__ . '/includes/config/GlobalVarConfig.php',
-       'HTMLApiField' => __DIR__ . '/includes/htmlform/HTMLApiField.php',
-       'HTMLAutoCompleteSelectField' => __DIR__ . '/includes/htmlform/HTMLAutoCompleteSelectField.php',
-       'HTMLButtonField' => __DIR__ . '/includes/htmlform/HTMLButtonField.php',
+       'HTMLApiField' => __DIR__ . '/includes/htmlform/fields/HTMLApiField.php',
+       'HTMLAutoCompleteSelectField' => __DIR__ . '/includes/htmlform/fields/HTMLAutoCompleteSelectField.php',
+       'HTMLButtonField' => __DIR__ . '/includes/htmlform/fields/HTMLButtonField.php',
        'HTMLCacheUpdate' => __DIR__ . '/includes/deferred/HTMLCacheUpdate.php',
        'HTMLCacheUpdateJob' => __DIR__ . '/includes/jobqueue/jobs/HTMLCacheUpdateJob.php',
-       'HTMLCheckField' => __DIR__ . '/includes/htmlform/HTMLCheckField.php',
-       'HTMLCheckMatrix' => __DIR__ . '/includes/htmlform/HTMLCheckMatrix.php',
-       'HTMLComboboxField' => __DIR__ . '/includes/htmlform/HTMLComboboxField.php',
-       'HTMLEditTools' => __DIR__ . '/includes/htmlform/HTMLEditTools.php',
+       'HTMLCheckField' => __DIR__ . '/includes/htmlform/fields/HTMLCheckField.php',
+       'HTMLCheckMatrix' => __DIR__ . '/includes/htmlform/fields/HTMLCheckMatrix.php',
+       'HTMLComboboxField' => __DIR__ . '/includes/htmlform/fields/HTMLComboboxField.php',
+       'HTMLEditTools' => __DIR__ . '/includes/htmlform/fields/HTMLEditTools.php',
        'HTMLFileCache' => __DIR__ . '/includes/cache/HTMLFileCache.php',
-       'HTMLFloatField' => __DIR__ . '/includes/htmlform/HTMLFloatField.php',
+       'HTMLFloatField' => __DIR__ . '/includes/htmlform/fields/HTMLFloatField.php',
        'HTMLForm' => __DIR__ . '/includes/htmlform/HTMLForm.php',
        'HTMLFormField' => __DIR__ . '/includes/htmlform/HTMLFormField.php',
-       'HTMLFormFieldCloner' => __DIR__ . '/includes/htmlform/HTMLFormFieldCloner.php',
+       'HTMLFormFieldCloner' => __DIR__ . '/includes/htmlform/fields/HTMLFormFieldCloner.php',
        'HTMLFormFieldRequiredOptionsException' => __DIR__ . '/includes/htmlform/HTMLFormFieldRequiredOptionsException.php',
-       'HTMLFormFieldWithButton' => __DIR__ . '/includes/htmlform/HTMLFormFieldWithButton.php',
-       'HTMLHiddenField' => __DIR__ . '/includes/htmlform/HTMLHiddenField.php',
-       'HTMLInfoField' => __DIR__ . '/includes/htmlform/HTMLInfoField.php',
-       'HTMLIntField' => __DIR__ . '/includes/htmlform/HTMLIntField.php',
-       'HTMLMultiSelectField' => __DIR__ . '/includes/htmlform/HTMLMultiSelectField.php',
+       'HTMLFormFieldWithButton' => __DIR__ . '/includes/htmlform/fields/HTMLFormFieldWithButton.php',
+       'HTMLHiddenField' => __DIR__ . '/includes/htmlform/fields/HTMLHiddenField.php',
+       'HTMLInfoField' => __DIR__ . '/includes/htmlform/fields/HTMLInfoField.php',
+       'HTMLIntField' => __DIR__ . '/includes/htmlform/fields/HTMLIntField.php',
+       'HTMLMultiSelectField' => __DIR__ . '/includes/htmlform/fields/HTMLMultiSelectField.php',
        'HTMLNestedFilterable' => __DIR__ . '/includes/htmlform/HTMLNestedFilterable.php',
-       'HTMLRadioField' => __DIR__ . '/includes/htmlform/HTMLRadioField.php',
-       'HTMLSelectAndOtherField' => __DIR__ . '/includes/htmlform/HTMLSelectAndOtherField.php',
-       'HTMLSelectField' => __DIR__ . '/includes/htmlform/HTMLSelectField.php',
-       'HTMLSelectLimitField' => __DIR__ . '/includes/htmlform/HTMLSelectLimitField.php',
-       'HTMLSelectNamespace' => __DIR__ . '/includes/htmlform/HTMLSelectNamespace.php',
-       'HTMLSelectNamespaceWithButton' => __DIR__ . '/includes/htmlform/HTMLSelectNamespaceWithButton.php',
-       'HTMLSelectOrOtherField' => __DIR__ . '/includes/htmlform/HTMLSelectOrOtherField.php',
-       'HTMLSubmitField' => __DIR__ . '/includes/htmlform/HTMLSubmitField.php',
-       'HTMLTagFilter' => __DIR__ . '/includes/htmlform/HTMLTagFilter.php',
-       'HTMLTextAreaField' => __DIR__ . '/includes/htmlform/HTMLTextAreaField.php',
-       'HTMLTextField' => __DIR__ . '/includes/htmlform/HTMLTextField.php',
-       'HTMLTextFieldWithButton' => __DIR__ . '/includes/htmlform/HTMLTextFieldWithButton.php',
-       'HTMLTitleTextField' => __DIR__ . '/includes/htmlform/HTMLTitleTextField.php',
-       'HTMLUserTextField' => __DIR__ . '/includes/htmlform/HTMLUserTextField.php',
+       'HTMLRadioField' => __DIR__ . '/includes/htmlform/fields/HTMLRadioField.php',
+       'HTMLSelectAndOtherField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectAndOtherField.php',
+       'HTMLSelectField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectField.php',
+       'HTMLSelectLimitField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectLimitField.php',
+       'HTMLSelectNamespace' => __DIR__ . '/includes/htmlform/fields/HTMLSelectNamespace.php',
+       'HTMLSelectNamespaceWithButton' => __DIR__ . '/includes/htmlform/fields/HTMLSelectNamespaceWithButton.php',
+       'HTMLSelectOrOtherField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectOrOtherField.php',
+       'HTMLSubmitField' => __DIR__ . '/includes/htmlform/fields/HTMLSubmitField.php',
+       'HTMLTagFilter' => __DIR__ . '/includes/htmlform/fields/HTMLTagFilter.php',
+       'HTMLTextAreaField' => __DIR__ . '/includes/htmlform/fields/HTMLTextAreaField.php',
+       'HTMLTextField' => __DIR__ . '/includes/htmlform/fields/HTMLTextField.php',
+       'HTMLTextFieldWithButton' => __DIR__ . '/includes/htmlform/fields/HTMLTextFieldWithButton.php',
+       'HTMLTitleTextField' => __DIR__ . '/includes/htmlform/fields/HTMLTitleTextField.php',
+       'HTMLUserTextField' => __DIR__ . '/includes/htmlform/fields/HTMLUserTextField.php',
        'HWLDFWordAccumulator' => __DIR__ . '/includes/diff/DairikiDiff.php',
        'HashBagOStuff' => __DIR__ . '/includes/libs/objectcache/HashBagOStuff.php',
        'HashConfig' => __DIR__ . '/includes/config/HashConfig.php',
@@ -1169,6 +1169,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',
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 5926328..38ad63b 100644 (file)
@@ -2524,7 +2524,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 d34ace8..753c3b7 100644 (file)
@@ -3650,7 +3650,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 +3665,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 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 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 {
 }
diff --git a/includes/htmlform/HTMLApiField.php b/includes/htmlform/HTMLApiField.php
deleted file mode 100644 (file)
index 24a253e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-
-class HTMLApiField extends HTMLFormField {
-       public function getTableRow( $value ) {
-               return '';
-       }
-
-       public function getDiv( $value ) {
-               return $this->getTableRow( $value );
-       }
-
-       public function getRaw( $value ) {
-               return $this->getTableRow( $value );
-       }
-
-       public function getInputHTML( $value ) {
-               return '';
-       }
-
-       public function hasVisibleOutput() {
-               return false;
-       }
-}
diff --git a/includes/htmlform/HTMLAutoCompleteSelectField.php b/includes/htmlform/HTMLAutoCompleteSelectField.php
deleted file mode 100644 (file)
index 76a88d5..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-<?php
-
-/**
- * Text field for selecting a value from a large list of possible values, with
- * auto-completion and optionally with a select dropdown for selecting common
- * options.
- *
- * HTMLComboboxField implements most of the same functionality and should be
- * used instead, if possible.
- *
- * If one of 'options-messages', 'options', or 'options-message' is provided
- * and non-empty, the select dropdown will be shown. An 'other' key will be
- * appended using message 'htmlform-selectorother-other' if not already
- * present.
- *
- * Besides the parameters recognized by HTMLTextField, the following are
- * recognized:
- *   options-messages - As for HTMLSelectField
- *   options - As for HTMLSelectField
- *   options-message - As for HTMLSelectField
- *   autocomplete - Associative array mapping display text to values.
- *   autocomplete-messages - Like autocomplete, but keys are message names.
- *   require-match - Boolean, if true the value must be in the options or the
- *     autocomplete.
- *   other-message - Message to use instead of htmlform-selectorother-other for
- *      the 'other' message.
- *   other - Raw text to use for the 'other' message
- */
-class HTMLAutoCompleteSelectField extends HTMLTextField {
-       protected $autocomplete = [];
-
-       function __construct( $params ) {
-               $params += [
-                       'require-match' => false,
-               ];
-
-               parent::__construct( $params );
-
-               if ( array_key_exists( 'autocomplete-messages', $this->mParams ) ) {
-                       foreach ( $this->mParams['autocomplete-messages'] as $key => $value ) {
-                               $key = $this->msg( $key )->plain();
-                               $this->autocomplete[$key] = strval( $value );
-                       }
-               } elseif ( array_key_exists( 'autocomplete', $this->mParams ) ) {
-                       foreach ( $this->mParams['autocomplete'] as $key => $value ) {
-                               $this->autocomplete[$key] = strval( $value );
-                       }
-               }
-               if ( !is_array( $this->autocomplete ) || !$this->autocomplete ) {
-                       throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
-               }
-
-               $this->getOptions();
-               if ( $this->mOptions && !in_array( 'other', $this->mOptions, true ) ) {
-                       if ( isset( $params['other-message'] ) ) {
-                               $msg = $this->getMessage( $params['other-message'] )->text();
-                       } elseif ( isset( $params['other'] ) ) {
-                               $msg = $params['other'];
-                       } else {
-                               $msg = wfMessage( 'htmlform-selectorother-other' )->text();
-                       }
-                       $this->mOptions[$msg] = 'other';
-               }
-       }
-
-       function loadDataFromRequest( $request ) {
-               if ( $request->getCheck( $this->mName ) ) {
-                       $val = $request->getText( $this->mName . '-select', 'other' );
-
-                       if ( $val === 'other' ) {
-                               $val = $request->getText( $this->mName );
-                               if ( isset( $this->autocomplete[$val] ) ) {
-                                       $val = $this->autocomplete[$val];
-                               }
-                       }
-
-                       return $val;
-               } else {
-                       return $this->getDefault();
-               }
-       }
-
-       function validate( $value, $alldata ) {
-               $p = parent::validate( $value, $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
-
-               if ( in_array( strval( $value ), $validOptions, true ) ) {
-                       return true;
-               } elseif ( in_array( strval( $value ), $this->autocomplete, true ) ) {
-                       return true;
-               } elseif ( $this->mParams['require-match'] ) {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
-               }
-
-               return true;
-       }
-
-       // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
-       public function getAttributes( array $list ) {
-               $attribs = [
-                       'type' => 'text',
-                       'data-autocomplete' => FormatJson::encode( array_keys( $this->autocomplete ) ),
-               ] + parent::getAttributes( $list );
-
-               if ( $this->getOptions() ) {
-                       $attribs['data-hide-if'] = FormatJson::encode(
-                               [ '!==', $this->mName . '-select', 'other' ]
-                       );
-               }
-
-               return $attribs;
-       }
-
-       function getInputHTML( $value ) {
-               $oldClass = $this->mClass;
-               $this->mClass = (array)$this->mClass;
-
-               $valInSelect = false;
-               $ret = '';
-
-               if ( $this->getOptions() ) {
-                       if ( $value !== false ) {
-                               $value = strval( $value );
-                               $valInSelect = in_array(
-                                       $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
-                               );
-                       }
-
-                       $selected = $valInSelect ? $value : 'other';
-                       $select = new XmlSelect( $this->mName . '-select', $this->mID . '-select', $selected );
-                       $select->addOptions( $this->getOptions() );
-                       $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
-
-                       if ( !empty( $this->mParams['disabled'] ) ) {
-                               $select->setAttribute( 'disabled', 'disabled' );
-                       }
-
-                       if ( isset( $this->mParams['tabindex'] ) ) {
-                               $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
-                       }
-
-                       $ret = $select->getHTML() . "<br />\n";
-
-                       $this->mClass[] = 'mw-htmlform-hide-if';
-               }
-
-               if ( $valInSelect ) {
-                       $value = '';
-               } else {
-                       $key = array_search( strval( $value ), $this->autocomplete, true );
-                       if ( $key !== false ) {
-                               $value = $key;
-                       }
-               }
-
-               $this->mClass[] = 'mw-htmlform-autocomplete';
-               $ret .= parent::getInputHTML( $valInSelect ? '' : $value );
-               $this->mClass = $oldClass;
-
-               return $ret;
-       }
-
-       /**
-        * Get the OOUI version of this input.
-        * @param string $value
-        * @return false
-        */
-       function getInputOOUI( $value ) {
-               // To be implemented, for now override the function from HTMLTextField
-               return false;
-       }
-}
diff --git a/includes/htmlform/HTMLButtonField.php b/includes/htmlform/HTMLButtonField.php
deleted file mode 100644 (file)
index 64fe7ed..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-/**
- * Adds a generic button inline to the form. Does not do anything, you must add
- * click handling code in JavaScript. Use a HTMLSubmitField if you merely
- * wish to add a submit button to a form.
- *
- * Additional recognized configuration parameters include:
- * - flags: OOUI flags for the button, see OOUI\FlaggedElement
- * - buttonlabel-message: Message to use for the button display text, instead
- *   of the value from 'default'. Overrides 'buttonlabel' and 'buttonlabel-raw'.
- * - buttonlabel: Text to display for the button display text, instead
- *   of the value from 'default'. Overrides 'buttonlabel-raw'.
- * - buttonlabel-raw: HTMLto display for the button display text, instead
- *   of the value from 'default'.
- *
- * Note that the buttonlabel parameters are not supported on IE6 and IE7 due to
- * bugs in those browsers. If detected, they will be served buttons using the
- * value of 'default' as the button label.
- *
- * @since 1.22
- */
-class HTMLButtonField extends HTMLFormField {
-       protected $buttonType = 'button';
-       protected $buttonLabel = null;
-
-       /** @var array $mFlags Flags to add to OOUI Button widget */
-       protected $mFlags = [];
-
-       public function __construct( $info ) {
-               $info['nodata'] = true;
-               if ( isset( $info['flags'] ) ) {
-                       $this->mFlags = $info['flags'];
-               }
-
-               # Generate the label from a message, if possible
-               if ( isset( $info['buttonlabel-message'] ) ) {
-                       $this->buttonLabel = $this->getMessage( $info['buttonlabel-message'] )->parse();
-               } elseif ( isset( $info['buttonlabel'] ) ) {
-                       if ( $info['buttonlabel'] === '&#160;' ) {
-                               // Apparently some things set &nbsp directly and in an odd format
-                               $this->buttonLabel = '&#160;';
-                       } else {
-                               $this->buttonLabel = htmlspecialchars( $info['buttonlabel'] );
-                       }
-               } elseif ( isset( $info['buttonlabel-raw'] ) ) {
-                       $this->buttonLabel = $info['buttonlabel-raw'];
-               }
-
-               $this->setShowEmptyLabel( false );
-
-               parent::__construct( $info );
-       }
-
-       public function getInputHTML( $value ) {
-               $flags = '';
-               $prefix = 'mw-htmlform-';
-               if ( $this->mParent instanceof VFormHTMLForm ||
-                       $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' )
-               ) {
-                       $prefix = 'mw-ui-';
-                       // add mw-ui-button separately, so the descriptor doesn't need to set it
-                       $flags .= ' ' . $prefix . 'button';
-               }
-               foreach ( $this->mFlags as $flag ) {
-                       $flags .= ' ' . $prefix . $flag;
-               }
-               $attr = [
-                       'class' => 'mw-htmlform-submit ' . $this->mClass . $flags,
-                       'id' => $this->mID,
-                       'type' => $this->buttonType,
-                       'name' => $this->mName,
-                       'value' => $this->getDefault(),
-               ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
-
-               if ( $this->isBadIE() ) {
-                       return Html::element( 'input', $attr );
-               } else {
-                       return Html::rawElement( 'button', $attr,
-                               $this->buttonLabel ?: htmlspecialchars( $this->getDefault() ) );
-               }
-       }
-
-       /**
-        * Get the OOUI widget for this field.
-        * @param string $value
-        * @return OOUI\ButtonInputWidget
-        */
-       public function getInputOOUI( $value ) {
-               return new OOUI\ButtonInputWidget( [
-                       'name' => $this->mName,
-                       'value' => $this->getDefault(),
-                       'label' => !$this->isBadIE() && $this->buttonLabel
-                               ? new OOUI\HtmlSnippet( $this->buttonLabel )
-                               : $this->getDefault(),
-                       'type' => $this->buttonType,
-                       'classes' => [ 'mw-htmlform-submit', $this->mClass ],
-                       'id' => $this->mID,
-                       'flags' => $this->mFlags,
-                       'useInputTag' => $this->isBadIE(),
-               ] + OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
-               ) );
-       }
-
-       protected function needsLabel() {
-               return false;
-       }
-
-       /**
-        * Button cannot be invalid
-        *
-        * @param string $value
-        * @param array $alldata
-        *
-        * @return bool
-        */
-       public function validate( $value, $alldata ) {
-               return true;
-       }
-
-       /**
-        * IE<8 has bugs with <button>, so we'll need to avoid them.
-        * @return bool Whether the request is from a bad version of IE
-        */
-       private function isBadIE() {
-               $request = $this->mParent
-                       ? $this->mParent->getRequest()
-                       : RequestContext::getMain()->getRequest();
-               return preg_match( '/MSIE [1-7]\./i', $request->getHeader( 'User-Agent' ) );
-       }
-}
diff --git a/includes/htmlform/HTMLCheckField.php b/includes/htmlform/HTMLCheckField.php
deleted file mode 100644 (file)
index a553839..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-<?php
-
-/**
- * A checkbox field
- */
-class HTMLCheckField extends HTMLFormField {
-       function getInputHTML( $value ) {
-               global $wgUseMediaWikiUIEverywhere;
-
-               if ( !empty( $this->mParams['invert'] ) ) {
-                       $value = !$value;
-               }
-
-               $attr = $this->getTooltipAndAccessKey();
-               $attr['id'] = $this->mID;
-
-               $attr += $this->getAttributes( [ 'disabled', 'tabindex' ] );
-
-               if ( $this->mClass !== '' ) {
-                       $attr['class'] = $this->mClass;
-               }
-
-               $attrLabel = [ 'for' => $this->mID ];
-               if ( isset( $attr['title'] ) ) {
-                       // propagate tooltip to label
-                       $attrLabel['title'] = $attr['title'];
-               }
-
-               $chkLabel = Xml::check( $this->mName, $value, $attr ) .
-                       '&#160;' .
-                       Html::rawElement( 'label', $attrLabel, $this->mLabel );
-
-               if ( $wgUseMediaWikiUIEverywhere || $this->mParent instanceof VFormHTMLForm ) {
-                       $chkLabel = Html::rawElement(
-                               'div',
-                               [ 'class' => 'mw-ui-checkbox' ],
-                               $chkLabel
-                       );
-               }
-
-               return $chkLabel;
-       }
-
-       /**
-        * Get the OOUI version of this field.
-        * @since 1.26
-        * @param string $value
-        * @return OOUI\CheckboxInputWidget The checkbox widget.
-        */
-       public function getInputOOUI( $value ) {
-               if ( !empty( $this->mParams['invert'] ) ) {
-                       $value = !$value;
-               }
-
-               $attr = $this->getTooltipAndAccessKey();
-               $attr['id'] = $this->mID;
-               $attr['name'] = $this->mName;
-
-               $attr += OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
-               );
-
-               if ( $this->mClass !== '' ) {
-                       $attr['classes'] = [ $this->mClass ];
-               }
-
-               $attr['selected'] = $value;
-               $attr['value'] = '1'; // Nasty hack, but needed to make this work
-
-               return new OOUI\CheckboxInputWidget( $attr );
-       }
-
-       /**
-        * For a checkbox, the label goes on the right hand side, and is
-        * added in getInputHTML(), rather than HTMLFormField::getRow()
-        *
-        * ...unless OOUI is being used, in which case we actually return
-        * the label here.
-        *
-        * @return string
-        */
-       function getLabel() {
-               if ( $this->mParent instanceof OOUIHTMLForm ) {
-                       return $this->mLabel;
-               } elseif (
-                       $this->mParent instanceof HTMLForm &&
-                       $this->mParent->getDisplayFormat() === 'div'
-               ) {
-                       return '';
-               } else {
-                       return '&#160;';
-               }
-       }
-
-       /**
-        * Get label alignment when generating field for OOUI.
-        * @return string 'left', 'right', 'top' or 'inline'
-        */
-       protected function getLabelAlignOOUI() {
-               return 'inline';
-       }
-
-       /**
-        * checkboxes don't need a label.
-        * @return bool
-        */
-       protected function needsLabel() {
-               return false;
-       }
-
-       /**
-        * @param WebRequest $request
-        *
-        * @return bool
-        */
-       function loadDataFromRequest( $request ) {
-               $invert = isset( $this->mParams['invert'] ) && $this->mParams['invert'];
-
-               // GetCheck won't work like we want for checks.
-               // Fetch the value in either one of the two following case:
-               // - we have a valid submit attempt (form was just submitted, or a GET URL forged by the user)
-               // - checkbox name has a value (false or true), ie is not null
-               if ( $this->isSubmitAttempt( $request ) || $request->getVal( $this->mName ) !== null ) {
-                       return $invert
-                               ? !$request->getBool( $this->mName )
-                               : $request->getBool( $this->mName );
-               } else {
-                       return (bool)$this->getDefault();
-               }
-       }
-}
diff --git a/includes/htmlform/HTMLCheckMatrix.php b/includes/htmlform/HTMLCheckMatrix.php
deleted file mode 100644 (file)
index b324fb6..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-<?php
-
-/**
- * A checkbox matrix
- * Operates similarly to HTMLMultiSelectField, but instead of using an array of
- * options, uses an array of rows and an array of columns to dynamically
- * construct a matrix of options. The tags used to identify a particular cell
- * are of the form "columnName-rowName"
- *
- * Options:
- *   - columns
- *     - Required list of columns in the matrix.
- *   - rows
- *     - Required list of rows in the matrix.
- *   - force-options-on
- *     - Accepts array of column-row tags to be displayed as enabled but unavailable to change
- *   - force-options-off
- *     - Accepts array of column-row tags to be displayed as disabled but unavailable to change.
- *   - tooltips
- *     - Optional array mapping row label to tooltip content
- *   - tooltip-class
- *     - Optional CSS class used on tooltip container span. Defaults to mw-icon-question.
- */
-class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
-       static private $requiredParams = [
-               // Required by underlying HTMLFormField
-               'fieldname',
-               // Required by HTMLCheckMatrix
-               'rows',
-               'columns'
-       ];
-
-       public function __construct( $params ) {
-               $missing = array_diff( self::$requiredParams, array_keys( $params ) );
-               if ( $missing ) {
-                       throw new HTMLFormFieldRequiredOptionsException( $this, $missing );
-               }
-               parent::__construct( $params );
-       }
-
-       function validate( $value, $alldata ) {
-               $rows = $this->mParams['rows'];
-               $columns = $this->mParams['columns'];
-
-               // Make sure user-defined validation callback is run
-               $p = parent::validate( $value, $alldata );
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               // Make sure submitted value is an array
-               if ( !is_array( $value ) ) {
-                       return false;
-               }
-
-               // If all options are valid, array_intersect of the valid options
-               // and the provided options will return the provided options.
-               $validOptions = [];
-               foreach ( $rows as $rowTag ) {
-                       foreach ( $columns as $columnTag ) {
-                               $validOptions[] = $columnTag . '-' . $rowTag;
-                       }
-               }
-               $validValues = array_intersect( $value, $validOptions );
-               if ( count( $validValues ) == count( $value ) ) {
-                       return true;
-               } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
-               }
-       }
-
-       /**
-        * Build a table containing a matrix of checkbox options.
-        * The value of each option is a combination of the row tag and column tag.
-        * mParams['rows'] is an array with row labels as keys and row tags as values.
-        * mParams['columns'] is an array with column labels as keys and column tags as values.
-        *
-        * @param array $value Array of the options that should be checked
-        *
-        * @return string
-        */
-       function getInputHTML( $value ) {
-               $html = '';
-               $tableContents = '';
-               $rows = $this->mParams['rows'];
-               $columns = $this->mParams['columns'];
-
-               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
-
-               // Build the column headers
-               $headerContents = Html::rawElement( 'td', [], '&#160;' );
-               foreach ( $columns as $columnLabel => $columnTag ) {
-                       $headerContents .= Html::rawElement( 'td', [], $columnLabel );
-               }
-               $tableContents .= Html::rawElement( 'tr', [], "\n$headerContents\n" );
-
-               $tooltipClass = 'mw-icon-question';
-               if ( isset( $this->mParams['tooltip-class'] ) ) {
-                       $tooltipClass = $this->mParams['tooltip-class'];
-               }
-
-               // Build the options matrix
-               foreach ( $rows as $rowLabel => $rowTag ) {
-                       // Append tooltip if configured
-                       if ( isset( $this->mParams['tooltips'][$rowLabel] ) ) {
-                               $tooltipAttribs = [
-                                       'class' => "mw-htmlform-tooltip $tooltipClass",
-                                       'title' => $this->mParams['tooltips'][$rowLabel],
-                               ];
-                               $rowLabel .= ' ' . Html::element( 'span', $tooltipAttribs, '' );
-                       }
-                       $rowContents = Html::rawElement( 'td', [], $rowLabel );
-                       foreach ( $columns as $columnTag ) {
-                               $thisTag = "$columnTag-$rowTag";
-                               // Construct the checkbox
-                               $thisAttribs = [
-                                       'id' => "{$this->mID}-$thisTag",
-                                       'value' => $thisTag,
-                               ];
-                               $checked = in_array( $thisTag, (array)$value, true );
-                               if ( $this->isTagForcedOff( $thisTag ) ) {
-                                       $checked = false;
-                                       $thisAttribs['disabled'] = 1;
-                               } elseif ( $this->isTagForcedOn( $thisTag ) ) {
-                                       $checked = true;
-                                       $thisAttribs['disabled'] = 1;
-                               }
-
-                               $checkbox = $this->getOneCheckbox( $checked, $attribs + $thisAttribs );
-
-                               $rowContents .= Html::rawElement(
-                                       'td',
-                                       [],
-                                       $checkbox
-                               );
-                       }
-                       $tableContents .= Html::rawElement( 'tr', [], "\n$rowContents\n" );
-               }
-
-               // Put it all in a table
-               $html .= Html::rawElement( 'table',
-                               [ 'class' => 'mw-htmlform-matrix' ],
-                               Html::rawElement( 'tbody', [], "\n$tableContents\n" ) ) . "\n";
-
-               return $html;
-       }
-
-       protected function getOneCheckbox( $checked, $attribs ) {
-               if ( $this->mParent instanceof OOUIHTMLForm ) {
-                       return new OOUI\CheckboxInputWidget( [
-                               'name' => "{$this->mName}[]",
-                               'selected' => $checked,
-                       ] + OOUI\Element::configFromHtmlAttributes(
-                               $attribs
-                       ) );
-               } else {
-                       $checkbox = Xml::check( "{$this->mName}[]", $checked, $attribs );
-                       if ( $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
-                               $checkbox = Html::openElement( 'div', [ 'class' => 'mw-ui-checkbox' ] ) .
-                                       $checkbox .
-                                       Html::element( 'label', [ 'for' => $attribs['id'] ] ) .
-                                       Html::closeElement( 'div' );
-                       }
-                       return $checkbox;
-               }
-       }
-
-       protected function isTagForcedOff( $tag ) {
-               return isset( $this->mParams['force-options-off'] )
-                       && in_array( $tag, $this->mParams['force-options-off'] );
-       }
-
-       protected function isTagForcedOn( $tag ) {
-               return isset( $this->mParams['force-options-on'] )
-                       && in_array( $tag, $this->mParams['force-options-on'] );
-       }
-
-       /**
-        * Get the complete table row for the input, including help text,
-        * labels, and whatever.
-        * We override this function since the label should always be on a separate
-        * line above the options in the case of a checkbox matrix, i.e. it's always
-        * a "vertical-label".
-        *
-        * @param string $value The value to set the input to
-        *
-        * @return string Complete HTML table row
-        */
-       function getTableRow( $value ) {
-               list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
-               $inputHtml = $this->getInputHTML( $value );
-               $fieldType = get_class( $this );
-               $helptext = $this->getHelpTextHtmlTable( $this->getHelpText() );
-               $cellAttributes = [ 'colspan' => 2 ];
-
-               $hideClass = '';
-               $hideAttributes = [];
-               if ( $this->mHideIf ) {
-                       $hideAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
-                       $hideClass = 'mw-htmlform-hide-if';
-               }
-
-               $label = $this->getLabelHtml( $cellAttributes );
-
-               $field = Html::rawElement(
-                       'td',
-                       [ 'class' => 'mw-input' ] + $cellAttributes,
-                       $inputHtml . "\n$errors"
-               );
-
-               $html = Html::rawElement( 'tr',
-                       [ 'class' => "mw-htmlform-vertical-label $hideClass" ] + $hideAttributes,
-                       $label );
-               $html .= Html::rawElement( 'tr',
-                       [ 'class' => "mw-htmlform-field-$fieldType {$this->mClass} $errorClass $hideClass" ] +
-                               $hideAttributes,
-                       $field );
-
-               return $html . $helptext;
-       }
-
-       /**
-        * @param WebRequest $request
-        *
-        * @return array
-        */
-       function loadDataFromRequest( $request ) {
-               if ( $this->isSubmitAttempt( $request ) ) {
-                       // Checkboxes are just not added to the request arrays if they're not checked,
-                       // so it's perfectly possible for there not to be an entry at all
-                       return $request->getArray( $this->mName, [] );
-               } else {
-                       // That's ok, the user has not yet submitted the form, so show the defaults
-                       return $this->getDefault();
-               }
-       }
-
-       function getDefault() {
-               if ( isset( $this->mDefault ) ) {
-                       return $this->mDefault;
-               } else {
-                       return [];
-               }
-       }
-
-       function filterDataForSubmit( $data ) {
-               $columns = HTMLFormField::flattenOptions( $this->mParams['columns'] );
-               $rows = HTMLFormField::flattenOptions( $this->mParams['rows'] );
-               $res = [];
-               foreach ( $columns as $column ) {
-                       foreach ( $rows as $row ) {
-                               // Make sure option hasn't been forced
-                               $thisTag = "$column-$row";
-                               if ( $this->isTagForcedOff( $thisTag ) ) {
-                                       $res[$thisTag] = false;
-                               } elseif ( $this->isTagForcedOn( $thisTag ) ) {
-                                       $res[$thisTag] = true;
-                               } else {
-                                       $res[$thisTag] = in_array( $thisTag, $data );
-                               }
-                       }
-               }
-
-               return $res;
-       }
-}
diff --git a/includes/htmlform/HTMLComboboxField.php b/includes/htmlform/HTMLComboboxField.php
deleted file mode 100644 (file)
index 778aedb..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-/**
- * A combo box field.
- *
- * You can think of it as a dropdown select with the ability to add custom options,
- * or as a text field with input suggestions (autocompletion).
- *
- * When JavaScript is not supported or enabled, it uses HTML5 `<datalist>` element.
- *
- * Besides the parameters recognized by HTMLTextField, the following are
- * recognized:
- *   options-messages - As for HTMLSelectField
- *   options - As for HTMLSelectField
- *   options-message - As for HTMLSelectField
- */
-class HTMLComboboxField extends HTMLTextField {
-       // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
-       public function getAttributes( array $list ) {
-               $attribs = [
-                       'type' => 'text',
-                       'list' => $this->mName . '-datalist',
-               ] + parent::getAttributes( $list );
-
-               return $attribs;
-       }
-
-       function getInputHTML( $value ) {
-               $datalist = new XmlSelect( false, $this->mName . '-datalist' );
-               $datalist->setTagName( 'datalist' );
-               $datalist->addOptions( $this->getOptions() );
-
-               return parent::getInputHTML( $value ) . $datalist->getHTML();
-       }
-
-       function getInputOOUI( $value ) {
-               $disabled = false;
-               $allowedParams = [ 'tabindex' ];
-               $attribs = OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( $allowedParams )
-               );
-
-               if ( $this->mClass !== '' ) {
-                       $attribs['classes'] = [ $this->mClass ];
-               }
-
-               if ( !empty( $this->mParams['disabled'] ) ) {
-                       $disabled = true;
-               }
-
-               return new OOUI\ComboBoxInputWidget( [
-                       'name' => $this->mName,
-                       'id' => $this->mID,
-                       'options' => $this->getOptionsOOUI(),
-                       'value' => strval( $value ),
-                       'disabled' => $disabled,
-               ] + $attribs );
-       }
-}
diff --git a/includes/htmlform/HTMLEditTools.php b/includes/htmlform/HTMLEditTools.php
deleted file mode 100644 (file)
index 1b5d1fb..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-class HTMLEditTools extends HTMLFormField {
-       public function getInputHTML( $value ) {
-               return '';
-       }
-
-       public function getTableRow( $value ) {
-               $msg = $this->formatMsg();
-
-               return
-                       '<tr><td></td><td class="mw-input">' .
-                       '<div class="mw-editTools">' .
-                       $msg->parseAsBlock() .
-                       "</div></td></tr>\n";
-       }
-
-       /**
-        * @param string $value
-        * @return string
-        * @since 1.20
-        */
-       public function getDiv( $value ) {
-               $msg = $this->formatMsg();
-
-               return '<div class="mw-editTools">' . $msg->parseAsBlock() . '</div>';
-       }
-
-       /**
-        * @param string $value
-        * @return string
-        * @since 1.20
-        */
-       public function getRaw( $value ) {
-               return $this->getDiv( $value );
-       }
-
-       protected function formatMsg() {
-               if ( empty( $this->mParams['message'] ) ) {
-                       $msg = $this->msg( 'edittools' );
-               } else {
-                       $msg = $this->getMessage( $this->mParams['message'] );
-                       if ( $msg->isDisabled() ) {
-                               $msg = $this->msg( 'edittools' );
-                       }
-               }
-               $msg->inContentLanguage();
-
-               return $msg;
-       }
-}
diff --git a/includes/htmlform/HTMLFloatField.php b/includes/htmlform/HTMLFloatField.php
deleted file mode 100644 (file)
index 2ef4978..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-/**
- * A field that will contain a numeric value
- */
-class HTMLFloatField extends HTMLTextField {
-       function getSize() {
-               return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 20;
-       }
-
-       function validate( $value, $alldata ) {
-               $p = parent::validate( $value, $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               $value = trim( $value );
-
-               # http://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
-               # with the addition that a leading '+' sign is ok.
-               if ( !preg_match( '/^((\+|\-)?\d+(\.\d+)?(E(\+|\-)?\d+)?)?$/i', $value ) ) {
-                       return $this->msg( 'htmlform-float-invalid' )->parseAsBlock();
-               }
-
-               # The "int" part of these message names is rather confusing.
-               # They make equal sense for all numbers.
-               if ( isset( $this->mParams['min'] ) ) {
-                       $min = $this->mParams['min'];
-
-                       if ( $min > $value ) {
-                               return $this->msg( 'htmlform-int-toolow', $min )->parseAsBlock();
-                       }
-               }
-
-               if ( isset( $this->mParams['max'] ) ) {
-                       $max = $this->mParams['max'];
-
-                       if ( $max < $value ) {
-                               return $this->msg( 'htmlform-int-toohigh', $max )->parseAsBlock();
-                       }
-               }
-
-               return true;
-       }
-}
diff --git a/includes/htmlform/HTMLFormFieldCloner.php b/includes/htmlform/HTMLFormFieldCloner.php
deleted file mode 100644 (file)
index ec1bd84..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-<?php
-
-/**
- * A container for HTMLFormFields that allows for multiple copies of the set of
- * fields to be displayed to and entered by the user.
- *
- * Recognized parameters, besides the general ones, include:
- *   fields - HTMLFormField descriptors for the subfields this cloner manages.
- *     The format is just like for the HTMLForm. A field with key 'delete' is
- *     special: it must have type = submit and will serve to delete the group
- *     of fields.
- *   required - If specified, at least one group of fields must be submitted.
- *   format - HTMLForm display format to use when displaying the subfields:
- *     'table', 'div', or 'raw'.
- *   row-legend - If non-empty, each group of subfields will be enclosed in a
- *     fieldset. The value is the name of a message key to use as the legend.
- *   create-button-message - Message to use as the text of the button to
- *     add an additional group of fields.
- *   delete-button-message - Message to use as the text of automatically-
- *     generated 'delete' button. Ignored if 'delete' is included in 'fields'.
- *
- * In the generated HTML, the subfields will be named along the lines of
- * "clonerName[index][fieldname]", with ids "clonerId--index--fieldid". 'index'
- * may be a number or an arbitrary string, and may likely change when the page
- * is resubmitted. Cloners may be nested, resulting in field names along the
- * lines of "cloner1Name[index1][cloner2Name][index2][fieldname]" and
- * corresponding ids.
- *
- * Use of cloner may result in submissions of the page that are not submissions
- * of the HTMLForm, when non-JavaScript clients use the create or remove buttons.
- *
- * The result is an array, with values being arrays mapping subfield names to
- * their values. On non-HTMLForm-submission page loads, there may also be
- * additional (string) keys present with other types of values.
- *
- * @since 1.23
- */
-class HTMLFormFieldCloner extends HTMLFormField {
-       private static $counter = 0;
-
-       /**
-        * @var string String uniquely identifying this cloner instance and
-        * unlikely to exist otherwise in the generated HTML, while still being
-        * valid as part of an HTML id.
-        */
-       protected $uniqueId;
-
-       public function __construct( $params ) {
-               $this->uniqueId = get_class( $this ) . ++self::$counter . 'x';
-               parent::__construct( $params );
-
-               if ( empty( $this->mParams['fields'] ) || !is_array( $this->mParams['fields'] ) ) {
-                       throw new MWException( 'HTMLFormFieldCloner called without any fields' );
-               }
-
-               // Make sure the delete button, if explicitly specified, is sane
-               if ( isset( $this->mParams['fields']['delete'] ) ) {
-                       $class = 'mw-htmlform-cloner-delete-button';
-                       $info = $this->mParams['fields']['delete'] + [
-                               'cssclass' => $class
-                       ];
-                       unset( $info['name'], $info['class'] );
-
-                       if ( !isset( $info['type'] ) || $info['type'] !== 'submit' ) {
-                               throw new MWException(
-                                       'HTMLFormFieldCloner delete field, if specified, must be of type "submit"'
-                               );
-                       }
-
-                       if ( !in_array( $class, explode( ' ', $info['cssclass'] ) ) ) {
-                               $info['cssclass'] .= " $class";
-                       }
-
-                       $this->mParams['fields']['delete'] = $info;
-               }
-       }
-
-       /**
-        * Create the HTMLFormFields that go inside this element, using the
-        * specified key.
-        *
-        * @param string $key Array key under which these fields should be named
-        * @return HTMLFormField[]
-        */
-       protected function createFieldsForKey( $key ) {
-               $fields = [];
-               foreach ( $this->mParams['fields'] as $fieldname => $info ) {
-                       $name = "{$this->mName}[$key][$fieldname]";
-                       if ( isset( $info['name'] ) ) {
-                               $info['name'] = "{$this->mName}[$key][{$info['name']}]";
-                       } else {
-                               $info['name'] = $name;
-                       }
-                       if ( isset( $info['id'] ) ) {
-                               $info['id'] = Sanitizer::escapeId( "{$this->mID}--$key--{$info['id']}" );
-                       } else {
-                               $info['id'] = Sanitizer::escapeId( "{$this->mID}--$key--$fieldname" );
-                       }
-                       $field = HTMLForm::loadInputFromParameters( $name, $info, $this->mParent );
-                       $fields[$fieldname] = $field;
-               }
-               return $fields;
-       }
-
-       /**
-        * Re-key the specified values array to match the names applied by
-        * createFieldsForKey().
-        *
-        * @param string $key Array key under which these fields should be named
-        * @param array $values Values array from the request
-        * @return array
-        */
-       protected function rekeyValuesArray( $key, $values ) {
-               $data = [];
-               foreach ( $values as $fieldname => $value ) {
-                       $name = "{$this->mName}[$key][$fieldname]";
-                       $data[$name] = $value;
-               }
-               return $data;
-       }
-
-       protected function needsLabel() {
-               return false;
-       }
-
-       public function loadDataFromRequest( $request ) {
-               // It's possible that this might be posted with no fields. Detect that
-               // by looking for an edit token.
-               if ( !$request->getCheck( 'wpEditToken' ) && $request->getArray( $this->mName ) === null ) {
-                       return $this->getDefault();
-               }
-
-               $values = $request->getArray( $this->mName );
-               if ( $values === null ) {
-                       $values = [];
-               }
-
-               $ret = [];
-               foreach ( $values as $key => $value ) {
-                       if ( $key === 'create' || isset( $value['delete'] ) ) {
-                               $ret['nonjs'] = 1;
-                               continue;
-                       }
-
-                       // Add back in $request->getValues() so things that look for e.g.
-                       // wpEditToken don't fail.
-                       $data = $this->rekeyValuesArray( $key, $value ) + $request->getValues();
-
-                       $fields = $this->createFieldsForKey( $key );
-                       $subrequest = new DerivativeRequest( $request, $data, $request->wasPosted() );
-                       $row = [];
-                       foreach ( $fields as $fieldname => $field ) {
-                               if ( $field->skipLoadData( $subrequest ) ) {
-                                       continue;
-                               } elseif ( !empty( $field->mParams['disabled'] ) ) {
-                                       $row[$fieldname] = $field->getDefault();
-                               } else {
-                                       $row[$fieldname] = $field->loadDataFromRequest( $subrequest );
-                               }
-                       }
-                       $ret[] = $row;
-               }
-
-               if ( isset( $values['create'] ) ) {
-                       // Non-JS client clicked the "create" button.
-                       $fields = $this->createFieldsForKey( $this->uniqueId );
-                       $row = [];
-                       foreach ( $fields as $fieldname => $field ) {
-                               if ( !empty( $field->mParams['nodata'] ) ) {
-                                       continue;
-                               } else {
-                                       $row[$fieldname] = $field->getDefault();
-                               }
-                       }
-                       $ret[] = $row;
-               }
-
-               return $ret;
-       }
-
-       public function getDefault() {
-               $ret = parent::getDefault();
-
-               // The default default is one entry with all subfields at their
-               // defaults.
-               if ( $ret === null ) {
-                       $fields = $this->createFieldsForKey( $this->uniqueId );
-                       $row = [];
-                       foreach ( $fields as $fieldname => $field ) {
-                               if ( !empty( $field->mParams['nodata'] ) ) {
-                                       continue;
-                               } else {
-                                       $row[$fieldname] = $field->getDefault();
-                               }
-                       }
-                       $ret = [ $row ];
-               }
-
-               return $ret;
-       }
-
-       public function cancelSubmit( $values, $alldata ) {
-               if ( isset( $values['nonjs'] ) ) {
-                       return true;
-               }
-
-               foreach ( $values as $key => $value ) {
-                       $fields = $this->createFieldsForKey( $key );
-                       foreach ( $fields as $fieldname => $field ) {
-                               if ( !array_key_exists( $fieldname, $value ) ) {
-                                       continue;
-                               }
-                               if ( $field->cancelSubmit( $value[$fieldname], $alldata ) ) {
-                                       return true;
-                               }
-                       }
-               }
-
-               return parent::cancelSubmit( $values, $alldata );
-       }
-
-       public function validate( $values, $alldata ) {
-               if ( isset( $this->mParams['required'] )
-                       && $this->mParams['required'] !== false
-                       && !$values
-               ) {
-                       return $this->msg( 'htmlform-cloner-required' )->parseAsBlock();
-               }
-
-               if ( isset( $values['nonjs'] ) ) {
-                       // The submission was a non-JS create/delete click, so fail
-                       // validation in case cancelSubmit() somehow didn't already handle
-                       // it.
-                       return false;
-               }
-
-               foreach ( $values as $key => $value ) {
-                       $fields = $this->createFieldsForKey( $key );
-                       foreach ( $fields as $fieldname => $field ) {
-                               if ( !array_key_exists( $fieldname, $value ) ) {
-                                       continue;
-                               }
-                               $ok = $field->validate( $value[$fieldname], $alldata );
-                               if ( $ok !== true ) {
-                                       return false;
-                               }
-                       }
-               }
-
-               return parent::validate( $values, $alldata );
-       }
-
-       /**
-        * Get the input HTML for the specified key.
-        *
-        * @param string $key Array key under which the fields should be named
-        * @param array $values
-        * @return string
-        */
-       protected function getInputHTMLForKey( $key, $values ) {
-               $displayFormat = isset( $this->mParams['format'] )
-                       ? $this->mParams['format']
-                       : $this->mParent->getDisplayFormat();
-
-               // Conveniently, PHP method names are case-insensitive.
-               $getFieldHtmlMethod = $displayFormat == 'table' ? 'getTableRow' : ( 'get' . $displayFormat );
-
-               $html = '';
-               $hidden = '';
-               $hasLabel = false;
-
-               $fields = $this->createFieldsForKey( $key );
-               foreach ( $fields as $fieldname => $field ) {
-                       $v = array_key_exists( $fieldname, $values )
-                               ? $values[$fieldname]
-                               : $field->getDefault();
-
-                       if ( $field instanceof HTMLHiddenField ) {
-                               // HTMLHiddenField doesn't generate its own HTML
-                               list( $name, $value, $params ) = $field->getHiddenFieldData( $v );
-                               $hidden .= Html::hidden( $name, $value, $params ) . "\n";
-                       } else {
-                               $html .= $field->$getFieldHtmlMethod( $v );
-
-                               $labelValue = trim( $field->getLabel() );
-                               if ( $labelValue != '&#160;' && $labelValue !== '' ) {
-                                       $hasLabel = true;
-                               }
-                       }
-               }
-
-               if ( !isset( $fields['delete'] ) ) {
-                       $name = "{$this->mName}[$key][delete]";
-                       $label = isset( $this->mParams['delete-button-message'] )
-                               ? $this->mParams['delete-button-message']
-                               : 'htmlform-cloner-delete';
-                       $field = HTMLForm::loadInputFromParameters( $name, [
-                               'type' => 'submit',
-                               'name' => $name,
-                               'id' => Sanitizer::escapeId( "{$this->mID}--$key--delete" ),
-                               'cssclass' => 'mw-htmlform-cloner-delete-button',
-                               'default' => $this->getMessage( $label )->text(),
-                       ], $this->mParent );
-                       $v = $field->getDefault();
-
-                       if ( $displayFormat === 'table' ) {
-                               $html .= $field->$getFieldHtmlMethod( $v );
-                       } else {
-                               $html .= $field->getInputHTML( $v );
-                       }
-               }
-
-               if ( $displayFormat !== 'raw' ) {
-                       $classes = [
-                               'mw-htmlform-cloner-row',
-                       ];
-
-                       if ( !$hasLabel ) { // Avoid strange spacing when no labels exist
-                               $classes[] = 'mw-htmlform-nolabel';
-                       }
-
-                       $attribs = [
-                               'class' => implode( ' ', $classes ),
-                       ];
-
-                       if ( $displayFormat === 'table' ) {
-                               $html = Html::rawElement( 'table',
-                                       $attribs,
-                                       Html::rawElement( 'tbody', [], "\n$html\n" ) ) . "\n";
-                       } else {
-                               $html = Html::rawElement( 'div', $attribs, "\n$html\n" );
-                       }
-               }
-
-               $html .= $hidden;
-
-               if ( !empty( $this->mParams['row-legend'] ) ) {
-                       $legend = $this->msg( $this->mParams['row-legend'] )->text();
-                       $html = Xml::fieldset( $legend, $html );
-               }
-
-               return $html;
-       }
-
-       public function getInputHTML( $values ) {
-               $html = '';
-
-               foreach ( (array)$values as $key => $value ) {
-                       if ( $key === 'nonjs' ) {
-                               continue;
-                       }
-                       $html .= Html::rawElement( 'li', [ 'class' => 'mw-htmlform-cloner-li' ],
-                               $this->getInputHTMLForKey( $key, $value )
-                       );
-               }
-
-               $template = $this->getInputHTMLForKey( $this->uniqueId, null );
-               $html = Html::rawElement( 'ul', [
-                       'id' => "mw-htmlform-cloner-list-{$this->mID}",
-                       'class' => 'mw-htmlform-cloner-ul',
-                       'data-template' => $template,
-                       'data-unique-id' => $this->uniqueId,
-               ], $html );
-
-               $name = "{$this->mName}[create]";
-               $label = isset( $this->mParams['create-button-message'] )
-                       ? $this->mParams['create-button-message']
-                       : 'htmlform-cloner-create';
-               $field = HTMLForm::loadInputFromParameters( $name, [
-                       'type' => 'submit',
-                       'name' => $name,
-                       'id' => Sanitizer::escapeId( "{$this->mID}--create" ),
-                       'cssclass' => 'mw-htmlform-cloner-create-button',
-                       'default' => $this->getMessage( $label )->text(),
-               ], $this->mParent );
-               $html .= $field->getInputHTML( $field->getDefault() );
-
-               return $html;
-       }
-}
diff --git a/includes/htmlform/HTMLFormFieldWithButton.php b/includes/htmlform/HTMLFormFieldWithButton.php
deleted file mode 100644 (file)
index bcb07bd..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-/**
- * Enables HTMLFormField elements to be build with a button.
- */
-class HTMLFormFieldWithButton extends HTMLFormField {
-       /** @var string $mButtonClass CSS class for the button in this field */
-       protected $mButtonClass = '';
-
-       /** @var string|integer $mButtonId Element ID for the button in this field */
-       protected $mButtonId = '';
-
-       /** @var string $mButtonName Name the button in this field */
-       protected $mButtonName = '';
-
-       /** @var string $mButtonType Type of the button in this field (e.g. button or submit) */
-       protected $mButtonType = 'submit';
-
-       /** @var string $mButtonType Value for the button in this field */
-       protected $mButtonValue;
-
-       /** @var string $mButtonType Value for the button in this field */
-       protected $mButtonFlags = [ 'progressive' ];
-
-       public function __construct( $info ) {
-               if ( isset( $info['buttonclass'] ) ) {
-                       $this->mButtonClass = $info['buttonclass'];
-               }
-               if ( isset( $info['buttonid'] ) ) {
-                       $this->mButtonId = $info['buttonid'];
-               }
-               if ( isset( $info['buttonname'] ) ) {
-                       $this->mButtonName = $info['buttonname'];
-               }
-               if ( isset( $info['buttondefault'] ) ) {
-                       $this->mButtonValue = $info['buttondefault'];
-               }
-               if ( isset( $info['buttontype'] ) ) {
-                       $this->mButtonType = $info['buttontype'];
-               }
-               if ( isset( $info['buttonflags'] ) ) {
-                       $this->mButtonFlags = $info['buttonflags'];
-               }
-               parent::__construct( $info );
-       }
-
-       public function getInputHTML( $value ) {
-               $attr = [
-                       'class' => 'mw-htmlform-submit ' . $this->mButtonClass,
-                       'id' => $this->mButtonId,
-               ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
-
-               return Html::input( $this->mButtonName, $this->mButtonValue, $this->mButtonType, $attr );
-       }
-
-       public function getInputOOUI( $value ) {
-               return new OOUI\ButtonInputWidget( [
-                       'name' => $this->mButtonName,
-                       'value' => $this->mButtonValue,
-                       'type' => $this->mButtonType,
-                       'label' => $this->mButtonValue,
-                       'flags' => $this->mButtonFlags,
-               ] + OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
-               ) );
-       }
-
-       /**
-        * Combines the passed element with a button.
-        * @param String $element Element to combine the button with.
-        * @return String
-        */
-       public function getElement( $element ) {
-               return $element . '&#160;' . $this->getInputHTML( '' );
-       }
-}
diff --git a/includes/htmlform/HTMLHiddenField.php b/includes/htmlform/HTMLHiddenField.php
deleted file mode 100644 (file)
index c0fce2b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-class HTMLHiddenField extends HTMLFormField {
-       protected $outputAsDefault = true;
-
-       public function __construct( $params ) {
-               parent::__construct( $params );
-
-               if ( isset( $this->mParams['output-as-default'] ) ) {
-                       $this->outputAsDefault = (bool)$this->mParams['output-as-default'];
-               }
-
-               # Per HTML5 spec, hidden fields cannot be 'required'
-               # http://www.w3.org/TR/html5/forms.html#hidden-state-%28type=hidden%29
-               unset( $this->mParams['required'] );
-       }
-
-       public function getHiddenFieldData( $value ) {
-               $params = [];
-               if ( $this->mID ) {
-                       $params['id'] = $this->mID;
-               }
-
-               if ( $this->outputAsDefault ) {
-                       $value = $this->mDefault;
-               }
-
-               return [ $this->mName, $value, $params ];
-       }
-
-       public function getTableRow( $value ) {
-               list( $name, $value, $params ) = $this->getHiddenFieldData( $value );
-               $this->mParent->addHiddenField( $name, $value, $params );
-               return '';
-       }
-
-       /**
-        * @param string $value
-        * @return string
-        * @since 1.20
-        */
-       public function getDiv( $value ) {
-               return $this->getTableRow( $value );
-       }
-
-       /**
-        * @param string $value
-        * @return string
-        * @since 1.20
-        */
-       public function getRaw( $value ) {
-               return $this->getTableRow( $value );
-       }
-
-       public function getInputHTML( $value ) {
-               return '';
-       }
-
-       public function canDisplayErrors() {
-               return false;
-       }
-
-       public function hasVisibleOutput() {
-               return false;
-       }
-}
diff --git a/includes/htmlform/HTMLInfoField.php b/includes/htmlform/HTMLInfoField.php
deleted file mode 100644 (file)
index ada4fb6..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-/**
- * An information field (text blob), not a proper input.
- */
-class HTMLInfoField extends HTMLFormField {
-       public function __construct( $info ) {
-               $info['nodata'] = true;
-
-               parent::__construct( $info );
-       }
-
-       public function getInputHTML( $value ) {
-               return !empty( $this->mParams['raw'] ) ? $value : htmlspecialchars( $value );
-       }
-
-       public function getInputOOUI( $value ) {
-               if ( !empty( $this->mParams['raw'] ) ) {
-                       $value = new OOUI\HtmlSnippet( $value );
-               }
-
-               return new OOUI\LabelWidget( [
-                       'label' => $value,
-               ] );
-       }
-
-       public function getTableRow( $value ) {
-               if ( !empty( $this->mParams['rawrow'] ) ) {
-                       return $value;
-               }
-
-               return parent::getTableRow( $value );
-       }
-
-       /**
-        * @param string $value
-        * @return string
-        * @since 1.20
-        */
-       public function getDiv( $value ) {
-               if ( !empty( $this->mParams['rawrow'] ) ) {
-                       return $value;
-               }
-
-               return parent::getDiv( $value );
-       }
-
-       /**
-        * @param string $value
-        * @return string
-        * @since 1.20
-        */
-       public function getRaw( $value ) {
-               if ( !empty( $this->mParams['rawrow'] ) ) {
-                       return $value;
-               }
-
-               return parent::getRaw( $value );
-       }
-
-       protected function needsLabel() {
-               return false;
-       }
-}
diff --git a/includes/htmlform/HTMLIntField.php b/includes/htmlform/HTMLIntField.php
deleted file mode 100644 (file)
index b0148d9..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/**
- * A field that must contain a number
- */
-class HTMLIntField extends HTMLFloatField {
-       function validate( $value, $alldata ) {
-               $p = parent::validate( $value, $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               # http://www.w3.org/TR/html5/infrastructure.html#signed-integers
-               # with the addition that a leading '+' sign is ok. Note that leading zeros
-               # are fine, and will be left in the input, which is useful for things like
-               # phone numbers when you know that they are integers (the HTML5 type=tel
-               # input does not require its value to be numeric).  If you want a tidier
-               # value to, eg, save in the DB, clean it up with intval().
-               if ( !preg_match( '/^((\+|\-)?\d+)?$/', trim( $value ) ) ) {
-                       return $this->msg( 'htmlform-int-invalid' )->parseAsBlock();
-               }
-
-               return true;
-       }
-}
diff --git a/includes/htmlform/HTMLMultiSelectField.php b/includes/htmlform/HTMLMultiSelectField.php
deleted file mode 100644 (file)
index a231b2f..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-/**
- * Multi-select field
- */
-class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable {
-       function validate( $value, $alldata ) {
-               $p = parent::validate( $value, $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               if ( !is_array( $value ) ) {
-                       return false;
-               }
-
-               # If all options are valid, array_intersect of the valid options
-               # and the provided options will return the provided options.
-               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
-
-               $validValues = array_intersect( $value, $validOptions );
-               if ( count( $validValues ) == count( $value ) ) {
-                       return true;
-               } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
-               }
-       }
-
-       function getInputHTML( $value ) {
-               $value = HTMLFormField::forceToStringRecursive( $value );
-               $html = $this->formatOptions( $this->getOptions(), $value );
-
-               return $html;
-       }
-
-       function formatOptions( $options, $value ) {
-               $html = '';
-
-               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
-
-               foreach ( $options as $label => $info ) {
-                       if ( is_array( $info ) ) {
-                               $html .= Html::rawElement( 'h1', [], $label ) . "\n";
-                               $html .= $this->formatOptions( $info, $value );
-                       } else {
-                               $thisAttribs = [
-                                       'id' => "{$this->mID}-$info",
-                                       'value' => $info,
-                               ];
-                               $checked = in_array( $info, $value, true );
-
-                               $checkbox = $this->getOneCheckbox( $checked, $attribs + $thisAttribs, $label );
-
-                               $html .= ' ' . Html::rawElement(
-                                       'div',
-                                       [ 'class' => 'mw-htmlform-flatlist-item' ],
-                                       $checkbox
-                               );
-                       }
-               }
-
-               return $html;
-       }
-
-       protected function getOneCheckbox( $checked, $attribs, $label ) {
-               if ( $this->mParent instanceof OOUIHTMLForm ) {
-                       throw new MWException( 'HTMLMultiSelectField#getOneCheckbox() is not supported' );
-               } else {
-                       $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
-                       $checkbox =
-                               Xml::check( "{$this->mName}[]", $checked, $attribs ) .
-                               '&#160;' .
-                               call_user_func( $elementFunc,
-                                       'label',
-                                       [ 'for' => $attribs['id'] ],
-                                       $label
-                               );
-                       if ( $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
-                               $checkbox = Html::openElement( 'div', [ 'class' => 'mw-ui-checkbox' ] ) .
-                                       $checkbox .
-                                       Html::closeElement( 'div' );
-                       }
-                       return $checkbox;
-               }
-       }
-
-       /**
-        * Get the OOUI version of this field.
-        *
-        * @since 1.28
-        * @param string[] $value
-        * @return OOUI\CheckboxMultiselectInputWidget
-        */
-       public function getInputOOUI( $value ) {
-               $attr = $this->getTooltipAndAccessKey();
-               $attr['id'] = $this->mID;
-               $attr['name'] = "{$this->mName}[]";
-
-               $attr['value'] = $value;
-               $attr['options'] = $this->getOptionsOOUI();
-
-               if ( $this->mOptionsLabelsNotFromMessage ) {
-                       foreach ( $attr['options'] as &$option ) {
-                               $option['label'] = new OOUI\HtmlSnippet( $option['label'] );
-                       }
-               }
-
-               $attr += OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
-               );
-
-               if ( $this->mClass !== '' ) {
-                       $attr['classes'] = [ $this->mClass ];
-               }
-
-               return new OOUI\CheckboxMultiselectInputWidget( $attr );
-       }
-
-       /**
-        * @param WebRequest $request
-        *
-        * @return string
-        */
-       function loadDataFromRequest( $request ) {
-               if ( $this->isSubmitAttempt( $request ) ) {
-                       // Checkboxes are just not added to the request arrays if they're not checked,
-                       // so it's perfectly possible for there not to be an entry at all
-                       return $request->getArray( $this->mName, [] );
-               } else {
-                       // That's ok, the user has not yet submitted the form, so show the defaults
-                       return $this->getDefault();
-               }
-       }
-
-       function getDefault() {
-               if ( isset( $this->mDefault ) ) {
-                       return $this->mDefault;
-               } else {
-                       return [];
-               }
-       }
-
-       function filterDataForSubmit( $data ) {
-               $data = HTMLFormField::forceToStringRecursive( $data );
-               $options = HTMLFormField::flattenOptions( $this->getOptions() );
-
-               $res = [];
-               foreach ( $options as $opt ) {
-                       $res["$opt"] = in_array( $opt, $data, true );
-               }
-
-               return $res;
-       }
-
-       protected function needsLabel() {
-               return false;
-       }
-}
diff --git a/includes/htmlform/HTMLRadioField.php b/includes/htmlform/HTMLRadioField.php
deleted file mode 100644 (file)
index e5b5e68..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-
-/**
- * Radio checkbox fields.
- */
-class HTMLRadioField extends HTMLFormField {
-       function validate( $value, $alldata ) {
-               $p = parent::validate( $value, $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               if ( !is_string( $value ) && !is_int( $value ) ) {
-                       return false;
-               }
-
-               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
-
-               if ( in_array( strval( $value ), $validOptions, true ) ) {
-                       return true;
-               } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
-               }
-       }
-
-       /**
-        * This returns a block of all the radio options, in one cell.
-        * @see includes/HTMLFormField#getInputHTML()
-        *
-        * @param string $value
-        *
-        * @return string
-        */
-       function getInputHTML( $value ) {
-               $html = $this->formatOptions( $this->getOptions(), strval( $value ) );
-
-               return $html;
-       }
-
-       function getInputOOUI( $value ) {
-               $options = [];
-               foreach ( $this->getOptions() as $label => $data ) {
-                       $options[] = [
-                               'data' => $data,
-                               'label' => $this->mOptionsLabelsNotFromMessage ? new OOUI\HtmlSnippet( $label ) : $label,
-                       ];
-               }
-
-               return new OOUI\RadioSelectInputWidget( [
-                       'name' => $this->mName,
-                       'id' => $this->mID,
-                       'value' => $value,
-                       'options' => $options,
-               ] + OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
-               ) );
-       }
-
-       function formatOptions( $options, $value ) {
-               global $wgUseMediaWikiUIEverywhere;
-
-               $html = '';
-
-               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
-               $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
-
-               # @todo Should this produce an unordered list perhaps?
-               foreach ( $options as $label => $info ) {
-                       if ( is_array( $info ) ) {
-                               $html .= Html::rawElement( 'h1', [], $label ) . "\n";
-                               $html .= $this->formatOptions( $info, $value );
-                       } else {
-                               $id = Sanitizer::escapeId( $this->mID . "-$info" );
-                               $classes = [ 'mw-htmlform-flatlist-item' ];
-                               if ( $wgUseMediaWikiUIEverywhere || $this->mParent instanceof VFormHTMLForm ) {
-                                       $classes[] = 'mw-ui-radio';
-                               }
-                               $radio = Xml::radio( $this->mName, $info, $info === $value, $attribs + [ 'id' => $id ] );
-                               $radio .= '&#160;' . call_user_func( $elementFunc, 'label', [ 'for' => $id ], $label );
-
-                               $html .= ' ' . Html::rawElement(
-                                       'div',
-                                       [ 'class' => $classes ],
-                                       $radio
-                               );
-                       }
-               }
-
-               return $html;
-       }
-
-       protected function needsLabel() {
-               return false;
-       }
-}
diff --git a/includes/htmlform/HTMLSelectAndOtherField.php b/includes/htmlform/HTMLSelectAndOtherField.php
deleted file mode 100644 (file)
index e75c2b2..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-
-/**
- * Double field with a dropdown list constructed from a system message in the format
- *     * Optgroup header
- *     ** <option value>
- *     * New Optgroup header
- * Plus a text field underneath for an additional reason.  The 'value' of the field is
- * "<select>: <extra reason>", or "<extra reason>" if nothing has been selected in the
- * select dropdown.
- * @todo FIXME: If made 'required', only the text field should be compulsory.
- */
-class HTMLSelectAndOtherField extends HTMLSelectField {
-       function __construct( $params ) {
-               if ( array_key_exists( 'other', $params ) ) {
-                       // Do nothing
-               } elseif ( array_key_exists( 'other-message', $params ) ) {
-                       $params['other'] = $this->getMessage( $params['other-message'] )->plain();
-               } else {
-                       $params['other'] = $this->msg( 'htmlform-selectorother-other' )->plain();
-               }
-
-               parent::__construct( $params );
-
-               if ( $this->getOptions() === null ) {
-                       // Sulk
-                       throw new MWException( 'HTMLSelectAndOtherField called without any options' );
-               }
-               if ( !in_array( 'other', $this->mOptions, true ) ) {
-                       // Have 'other' always as first element
-                       $this->mOptions = [ $params['other'] => 'other' ] + $this->mOptions;
-               }
-               $this->mFlatOptions = self::flattenOptions( $this->getOptions() );
-
-       }
-
-       function getInputHTML( $value ) {
-               $select = parent::getInputHTML( $value[1] );
-
-               $textAttribs = [
-                       'id' => $this->mID . '-other',
-                       'size' => $this->getSize(),
-                       'class' => [ 'mw-htmlform-select-and-other-field' ],
-                       'data-id-select' => $this->mID,
-               ];
-
-               if ( $this->mClass !== '' ) {
-                       $textAttribs['class'][] = $this->mClass;
-               }
-
-               $allowedParams = [
-                       'required',
-                       'autofocus',
-                       'multiple',
-                       'disabled',
-                       'tabindex',
-                       'maxlength', // gets dynamic with javascript, see mediawiki.htmlform.js
-               ];
-
-               $textAttribs += $this->getAttributes( $allowedParams );
-
-               $textbox = Html::input( $this->mName . '-other', $value[2], 'text', $textAttribs );
-
-               return "$select<br />\n$textbox";
-       }
-
-       function getInputOOUI( $value ) {
-               return false;
-       }
-
-       /**
-        * @param WebRequest $request
-        *
-        * @return array("<overall message>","<select value>","<text field value>")
-        */
-       function loadDataFromRequest( $request ) {
-               if ( $request->getCheck( $this->mName ) ) {
-                       $list = $request->getText( $this->mName );
-                       $text = $request->getText( $this->mName . '-other' );
-
-                       // Should be built the same as in mediawiki.htmlform.js
-                       if ( $list == 'other' ) {
-                               $final = $text;
-                       } elseif ( !in_array( $list, $this->mFlatOptions, true ) ) {
-                               # User has spoofed the select form to give an option which wasn't
-                               # in the original offer.  Sulk...
-                               $final = $text;
-                       } elseif ( $text == '' ) {
-                               $final = $list;
-                       } else {
-                               $final = $list . $this->msg( 'colon-separator' )->inContentLanguage()->text() . $text;
-                       }
-               } else {
-                       $final = $this->getDefault();
-
-                       $list = 'other';
-                       $text = $final;
-                       foreach ( $this->mFlatOptions as $option ) {
-                               $match = $option . $this->msg( 'colon-separator' )->inContentLanguage()->text();
-                               if ( strpos( $text, $match ) === 0 ) {
-                                       $list = $option;
-                                       $text = substr( $text, strlen( $match ) );
-                                       break;
-                               }
-                       }
-               }
-
-               return [ $final, $list, $text ];
-       }
-
-       function getSize() {
-               return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45;
-       }
-
-       function validate( $value, $alldata ) {
-               # HTMLSelectField forces $value to be one of the options in the select
-               # field, which is not useful here.  But we do want the validation further up
-               # the chain
-               $p = parent::validate( $value[1], $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               if ( isset( $this->mParams['required'] )
-                       && $this->mParams['required'] !== false
-                       && $value[1] === ''
-               ) {
-                       return $this->msg( 'htmlform-required' )->parse();
-               }
-
-               return true;
-       }
-}
diff --git a/includes/htmlform/HTMLSelectField.php b/includes/htmlform/HTMLSelectField.php
deleted file mode 100644 (file)
index b6ad46c..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-/**
- * A select dropdown field.  Basically a wrapper for Xmlselect class
- */
-class HTMLSelectField extends HTMLFormField {
-       function validate( $value, $alldata ) {
-               $p = parent::validate( $value, $alldata );
-
-               if ( $p !== true ) {
-                       return $p;
-               }
-
-               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
-
-               if ( in_array( strval( $value ), $validOptions, true ) ) {
-                       return true;
-               } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
-               }
-       }
-
-       function getInputHTML( $value ) {
-               $select = new XmlSelect( $this->mName, $this->mID, strval( $value ) );
-
-               if ( !empty( $this->mParams['disabled'] ) ) {
-                       $select->setAttribute( 'disabled', 'disabled' );
-               }
-
-               $allowedParams = [ 'tabindex', 'size' ];
-               $customParams = $this->getAttributes( $allowedParams );
-               foreach ( $customParams as $name => $value ) {
-                       $select->setAttribute( $name, $value );
-               }
-
-               if ( $this->mClass !== '' ) {
-                       $select->setAttribute( 'class', $this->mClass );
-               }
-
-               $select->addOptions( $this->getOptions() );
-
-               return $select->getHTML();
-       }
-
-       function getInputOOUI( $value ) {
-               $disabled = false;
-               $allowedParams = [ 'tabindex' ];
-               $attribs = OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( $allowedParams )
-               );
-
-               if ( $this->mClass !== '' ) {
-                       $attribs['classes'] = [ $this->mClass ];
-               }
-
-               if ( !empty( $this->mParams['disabled'] ) ) {
-                       $disabled = true;
-               }
-
-               return new OOUI\DropdownInputWidget( [
-                       'name' => $this->mName,
-                       'id' => $this->mID,
-                       'options' => $this->getOptionsOOUI(),
-                       'value' => strval( $value ),
-                       'disabled' => $disabled,
-               ] + $attribs );
-       }
-}
diff --git a/includes/htmlform/HTMLSelectLimitField.php b/includes/htmlform/HTMLSelectLimitField.php
deleted file mode 100644 (file)
index e7f1c04..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/**
- * A limit dropdown, which accepts any valid number
- */
-class HTMLSelectLimitField extends HTMLSelectField {
-       /**
-        * Basically don't do any validation. If it's a number that's fine. Also,
-        * add it to the list if it's not there already
-        *
-        * @param string $value
-        * @param array $alldata
-        * @return bool
-        */
-       function validate( $value, $alldata ) {
-               if ( $value == '' ) {
-                       return true;
-               }
-
-               // Let folks pick an explicit limit not from our list, as long as it's a real numbr.
-               if ( !in_array( $value, $this->mParams['options'] )
-                       && $value == intval( $value )
-                       && $value > 0
-               ) {
-                       // This adds the explicitly requested limit value to the drop-down,
-                       // then makes sure it's sorted correctly so when we output the list
-                       // later, the custom option doesn't just show up last.
-                       $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] =
-                               intval( $value );
-                       asort( $this->mParams['options'] );
-               }
-
-               return true;
-       }
-}
diff --git a/includes/htmlform/HTMLSelectNamespace.php b/includes/htmlform/HTMLSelectNamespace.php
deleted file mode 100644 (file)
index ef21969..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-/**
- * Wrapper for Html::namespaceSelector to use in HTMLForm
- */
-class HTMLSelectNamespace extends HTMLFormField {
-       public function __construct( $params ) {
-               parent::__construct( $params );
-
-               $this->mAllValue = array_key_exists( 'all', $params )
-                       ? $params['all']
-                       : 'all';
-
-       }
-
-       function getInputHTML( $value ) {
-               return Html::namespaceSelector(
-                       [
-                               'selected' => $value,
-                               'all' => $this->mAllValue
-                       ], [
-                               'name' => $this->mName,
-                               'id' => $this->mID,
-                               'class' => 'namespaceselector',
-                       ]
-               );
-       }
-
-       public function getInputOOUI( $value ) {
-               return new MediaWiki\Widget\NamespaceInputWidget( [
-                       'value' => $value,
-                       'name' => $this->mName,
-                       'id' => $this->mID,
-                       'includeAllValue' => $this->mAllValue,
-               ] );
-       }
-}
diff --git a/includes/htmlform/HTMLSelectNamespaceWithButton.php b/includes/htmlform/HTMLSelectNamespaceWithButton.php
deleted file mode 100644 (file)
index 5225983..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-/**
- * Creates a Html::namespaceSelector input field with a button assigned to the input field.
- */
-class HTMLSelectNamespaceWithButton extends HTMLSelectNamespace {
-       /** @var HTMLFormFieldWithButton $mClassWithButton */
-       protected $mClassWithButton = null;
-
-       public function __construct( $info ) {
-               $this->mClassWithButton = new HTMLFormFieldWithButton( $info );
-               parent::__construct( $info );
-       }
-
-       public function getInputHTML( $value ) {
-               return $this->mClassWithButton->getElement( parent::getInputHTML( $value ) );
-       }
-}
diff --git a/includes/htmlform/HTMLSelectOrOtherField.php b/includes/htmlform/HTMLSelectOrOtherField.php
deleted file mode 100644 (file)
index 8f7750c..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-/**
- * Select dropdown field, with an additional "other" textbox.
- *
- * HTMLComboboxField implements the same functionality using a single form field
- * and should be used instead.
- */
-class HTMLSelectOrOtherField extends HTMLTextField {
-       function __construct( $params ) {
-               parent::__construct( $params );
-               $this->getOptions();
-               if ( !in_array( 'other', $this->mOptions, true ) ) {
-                       $msg =
-                               isset( $params['other'] )
-                                       ? $params['other']
-                                       : wfMessage( 'htmlform-selectorother-other' )->text();
-                       // Have 'other' always as first element
-                       $this->mOptions = [ $msg => 'other' ] + $this->mOptions;
-               }
-
-       }
-
-       function getInputHTML( $value ) {
-               $valInSelect = false;
-
-               if ( $value !== false ) {
-                       $value = strval( $value );
-                       $valInSelect = in_array(
-                               $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
-                       );
-               }
-
-               $selected = $valInSelect ? $value : 'other';
-
-               $select = new XmlSelect( $this->mName, $this->mID, $selected );
-               $select->addOptions( $this->getOptions() );
-
-               $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
-
-               $tbAttribs = [ 'id' => $this->mID . '-other', 'size' => $this->getSize() ];
-
-               if ( !empty( $this->mParams['disabled'] ) ) {
-                       $select->setAttribute( 'disabled', 'disabled' );
-                       $tbAttribs['disabled'] = 'disabled';
-               }
-
-               if ( isset( $this->mParams['tabindex'] ) ) {
-                       $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
-                       $tbAttribs['tabindex'] = $this->mParams['tabindex'];
-               }
-
-               $select = $select->getHTML();
-
-               if ( isset( $this->mParams['maxlength'] ) ) {
-                       $tbAttribs['maxlength'] = $this->mParams['maxlength'];
-               }
-
-               if ( $this->mClass !== '' ) {
-                       $tbAttribs['class'] = $this->mClass;
-               }
-
-               $textbox = Html::input( $this->mName . '-other', $valInSelect ? '' : $value, 'text', $tbAttribs );
-
-               return "$select<br />\n$textbox";
-       }
-
-       function getInputOOUI( $value ) {
-               return false;
-       }
-
-       /**
-        * @param WebRequest $request
-        *
-        * @return string
-        */
-       function loadDataFromRequest( $request ) {
-               if ( $request->getCheck( $this->mName ) ) {
-                       $val = $request->getText( $this->mName );
-
-                       if ( $val === 'other' ) {
-                               $val = $request->getText( $this->mName . '-other' );
-                       }
-
-                       return $val;
-               } else {
-                       return $this->getDefault();
-               }
-       }
-}
diff --git a/includes/htmlform/HTMLSubmitField.php b/includes/htmlform/HTMLSubmitField.php
deleted file mode 100644 (file)
index cb98549..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-/**
- * Add a submit button inline in the form (as opposed to
- * HTMLForm::addButton(), which will add it at the end).
- */
-class HTMLSubmitField extends HTMLButtonField {
-       protected $buttonType = 'submit';
-
-       protected $mFlags = [ 'primary', 'constructive' ];
-
-       public function skipLoadData( $request ) {
-               return !$request->getCheck( $this->mName );
-       }
-
-       public function loadDataFromRequest( $request ) {
-               return $request->getCheck( $this->mName );
-       }
-}
diff --git a/includes/htmlform/HTMLTagFilter.php b/includes/htmlform/HTMLTagFilter.php
deleted file mode 100644 (file)
index 8075de5..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
- * Wrapper for ChangeTags::buildTagFilterSelector to use in HTMLForm
- */
-class HTMLTagFilter extends HTMLFormField {
-       protected $tagFilter;
-
-       function getTableRow( $value ) {
-               $this->tagFilter = ChangeTags::buildTagFilterSelector( $value );
-               if ( $this->tagFilter ) {
-                       return parent::getTableRow( $value );
-               }
-               return '';
-       }
-
-       function getDiv( $value ) {
-               $this->tagFilter = ChangeTags::buildTagFilterSelector( $value );
-               if ( $this->tagFilter ) {
-                       return parent::getDiv( $value );
-               }
-               return '';
-       }
-
-       function getInputHTML( $value ) {
-               if ( $this->tagFilter ) {
-                       // we only need the select field, HTMLForm should handle the label
-                       return $this->tagFilter[1];
-               }
-               return '';
-       }
-}
diff --git a/includes/htmlform/HTMLTextAreaField.php b/includes/htmlform/HTMLTextAreaField.php
deleted file mode 100644 (file)
index 8ffff43..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-
-class HTMLTextAreaField extends HTMLFormField {
-       const DEFAULT_COLS = 80;
-       const DEFAULT_ROWS = 25;
-
-       protected $mPlaceholder = '';
-
-       /**
-        * @param array $params
-        *   - cols, rows: textarea size
-        *   - placeholder/placeholder-message: set HTML placeholder attribute
-        *   - spellcheck: set HTML spellcheck attribute
-        */
-       public function __construct( $params ) {
-               parent::__construct( $params );
-
-               if ( isset( $params['placeholder-message'] ) ) {
-                       $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->parse();
-               } elseif ( isset( $params['placeholder'] ) ) {
-                       $this->mPlaceholder = $params['placeholder'];
-               }
-       }
-
-       function getCols() {
-               return isset( $this->mParams['cols'] ) ? $this->mParams['cols'] : static::DEFAULT_COLS;
-       }
-
-       function getRows() {
-               return isset( $this->mParams['rows'] ) ? $this->mParams['rows'] : static::DEFAULT_ROWS;
-       }
-
-       function getSpellCheck() {
-               $val = isset( $this->mParams['spellcheck'] ) ? $this->mParams['spellcheck'] : null;
-               if ( is_bool( $val ) ) {
-                       // "spellcheck" attribute literally requires "true" or "false" to work.
-                       return $val === true ? 'true' : 'false';
-               }
-               return null;
-       }
-
-       function getInputHTML( $value ) {
-               $attribs = [
-                               'id' => $this->mID,
-                               'cols' => $this->getCols(),
-                               'rows' => $this->getRows(),
-                               'spellcheck' => $this->getSpellCheck(),
-                       ] + $this->getTooltipAndAccessKey();
-
-               if ( $this->mClass !== '' ) {
-                       $attribs['class'] = $this->mClass;
-               }
-               if ( $this->mPlaceholder !== '' ) {
-                       $attribs['placeholder'] = $this->mPlaceholder;
-               }
-
-               $allowedParams = [
-                       'tabindex',
-                       'disabled',
-                       'readonly',
-                       'required',
-                       'autofocus'
-               ];
-
-               $attribs += $this->getAttributes( $allowedParams );
-               return Html::textarea( $this->mName, $value, $attribs );
-       }
-
-       function getInputOOUI( $value ) {
-               if ( isset( $this->mParams['cols'] ) ) {
-                       throw new Exception( "OOUIHTMLForm does not support the 'cols' parameter for textareas" );
-               }
-
-               $attribs = $this->getTooltipAndAccessKey();
-
-               if ( $this->mClass !== '' ) {
-                       $attribs['classes'] = [ $this->mClass ];
-               }
-               if ( $this->mPlaceholder !== '' ) {
-                       $attribs['placeholder'] = $this->mPlaceholder;
-               }
-
-               $allowedParams = [
-                       'tabindex',
-                       'disabled',
-                       'readonly',
-                       'required',
-                       'autofocus',
-               ];
-
-               $attribs += OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( $allowedParams )
-               );
-
-               return new OOUI\TextInputWidget( [
-                       'id' => $this->mID,
-                       'name' => $this->mName,
-                       'multiline' => true,
-                       'value' => $value,
-                       'rows' => $this->getRows(),
-               ] + $attribs );
-       }
-}
diff --git a/includes/htmlform/HTMLTextField.php b/includes/htmlform/HTMLTextField.php
deleted file mode 100644 (file)
index 3ab7176..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-<?php
-
-class HTMLTextField extends HTMLFormField {
-       protected $mPlaceholder = '';
-
-       /**
-        * @param array $params
-        *   - type: HTML textfield type
-        *   - size: field size in characters (defaults to 45)
-        *   - placeholder/placeholder-message: set HTML placeholder attribute
-        *   - spellcheck: set HTML spellcheck attribute
-        *   - persistent: upon unsuccessful requests, retain the value (defaults to true, except
-        *     for password fields)
-        */
-       public function __construct( $params ) {
-               parent::__construct( $params );
-
-               if ( isset( $params['placeholder-message'] ) ) {
-                       $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->parse();
-               } elseif ( isset( $params['placeholder'] ) ) {
-                       $this->mPlaceholder = $params['placeholder'];
-               }
-       }
-
-       function getSize() {
-               return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45;
-       }
-
-       function getSpellCheck() {
-               $val = isset( $this->mParams['spellcheck'] ) ? $this->mParams['spellcheck'] : null;
-               if ( is_bool( $val ) ) {
-                       // "spellcheck" attribute literally requires "true" or "false" to work.
-                       return $val === true ? 'true' : 'false';
-               }
-               return null;
-       }
-
-       public function isPersistent() {
-               if ( isset( $this->mParams['persistent'] ) ) {
-                       return $this->mParams['persistent'];
-               }
-               // don't put passwords into the HTML body, they could get cached or otherwise leaked
-               return !( isset( $this->mParams['type'] ) && $this->mParams['type'] === 'password' );
-       }
-
-       function getInputHTML( $value ) {
-               if ( !$this->isPersistent() ) {
-                       $value = '';
-               }
-
-               $attribs = [
-                               'id' => $this->mID,
-                               'name' => $this->mName,
-                               'size' => $this->getSize(),
-                               'value' => $value,
-                               'dir' => $this->mDir,
-                               'spellcheck' => $this->getSpellCheck(),
-                       ] + $this->getTooltipAndAccessKey() + $this->getDataAttribs();
-
-               if ( $this->mClass !== '' ) {
-                       $attribs['class'] = $this->mClass;
-               }
-               if ( $this->mPlaceholder !== '' ) {
-                       $attribs['placeholder'] = $this->mPlaceholder;
-               }
-
-               # @todo Enforce pattern, step, required, readonly on the server side as
-               # well
-               $allowedParams = [
-                       'type',
-                       'min',
-                       'max',
-                       'pattern',
-                       'title',
-                       'step',
-                       'list',
-                       'maxlength',
-                       'tabindex',
-                       'disabled',
-                       'required',
-                       'autofocus',
-                       'multiple',
-                       'readonly'
-               ];
-
-               $attribs += $this->getAttributes( $allowedParams );
-
-               # Extract 'type'
-               $type = $this->getType( $attribs );
-               return Html::input( $this->mName, $value, $type, $attribs );
-       }
-
-       protected function getType( &$attribs ) {
-               $type = isset( $attribs['type'] ) ? $attribs['type'] : 'text';
-               unset( $attribs['type'] );
-
-               # Implement tiny differences between some field variants
-               # here, rather than creating a new class for each one which
-               # is essentially just a clone of this one.
-               if ( isset( $this->mParams['type'] ) ) {
-                       switch ( $this->mParams['type'] ) {
-                               case 'int':
-                                       $type = 'number';
-                                       break;
-                               case 'float':
-                                       $type = 'number';
-                                       $attribs['step'] = 'any';
-                                       break;
-                               # Pass through
-                               case 'email':
-                               case 'password':
-                               case 'file':
-                               case 'url':
-                                       $type = $this->mParams['type'];
-                                       break;
-                       }
-               }
-
-               return $type;
-       }
-
-       function getInputOOUI( $value ) {
-               if ( !$this->isPersistent() ) {
-                       $value = '';
-               }
-
-               $attribs = $this->getTooltipAndAccessKey();
-
-               if ( $this->mClass !== '' ) {
-                       $attribs['classes'] = [ $this->mClass ];
-               }
-               if ( $this->mPlaceholder !== '' ) {
-                       $attribs['placeholder'] = $this->mPlaceholder;
-               }
-
-               # @todo Enforce pattern, step, required, readonly on the server side as
-               # well
-               $allowedParams = [
-                       'autofocus',
-                       'autosize',
-                       'disabled',
-                       'flags',
-                       'indicator',
-                       'maxlength',
-                       'readonly',
-                       'required',
-                       'tabindex',
-                       'type',
-               ];
-
-               $attribs += OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( $allowedParams )
-               );
-
-               $type = $this->getType( $attribs );
-
-               return $this->getInputWidget( [
-                       'id' => $this->mID,
-                       'name' => $this->mName,
-                       'value' => $value,
-                       'type' => $type,
-               ] + $attribs );
-       }
-
-       protected function getInputWidget( $params ) {
-               return new OOUI\TextInputWidget( $params );
-       }
-
-       /**
-        * Returns an array of data-* attributes to add to the field.
-        *
-        * @return array
-        */
-       protected function getDataAttribs() {
-               return [];
-       }
-}
diff --git a/includes/htmlform/HTMLTextFieldWithButton.php b/includes/htmlform/HTMLTextFieldWithButton.php
deleted file mode 100644 (file)
index 7c1c673..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-/**
- * Creates a text input field with a button assigned to the input field.
- */
-class HTMLTextFieldWithButton extends HTMLTextField {
-       /** @var HTMLFormFieldWithButton $mClassWithButton */
-       protected $mClassWithButton = null;
-
-       public function __construct( $info ) {
-               $this->mClassWithButton = new HTMLFormFieldWithButton( $info );
-               parent::__construct( $info );
-       }
-
-       public function getInputHTML( $value ) {
-               return $this->mClassWithButton->getElement( parent::getInputHTML( $value ) );
-       }
-}
diff --git a/includes/htmlform/HTMLTitleTextField.php b/includes/htmlform/HTMLTitleTextField.php
deleted file mode 100644 (file)
index fcf721a..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-use MediaWiki\Widget\TitleInputWidget;
-
-/**
- * Implements a text input field for page titles.
- * Automatically does validation that the title is valid,
- * as well as autocompletion if using the OOUI display format.
- *
- * Note: Forms using GET requests will need to make sure the title value is not
- * an empty string.
- *
- * Optional parameters:
- * 'namespace' - Namespace the page must be in
- * 'relative' - If true and 'namespace' given, strip/add the namespace from/to the title as needed
- * 'creatable' - Whether to validate the title is creatable (not a special page)
- * 'exists' - Whether to validate that the title already exists
- *
- * @since 1.26
- */
-class HTMLTitleTextField extends HTMLTextField {
-       public function __construct( $params ) {
-               $params += [
-                       'namespace' => false,
-                       'relative' => false,
-                       'creatable' => false,
-                       'exists' => false,
-               ];
-
-               parent::__construct( $params );
-       }
-
-       public function validate( $value, $alldata ) {
-               if ( $this->mParent->getMethod() === 'get' && $value === '' ) {
-                       // If the form is a GET form and has no value, assume it hasn't been
-                       // submitted yet, and skip validation
-                       return parent::validate( $value, $alldata );
-               }
-               try {
-                       if ( !$this->mParams['relative'] ) {
-                               $title = Title::newFromTextThrow( $value );
-                       } else {
-                               // Can't use Title::makeTitleSafe(), because it doesn't throw useful exceptions
-                               global $wgContLang;
-                               $namespaceName = $wgContLang->getNsText( $this->mParams['namespace'] );
-                               $title = Title::newFromTextThrow( $namespaceName . ':' . $value );
-                       }
-               } catch ( MalformedTitleException $e ) {
-                       $msg = $this->msg( $e->getErrorMessage() );
-                       $params = $e->getErrorMessageParameters();
-                       if ( $params ) {
-                               $msg->params( $params );
-                       }
-                       return $msg->parse();
-               }
-
-               $text = $title->getPrefixedText();
-               if ( $this->mParams['namespace'] !== false &&
-                       !$title->inNamespace( $this->mParams['namespace'] )
-               ) {
-                       return $this->msg( 'htmlform-title-badnamespace', $this->mParams['namespace'], $text )->parse();
-               }
-
-               if ( $this->mParams['creatable'] && !$title->canExist() ) {
-                       return $this->msg( 'htmlform-title-not-creatable', $text )->escaped();
-               }
-
-               if ( $this->mParams['exists'] && !$title->exists() ) {
-                       return $this->msg( 'htmlform-title-not-exists', $text )->parse();
-               }
-
-               return parent::validate( $value, $alldata );
-       }
-
-       protected function getInputWidget( $params ) {
-               $this->mParent->getOutput()->addModules( 'mediawiki.widgets' );
-               if ( $this->mParams['namespace'] !== false ) {
-                       $params['namespace'] = $this->mParams['namespace'];
-               }
-               $params['relative'] = $this->mParams['relative'];
-               return new TitleInputWidget( $params );
-       }
-
-       public function getInputHtml( $value ) {
-               // add mw-searchInput class to enable search suggestions for non-OOUI, too
-               $this->mClass .= 'mw-searchInput';
-
-               // return the HTMLTextField html
-               return parent::getInputHTML( $value );
-       }
-
-       protected function getDataAttribs() {
-               return [
-                       'data-mw-searchsuggest' => FormatJson::encode( [
-                               'wrapAsLink' => false,
-                       ] ),
-               ];
-       }
-}
diff --git a/includes/htmlform/HTMLUserTextField.php b/includes/htmlform/HTMLUserTextField.php
deleted file mode 100644 (file)
index 5a7e0b9..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-use MediaWiki\Widget\UserInputWidget;
-
-/**
- * Implements a text input field for user names.
- * Automatically auto-completes if using the OOUI display format.
- *
- * FIXME: Does not work for forms that support GET requests.
- *
- * Optional parameters:
- * 'exists' - Whether to validate that the user already exists
- *
- * @since 1.26
- */
-class HTMLUserTextField extends HTMLTextField {
-       public function __construct( $params ) {
-               $params += [
-                       'exists' => false,
-                       'ipallowed' => false,
-               ];
-
-               parent::__construct( $params );
-       }
-
-       public function validate( $value, $alldata ) {
-               // check, if a user exists with the given username
-               $user = User::newFromName( $value, false );
-
-               if ( !$user ) {
-                       return $this->msg( 'htmlform-user-not-valid', $value )->parse();
-               } elseif (
-                       ( $this->mParams['exists'] && $user->getId() === 0 ) &&
-                       !( $this->mParams['ipallowed'] && User::isIP( $value ) )
-               ) {
-                       return $this->msg( 'htmlform-user-not-exists', $user->getName() )->parse();
-               }
-
-               return parent::validate( $value, $alldata );
-       }
-
-       protected function getInputWidget( $params ) {
-               $this->mParent->getOutput()->addModules( 'mediawiki.widgets.UserInputWidget' );
-
-               return new UserInputWidget( $params );
-       }
-
-       public function getInputHtml( $value ) {
-               // add the required module and css class for user suggestions in non-OOUI mode
-               $this->mParent->getOutput()->addModules( 'mediawiki.userSuggest' );
-               $this->mClass .= ' mw-autocomplete-user';
-
-               // return parent html
-               return parent::getInputHTML( $value );
-       }
-}
diff --git a/includes/htmlform/fields/HTMLApiField.php b/includes/htmlform/fields/HTMLApiField.php
new file mode 100644 (file)
index 0000000..24a253e
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+
+class HTMLApiField extends HTMLFormField {
+       public function getTableRow( $value ) {
+               return '';
+       }
+
+       public function getDiv( $value ) {
+               return $this->getTableRow( $value );
+       }
+
+       public function getRaw( $value ) {
+               return $this->getTableRow( $value );
+       }
+
+       public function getInputHTML( $value ) {
+               return '';
+       }
+
+       public function hasVisibleOutput() {
+               return false;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLAutoCompleteSelectField.php b/includes/htmlform/fields/HTMLAutoCompleteSelectField.php
new file mode 100644 (file)
index 0000000..76a88d5
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * Text field for selecting a value from a large list of possible values, with
+ * auto-completion and optionally with a select dropdown for selecting common
+ * options.
+ *
+ * HTMLComboboxField implements most of the same functionality and should be
+ * used instead, if possible.
+ *
+ * If one of 'options-messages', 'options', or 'options-message' is provided
+ * and non-empty, the select dropdown will be shown. An 'other' key will be
+ * appended using message 'htmlform-selectorother-other' if not already
+ * present.
+ *
+ * Besides the parameters recognized by HTMLTextField, the following are
+ * recognized:
+ *   options-messages - As for HTMLSelectField
+ *   options - As for HTMLSelectField
+ *   options-message - As for HTMLSelectField
+ *   autocomplete - Associative array mapping display text to values.
+ *   autocomplete-messages - Like autocomplete, but keys are message names.
+ *   require-match - Boolean, if true the value must be in the options or the
+ *     autocomplete.
+ *   other-message - Message to use instead of htmlform-selectorother-other for
+ *      the 'other' message.
+ *   other - Raw text to use for the 'other' message
+ */
+class HTMLAutoCompleteSelectField extends HTMLTextField {
+       protected $autocomplete = [];
+
+       function __construct( $params ) {
+               $params += [
+                       'require-match' => false,
+               ];
+
+               parent::__construct( $params );
+
+               if ( array_key_exists( 'autocomplete-messages', $this->mParams ) ) {
+                       foreach ( $this->mParams['autocomplete-messages'] as $key => $value ) {
+                               $key = $this->msg( $key )->plain();
+                               $this->autocomplete[$key] = strval( $value );
+                       }
+               } elseif ( array_key_exists( 'autocomplete', $this->mParams ) ) {
+                       foreach ( $this->mParams['autocomplete'] as $key => $value ) {
+                               $this->autocomplete[$key] = strval( $value );
+                       }
+               }
+               if ( !is_array( $this->autocomplete ) || !$this->autocomplete ) {
+                       throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
+               }
+
+               $this->getOptions();
+               if ( $this->mOptions && !in_array( 'other', $this->mOptions, true ) ) {
+                       if ( isset( $params['other-message'] ) ) {
+                               $msg = $this->getMessage( $params['other-message'] )->text();
+                       } elseif ( isset( $params['other'] ) ) {
+                               $msg = $params['other'];
+                       } else {
+                               $msg = wfMessage( 'htmlform-selectorother-other' )->text();
+                       }
+                       $this->mOptions[$msg] = 'other';
+               }
+       }
+
+       function loadDataFromRequest( $request ) {
+               if ( $request->getCheck( $this->mName ) ) {
+                       $val = $request->getText( $this->mName . '-select', 'other' );
+
+                       if ( $val === 'other' ) {
+                               $val = $request->getText( $this->mName );
+                               if ( isset( $this->autocomplete[$val] ) ) {
+                                       $val = $this->autocomplete[$val];
+                               }
+                       }
+
+                       return $val;
+               } else {
+                       return $this->getDefault();
+               }
+       }
+
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
+
+               if ( in_array( strval( $value ), $validOptions, true ) ) {
+                       return true;
+               } elseif ( in_array( strval( $value ), $this->autocomplete, true ) ) {
+                       return true;
+               } elseif ( $this->mParams['require-match'] ) {
+                       return $this->msg( 'htmlform-select-badoption' )->parse();
+               }
+
+               return true;
+       }
+
+       // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
+       public function getAttributes( array $list ) {
+               $attribs = [
+                       'type' => 'text',
+                       'data-autocomplete' => FormatJson::encode( array_keys( $this->autocomplete ) ),
+               ] + parent::getAttributes( $list );
+
+               if ( $this->getOptions() ) {
+                       $attribs['data-hide-if'] = FormatJson::encode(
+                               [ '!==', $this->mName . '-select', 'other' ]
+                       );
+               }
+
+               return $attribs;
+       }
+
+       function getInputHTML( $value ) {
+               $oldClass = $this->mClass;
+               $this->mClass = (array)$this->mClass;
+
+               $valInSelect = false;
+               $ret = '';
+
+               if ( $this->getOptions() ) {
+                       if ( $value !== false ) {
+                               $value = strval( $value );
+                               $valInSelect = in_array(
+                                       $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
+                               );
+                       }
+
+                       $selected = $valInSelect ? $value : 'other';
+                       $select = new XmlSelect( $this->mName . '-select', $this->mID . '-select', $selected );
+                       $select->addOptions( $this->getOptions() );
+                       $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
+
+                       if ( !empty( $this->mParams['disabled'] ) ) {
+                               $select->setAttribute( 'disabled', 'disabled' );
+                       }
+
+                       if ( isset( $this->mParams['tabindex'] ) ) {
+                               $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
+                       }
+
+                       $ret = $select->getHTML() . "<br />\n";
+
+                       $this->mClass[] = 'mw-htmlform-hide-if';
+               }
+
+               if ( $valInSelect ) {
+                       $value = '';
+               } else {
+                       $key = array_search( strval( $value ), $this->autocomplete, true );
+                       if ( $key !== false ) {
+                               $value = $key;
+                       }
+               }
+
+               $this->mClass[] = 'mw-htmlform-autocomplete';
+               $ret .= parent::getInputHTML( $valInSelect ? '' : $value );
+               $this->mClass = $oldClass;
+
+               return $ret;
+       }
+
+       /**
+        * Get the OOUI version of this input.
+        * @param string $value
+        * @return false
+        */
+       function getInputOOUI( $value ) {
+               // To be implemented, for now override the function from HTMLTextField
+               return false;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLButtonField.php b/includes/htmlform/fields/HTMLButtonField.php
new file mode 100644 (file)
index 0000000..64fe7ed
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * Adds a generic button inline to the form. Does not do anything, you must add
+ * click handling code in JavaScript. Use a HTMLSubmitField if you merely
+ * wish to add a submit button to a form.
+ *
+ * Additional recognized configuration parameters include:
+ * - flags: OOUI flags for the button, see OOUI\FlaggedElement
+ * - buttonlabel-message: Message to use for the button display text, instead
+ *   of the value from 'default'. Overrides 'buttonlabel' and 'buttonlabel-raw'.
+ * - buttonlabel: Text to display for the button display text, instead
+ *   of the value from 'default'. Overrides 'buttonlabel-raw'.
+ * - buttonlabel-raw: HTMLto display for the button display text, instead
+ *   of the value from 'default'.
+ *
+ * Note that the buttonlabel parameters are not supported on IE6 and IE7 due to
+ * bugs in those browsers. If detected, they will be served buttons using the
+ * value of 'default' as the button label.
+ *
+ * @since 1.22
+ */
+class HTMLButtonField extends HTMLFormField {
+       protected $buttonType = 'button';
+       protected $buttonLabel = null;
+
+       /** @var array $mFlags Flags to add to OOUI Button widget */
+       protected $mFlags = [];
+
+       public function __construct( $info ) {
+               $info['nodata'] = true;
+               if ( isset( $info['flags'] ) ) {
+                       $this->mFlags = $info['flags'];
+               }
+
+               # Generate the label from a message, if possible
+               if ( isset( $info['buttonlabel-message'] ) ) {
+                       $this->buttonLabel = $this->getMessage( $info['buttonlabel-message'] )->parse();
+               } elseif ( isset( $info['buttonlabel'] ) ) {
+                       if ( $info['buttonlabel'] === '&#160;' ) {
+                               // Apparently some things set &nbsp directly and in an odd format
+                               $this->buttonLabel = '&#160;';
+                       } else {
+                               $this->buttonLabel = htmlspecialchars( $info['buttonlabel'] );
+                       }
+               } elseif ( isset( $info['buttonlabel-raw'] ) ) {
+                       $this->buttonLabel = $info['buttonlabel-raw'];
+               }
+
+               $this->setShowEmptyLabel( false );
+
+               parent::__construct( $info );
+       }
+
+       public function getInputHTML( $value ) {
+               $flags = '';
+               $prefix = 'mw-htmlform-';
+               if ( $this->mParent instanceof VFormHTMLForm ||
+                       $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' )
+               ) {
+                       $prefix = 'mw-ui-';
+                       // add mw-ui-button separately, so the descriptor doesn't need to set it
+                       $flags .= ' ' . $prefix . 'button';
+               }
+               foreach ( $this->mFlags as $flag ) {
+                       $flags .= ' ' . $prefix . $flag;
+               }
+               $attr = [
+                       'class' => 'mw-htmlform-submit ' . $this->mClass . $flags,
+                       'id' => $this->mID,
+                       'type' => $this->buttonType,
+                       'name' => $this->mName,
+                       'value' => $this->getDefault(),
+               ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
+
+               if ( $this->isBadIE() ) {
+                       return Html::element( 'input', $attr );
+               } else {
+                       return Html::rawElement( 'button', $attr,
+                               $this->buttonLabel ?: htmlspecialchars( $this->getDefault() ) );
+               }
+       }
+
+       /**
+        * Get the OOUI widget for this field.
+        * @param string $value
+        * @return OOUI\ButtonInputWidget
+        */
+       public function getInputOOUI( $value ) {
+               return new OOUI\ButtonInputWidget( [
+                       'name' => $this->mName,
+                       'value' => $this->getDefault(),
+                       'label' => !$this->isBadIE() && $this->buttonLabel
+                               ? new OOUI\HtmlSnippet( $this->buttonLabel )
+                               : $this->getDefault(),
+                       'type' => $this->buttonType,
+                       'classes' => [ 'mw-htmlform-submit', $this->mClass ],
+                       'id' => $this->mID,
+                       'flags' => $this->mFlags,
+                       'useInputTag' => $this->isBadIE(),
+               ] + OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               ) );
+       }
+
+       protected function needsLabel() {
+               return false;
+       }
+
+       /**
+        * Button cannot be invalid
+        *
+        * @param string $value
+        * @param array $alldata
+        *
+        * @return bool
+        */
+       public function validate( $value, $alldata ) {
+               return true;
+       }
+
+       /**
+        * IE<8 has bugs with <button>, so we'll need to avoid them.
+        * @return bool Whether the request is from a bad version of IE
+        */
+       private function isBadIE() {
+               $request = $this->mParent
+                       ? $this->mParent->getRequest()
+                       : RequestContext::getMain()->getRequest();
+               return preg_match( '/MSIE [1-7]\./i', $request->getHeader( 'User-Agent' ) );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLCheckField.php b/includes/htmlform/fields/HTMLCheckField.php
new file mode 100644 (file)
index 0000000..a553839
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+
+/**
+ * A checkbox field
+ */
+class HTMLCheckField extends HTMLFormField {
+       function getInputHTML( $value ) {
+               global $wgUseMediaWikiUIEverywhere;
+
+               if ( !empty( $this->mParams['invert'] ) ) {
+                       $value = !$value;
+               }
+
+               $attr = $this->getTooltipAndAccessKey();
+               $attr['id'] = $this->mID;
+
+               $attr += $this->getAttributes( [ 'disabled', 'tabindex' ] );
+
+               if ( $this->mClass !== '' ) {
+                       $attr['class'] = $this->mClass;
+               }
+
+               $attrLabel = [ 'for' => $this->mID ];
+               if ( isset( $attr['title'] ) ) {
+                       // propagate tooltip to label
+                       $attrLabel['title'] = $attr['title'];
+               }
+
+               $chkLabel = Xml::check( $this->mName, $value, $attr ) .
+                       '&#160;' .
+                       Html::rawElement( 'label', $attrLabel, $this->mLabel );
+
+               if ( $wgUseMediaWikiUIEverywhere || $this->mParent instanceof VFormHTMLForm ) {
+                       $chkLabel = Html::rawElement(
+                               'div',
+                               [ 'class' => 'mw-ui-checkbox' ],
+                               $chkLabel
+                       );
+               }
+
+               return $chkLabel;
+       }
+
+       /**
+        * Get the OOUI version of this field.
+        * @since 1.26
+        * @param string $value
+        * @return OOUI\CheckboxInputWidget The checkbox widget.
+        */
+       public function getInputOOUI( $value ) {
+               if ( !empty( $this->mParams['invert'] ) ) {
+                       $value = !$value;
+               }
+
+               $attr = $this->getTooltipAndAccessKey();
+               $attr['id'] = $this->mID;
+               $attr['name'] = $this->mName;
+
+               $attr += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               );
+
+               if ( $this->mClass !== '' ) {
+                       $attr['classes'] = [ $this->mClass ];
+               }
+
+               $attr['selected'] = $value;
+               $attr['value'] = '1'; // Nasty hack, but needed to make this work
+
+               return new OOUI\CheckboxInputWidget( $attr );
+       }
+
+       /**
+        * For a checkbox, the label goes on the right hand side, and is
+        * added in getInputHTML(), rather than HTMLFormField::getRow()
+        *
+        * ...unless OOUI is being used, in which case we actually return
+        * the label here.
+        *
+        * @return string
+        */
+       function getLabel() {
+               if ( $this->mParent instanceof OOUIHTMLForm ) {
+                       return $this->mLabel;
+               } elseif (
+                       $this->mParent instanceof HTMLForm &&
+                       $this->mParent->getDisplayFormat() === 'div'
+               ) {
+                       return '';
+               } else {
+                       return '&#160;';
+               }
+       }
+
+       /**
+        * Get label alignment when generating field for OOUI.
+        * @return string 'left', 'right', 'top' or 'inline'
+        */
+       protected function getLabelAlignOOUI() {
+               return 'inline';
+       }
+
+       /**
+        * checkboxes don't need a label.
+        * @return bool
+        */
+       protected function needsLabel() {
+               return false;
+       }
+
+       /**
+        * @param WebRequest $request
+        *
+        * @return bool
+        */
+       function loadDataFromRequest( $request ) {
+               $invert = isset( $this->mParams['invert'] ) && $this->mParams['invert'];
+
+               // GetCheck won't work like we want for checks.
+               // Fetch the value in either one of the two following case:
+               // - we have a valid submit attempt (form was just submitted, or a GET URL forged by the user)
+               // - checkbox name has a value (false or true), ie is not null
+               if ( $this->isSubmitAttempt( $request ) || $request->getVal( $this->mName ) !== null ) {
+                       return $invert
+                               ? !$request->getBool( $this->mName )
+                               : $request->getBool( $this->mName );
+               } else {
+                       return (bool)$this->getDefault();
+               }
+       }
+}
diff --git a/includes/htmlform/fields/HTMLCheckMatrix.php b/includes/htmlform/fields/HTMLCheckMatrix.php
new file mode 100644 (file)
index 0000000..b324fb6
--- /dev/null
@@ -0,0 +1,266 @@
+<?php
+
+/**
+ * A checkbox matrix
+ * Operates similarly to HTMLMultiSelectField, but instead of using an array of
+ * options, uses an array of rows and an array of columns to dynamically
+ * construct a matrix of options. The tags used to identify a particular cell
+ * are of the form "columnName-rowName"
+ *
+ * Options:
+ *   - columns
+ *     - Required list of columns in the matrix.
+ *   - rows
+ *     - Required list of rows in the matrix.
+ *   - force-options-on
+ *     - Accepts array of column-row tags to be displayed as enabled but unavailable to change
+ *   - force-options-off
+ *     - Accepts array of column-row tags to be displayed as disabled but unavailable to change.
+ *   - tooltips
+ *     - Optional array mapping row label to tooltip content
+ *   - tooltip-class
+ *     - Optional CSS class used on tooltip container span. Defaults to mw-icon-question.
+ */
+class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
+       static private $requiredParams = [
+               // Required by underlying HTMLFormField
+               'fieldname',
+               // Required by HTMLCheckMatrix
+               'rows',
+               'columns'
+       ];
+
+       public function __construct( $params ) {
+               $missing = array_diff( self::$requiredParams, array_keys( $params ) );
+               if ( $missing ) {
+                       throw new HTMLFormFieldRequiredOptionsException( $this, $missing );
+               }
+               parent::__construct( $params );
+       }
+
+       function validate( $value, $alldata ) {
+               $rows = $this->mParams['rows'];
+               $columns = $this->mParams['columns'];
+
+               // Make sure user-defined validation callback is run
+               $p = parent::validate( $value, $alldata );
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               // Make sure submitted value is an array
+               if ( !is_array( $value ) ) {
+                       return false;
+               }
+
+               // If all options are valid, array_intersect of the valid options
+               // and the provided options will return the provided options.
+               $validOptions = [];
+               foreach ( $rows as $rowTag ) {
+                       foreach ( $columns as $columnTag ) {
+                               $validOptions[] = $columnTag . '-' . $rowTag;
+                       }
+               }
+               $validValues = array_intersect( $value, $validOptions );
+               if ( count( $validValues ) == count( $value ) ) {
+                       return true;
+               } else {
+                       return $this->msg( 'htmlform-select-badoption' )->parse();
+               }
+       }
+
+       /**
+        * Build a table containing a matrix of checkbox options.
+        * The value of each option is a combination of the row tag and column tag.
+        * mParams['rows'] is an array with row labels as keys and row tags as values.
+        * mParams['columns'] is an array with column labels as keys and column tags as values.
+        *
+        * @param array $value Array of the options that should be checked
+        *
+        * @return string
+        */
+       function getInputHTML( $value ) {
+               $html = '';
+               $tableContents = '';
+               $rows = $this->mParams['rows'];
+               $columns = $this->mParams['columns'];
+
+               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
+
+               // Build the column headers
+               $headerContents = Html::rawElement( 'td', [], '&#160;' );
+               foreach ( $columns as $columnLabel => $columnTag ) {
+                       $headerContents .= Html::rawElement( 'td', [], $columnLabel );
+               }
+               $tableContents .= Html::rawElement( 'tr', [], "\n$headerContents\n" );
+
+               $tooltipClass = 'mw-icon-question';
+               if ( isset( $this->mParams['tooltip-class'] ) ) {
+                       $tooltipClass = $this->mParams['tooltip-class'];
+               }
+
+               // Build the options matrix
+               foreach ( $rows as $rowLabel => $rowTag ) {
+                       // Append tooltip if configured
+                       if ( isset( $this->mParams['tooltips'][$rowLabel] ) ) {
+                               $tooltipAttribs = [
+                                       'class' => "mw-htmlform-tooltip $tooltipClass",
+                                       'title' => $this->mParams['tooltips'][$rowLabel],
+                               ];
+                               $rowLabel .= ' ' . Html::element( 'span', $tooltipAttribs, '' );
+                       }
+                       $rowContents = Html::rawElement( 'td', [], $rowLabel );
+                       foreach ( $columns as $columnTag ) {
+                               $thisTag = "$columnTag-$rowTag";
+                               // Construct the checkbox
+                               $thisAttribs = [
+                                       'id' => "{$this->mID}-$thisTag",
+                                       'value' => $thisTag,
+                               ];
+                               $checked = in_array( $thisTag, (array)$value, true );
+                               if ( $this->isTagForcedOff( $thisTag ) ) {
+                                       $checked = false;
+                                       $thisAttribs['disabled'] = 1;
+                               } elseif ( $this->isTagForcedOn( $thisTag ) ) {
+                                       $checked = true;
+                                       $thisAttribs['disabled'] = 1;
+                               }
+
+                               $checkbox = $this->getOneCheckbox( $checked, $attribs + $thisAttribs );
+
+                               $rowContents .= Html::rawElement(
+                                       'td',
+                                       [],
+                                       $checkbox
+                               );
+                       }
+                       $tableContents .= Html::rawElement( 'tr', [], "\n$rowContents\n" );
+               }
+
+               // Put it all in a table
+               $html .= Html::rawElement( 'table',
+                               [ 'class' => 'mw-htmlform-matrix' ],
+                               Html::rawElement( 'tbody', [], "\n$tableContents\n" ) ) . "\n";
+
+               return $html;
+       }
+
+       protected function getOneCheckbox( $checked, $attribs ) {
+               if ( $this->mParent instanceof OOUIHTMLForm ) {
+                       return new OOUI\CheckboxInputWidget( [
+                               'name' => "{$this->mName}[]",
+                               'selected' => $checked,
+                       ] + OOUI\Element::configFromHtmlAttributes(
+                               $attribs
+                       ) );
+               } else {
+                       $checkbox = Xml::check( "{$this->mName}[]", $checked, $attribs );
+                       if ( $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                               $checkbox = Html::openElement( 'div', [ 'class' => 'mw-ui-checkbox' ] ) .
+                                       $checkbox .
+                                       Html::element( 'label', [ 'for' => $attribs['id'] ] ) .
+                                       Html::closeElement( 'div' );
+                       }
+                       return $checkbox;
+               }
+       }
+
+       protected function isTagForcedOff( $tag ) {
+               return isset( $this->mParams['force-options-off'] )
+                       && in_array( $tag, $this->mParams['force-options-off'] );
+       }
+
+       protected function isTagForcedOn( $tag ) {
+               return isset( $this->mParams['force-options-on'] )
+                       && in_array( $tag, $this->mParams['force-options-on'] );
+       }
+
+       /**
+        * Get the complete table row for the input, including help text,
+        * labels, and whatever.
+        * We override this function since the label should always be on a separate
+        * line above the options in the case of a checkbox matrix, i.e. it's always
+        * a "vertical-label".
+        *
+        * @param string $value The value to set the input to
+        *
+        * @return string Complete HTML table row
+        */
+       function getTableRow( $value ) {
+               list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
+               $inputHtml = $this->getInputHTML( $value );
+               $fieldType = get_class( $this );
+               $helptext = $this->getHelpTextHtmlTable( $this->getHelpText() );
+               $cellAttributes = [ 'colspan' => 2 ];
+
+               $hideClass = '';
+               $hideAttributes = [];
+               if ( $this->mHideIf ) {
+                       $hideAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
+                       $hideClass = 'mw-htmlform-hide-if';
+               }
+
+               $label = $this->getLabelHtml( $cellAttributes );
+
+               $field = Html::rawElement(
+                       'td',
+                       [ 'class' => 'mw-input' ] + $cellAttributes,
+                       $inputHtml . "\n$errors"
+               );
+
+               $html = Html::rawElement( 'tr',
+                       [ 'class' => "mw-htmlform-vertical-label $hideClass" ] + $hideAttributes,
+                       $label );
+               $html .= Html::rawElement( 'tr',
+                       [ 'class' => "mw-htmlform-field-$fieldType {$this->mClass} $errorClass $hideClass" ] +
+                               $hideAttributes,
+                       $field );
+
+               return $html . $helptext;
+       }
+
+       /**
+        * @param WebRequest $request
+        *
+        * @return array
+        */
+       function loadDataFromRequest( $request ) {
+               if ( $this->isSubmitAttempt( $request ) ) {
+                       // Checkboxes are just not added to the request arrays if they're not checked,
+                       // so it's perfectly possible for there not to be an entry at all
+                       return $request->getArray( $this->mName, [] );
+               } else {
+                       // That's ok, the user has not yet submitted the form, so show the defaults
+                       return $this->getDefault();
+               }
+       }
+
+       function getDefault() {
+               if ( isset( $this->mDefault ) ) {
+                       return $this->mDefault;
+               } else {
+                       return [];
+               }
+       }
+
+       function filterDataForSubmit( $data ) {
+               $columns = HTMLFormField::flattenOptions( $this->mParams['columns'] );
+               $rows = HTMLFormField::flattenOptions( $this->mParams['rows'] );
+               $res = [];
+               foreach ( $columns as $column ) {
+                       foreach ( $rows as $row ) {
+                               // Make sure option hasn't been forced
+                               $thisTag = "$column-$row";
+                               if ( $this->isTagForcedOff( $thisTag ) ) {
+                                       $res[$thisTag] = false;
+                               } elseif ( $this->isTagForcedOn( $thisTag ) ) {
+                                       $res[$thisTag] = true;
+                               } else {
+                                       $res[$thisTag] = in_array( $thisTag, $data );
+                               }
+                       }
+               }
+
+               return $res;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLComboboxField.php b/includes/htmlform/fields/HTMLComboboxField.php
new file mode 100644 (file)
index 0000000..778aedb
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * A combo box field.
+ *
+ * You can think of it as a dropdown select with the ability to add custom options,
+ * or as a text field with input suggestions (autocompletion).
+ *
+ * When JavaScript is not supported or enabled, it uses HTML5 `<datalist>` element.
+ *
+ * Besides the parameters recognized by HTMLTextField, the following are
+ * recognized:
+ *   options-messages - As for HTMLSelectField
+ *   options - As for HTMLSelectField
+ *   options-message - As for HTMLSelectField
+ */
+class HTMLComboboxField extends HTMLTextField {
+       // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
+       public function getAttributes( array $list ) {
+               $attribs = [
+                       'type' => 'text',
+                       'list' => $this->mName . '-datalist',
+               ] + parent::getAttributes( $list );
+
+               return $attribs;
+       }
+
+       function getInputHTML( $value ) {
+               $datalist = new XmlSelect( false, $this->mName . '-datalist' );
+               $datalist->setTagName( 'datalist' );
+               $datalist->addOptions( $this->getOptions() );
+
+               return parent::getInputHTML( $value ) . $datalist->getHTML();
+       }
+
+       function getInputOOUI( $value ) {
+               $disabled = false;
+               $allowedParams = [ 'tabindex' ];
+               $attribs = OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['classes'] = [ $this->mClass ];
+               }
+
+               if ( !empty( $this->mParams['disabled'] ) ) {
+                       $disabled = true;
+               }
+
+               return new OOUI\ComboBoxInputWidget( [
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+                       'options' => $this->getOptionsOOUI(),
+                       'value' => strval( $value ),
+                       'disabled' => $disabled,
+               ] + $attribs );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLEditTools.php b/includes/htmlform/fields/HTMLEditTools.php
new file mode 100644 (file)
index 0000000..1b5d1fb
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+class HTMLEditTools extends HTMLFormField {
+       public function getInputHTML( $value ) {
+               return '';
+       }
+
+       public function getTableRow( $value ) {
+               $msg = $this->formatMsg();
+
+               return
+                       '<tr><td></td><td class="mw-input">' .
+                       '<div class="mw-editTools">' .
+                       $msg->parseAsBlock() .
+                       "</div></td></tr>\n";
+       }
+
+       /**
+        * @param string $value
+        * @return string
+        * @since 1.20
+        */
+       public function getDiv( $value ) {
+               $msg = $this->formatMsg();
+
+               return '<div class="mw-editTools">' . $msg->parseAsBlock() . '</div>';
+       }
+
+       /**
+        * @param string $value
+        * @return string
+        * @since 1.20
+        */
+       public function getRaw( $value ) {
+               return $this->getDiv( $value );
+       }
+
+       protected function formatMsg() {
+               if ( empty( $this->mParams['message'] ) ) {
+                       $msg = $this->msg( 'edittools' );
+               } else {
+                       $msg = $this->getMessage( $this->mParams['message'] );
+                       if ( $msg->isDisabled() ) {
+                               $msg = $this->msg( 'edittools' );
+                       }
+               }
+               $msg->inContentLanguage();
+
+               return $msg;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLFloatField.php b/includes/htmlform/fields/HTMLFloatField.php
new file mode 100644 (file)
index 0000000..2ef4978
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * A field that will contain a numeric value
+ */
+class HTMLFloatField extends HTMLTextField {
+       function getSize() {
+               return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 20;
+       }
+
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               $value = trim( $value );
+
+               # http://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
+               # with the addition that a leading '+' sign is ok.
+               if ( !preg_match( '/^((\+|\-)?\d+(\.\d+)?(E(\+|\-)?\d+)?)?$/i', $value ) ) {
+                       return $this->msg( 'htmlform-float-invalid' )->parseAsBlock();
+               }
+
+               # The "int" part of these message names is rather confusing.
+               # They make equal sense for all numbers.
+               if ( isset( $this->mParams['min'] ) ) {
+                       $min = $this->mParams['min'];
+
+                       if ( $min > $value ) {
+                               return $this->msg( 'htmlform-int-toolow', $min )->parseAsBlock();
+                       }
+               }
+
+               if ( isset( $this->mParams['max'] ) ) {
+                       $max = $this->mParams['max'];
+
+                       if ( $max < $value ) {
+                               return $this->msg( 'htmlform-int-toohigh', $max )->parseAsBlock();
+                       }
+               }
+
+               return true;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLFormFieldCloner.php b/includes/htmlform/fields/HTMLFormFieldCloner.php
new file mode 100644 (file)
index 0000000..ec1bd84
--- /dev/null
@@ -0,0 +1,380 @@
+<?php
+
+/**
+ * A container for HTMLFormFields that allows for multiple copies of the set of
+ * fields to be displayed to and entered by the user.
+ *
+ * Recognized parameters, besides the general ones, include:
+ *   fields - HTMLFormField descriptors for the subfields this cloner manages.
+ *     The format is just like for the HTMLForm. A field with key 'delete' is
+ *     special: it must have type = submit and will serve to delete the group
+ *     of fields.
+ *   required - If specified, at least one group of fields must be submitted.
+ *   format - HTMLForm display format to use when displaying the subfields:
+ *     'table', 'div', or 'raw'.
+ *   row-legend - If non-empty, each group of subfields will be enclosed in a
+ *     fieldset. The value is the name of a message key to use as the legend.
+ *   create-button-message - Message to use as the text of the button to
+ *     add an additional group of fields.
+ *   delete-button-message - Message to use as the text of automatically-
+ *     generated 'delete' button. Ignored if 'delete' is included in 'fields'.
+ *
+ * In the generated HTML, the subfields will be named along the lines of
+ * "clonerName[index][fieldname]", with ids "clonerId--index--fieldid". 'index'
+ * may be a number or an arbitrary string, and may likely change when the page
+ * is resubmitted. Cloners may be nested, resulting in field names along the
+ * lines of "cloner1Name[index1][cloner2Name][index2][fieldname]" and
+ * corresponding ids.
+ *
+ * Use of cloner may result in submissions of the page that are not submissions
+ * of the HTMLForm, when non-JavaScript clients use the create or remove buttons.
+ *
+ * The result is an array, with values being arrays mapping subfield names to
+ * their values. On non-HTMLForm-submission page loads, there may also be
+ * additional (string) keys present with other types of values.
+ *
+ * @since 1.23
+ */
+class HTMLFormFieldCloner extends HTMLFormField {
+       private static $counter = 0;
+
+       /**
+        * @var string String uniquely identifying this cloner instance and
+        * unlikely to exist otherwise in the generated HTML, while still being
+        * valid as part of an HTML id.
+        */
+       protected $uniqueId;
+
+       public function __construct( $params ) {
+               $this->uniqueId = get_class( $this ) . ++self::$counter . 'x';
+               parent::__construct( $params );
+
+               if ( empty( $this->mParams['fields'] ) || !is_array( $this->mParams['fields'] ) ) {
+                       throw new MWException( 'HTMLFormFieldCloner called without any fields' );
+               }
+
+               // Make sure the delete button, if explicitly specified, is sane
+               if ( isset( $this->mParams['fields']['delete'] ) ) {
+                       $class = 'mw-htmlform-cloner-delete-button';
+                       $info = $this->mParams['fields']['delete'] + [
+                               'cssclass' => $class
+                       ];
+                       unset( $info['name'], $info['class'] );
+
+                       if ( !isset( $info['type'] ) || $info['type'] !== 'submit' ) {
+                               throw new MWException(
+                                       'HTMLFormFieldCloner delete field, if specified, must be of type "submit"'
+                               );
+                       }
+
+                       if ( !in_array( $class, explode( ' ', $info['cssclass'] ) ) ) {
+                               $info['cssclass'] .= " $class";
+                       }
+
+                       $this->mParams['fields']['delete'] = $info;
+               }
+       }
+
+       /**
+        * Create the HTMLFormFields that go inside this element, using the
+        * specified key.
+        *
+        * @param string $key Array key under which these fields should be named
+        * @return HTMLFormField[]
+        */
+       protected function createFieldsForKey( $key ) {
+               $fields = [];
+               foreach ( $this->mParams['fields'] as $fieldname => $info ) {
+                       $name = "{$this->mName}[$key][$fieldname]";
+                       if ( isset( $info['name'] ) ) {
+                               $info['name'] = "{$this->mName}[$key][{$info['name']}]";
+                       } else {
+                               $info['name'] = $name;
+                       }
+                       if ( isset( $info['id'] ) ) {
+                               $info['id'] = Sanitizer::escapeId( "{$this->mID}--$key--{$info['id']}" );
+                       } else {
+                               $info['id'] = Sanitizer::escapeId( "{$this->mID}--$key--$fieldname" );
+                       }
+                       $field = HTMLForm::loadInputFromParameters( $name, $info, $this->mParent );
+                       $fields[$fieldname] = $field;
+               }
+               return $fields;
+       }
+
+       /**
+        * Re-key the specified values array to match the names applied by
+        * createFieldsForKey().
+        *
+        * @param string $key Array key under which these fields should be named
+        * @param array $values Values array from the request
+        * @return array
+        */
+       protected function rekeyValuesArray( $key, $values ) {
+               $data = [];
+               foreach ( $values as $fieldname => $value ) {
+                       $name = "{$this->mName}[$key][$fieldname]";
+                       $data[$name] = $value;
+               }
+               return $data;
+       }
+
+       protected function needsLabel() {
+               return false;
+       }
+
+       public function loadDataFromRequest( $request ) {
+               // It's possible that this might be posted with no fields. Detect that
+               // by looking for an edit token.
+               if ( !$request->getCheck( 'wpEditToken' ) && $request->getArray( $this->mName ) === null ) {
+                       return $this->getDefault();
+               }
+
+               $values = $request->getArray( $this->mName );
+               if ( $values === null ) {
+                       $values = [];
+               }
+
+               $ret = [];
+               foreach ( $values as $key => $value ) {
+                       if ( $key === 'create' || isset( $value['delete'] ) ) {
+                               $ret['nonjs'] = 1;
+                               continue;
+                       }
+
+                       // Add back in $request->getValues() so things that look for e.g.
+                       // wpEditToken don't fail.
+                       $data = $this->rekeyValuesArray( $key, $value ) + $request->getValues();
+
+                       $fields = $this->createFieldsForKey( $key );
+                       $subrequest = new DerivativeRequest( $request, $data, $request->wasPosted() );
+                       $row = [];
+                       foreach ( $fields as $fieldname => $field ) {
+                               if ( $field->skipLoadData( $subrequest ) ) {
+                                       continue;
+                               } elseif ( !empty( $field->mParams['disabled'] ) ) {
+                                       $row[$fieldname] = $field->getDefault();
+                               } else {
+                                       $row[$fieldname] = $field->loadDataFromRequest( $subrequest );
+                               }
+                       }
+                       $ret[] = $row;
+               }
+
+               if ( isset( $values['create'] ) ) {
+                       // Non-JS client clicked the "create" button.
+                       $fields = $this->createFieldsForKey( $this->uniqueId );
+                       $row = [];
+                       foreach ( $fields as $fieldname => $field ) {
+                               if ( !empty( $field->mParams['nodata'] ) ) {
+                                       continue;
+                               } else {
+                                       $row[$fieldname] = $field->getDefault();
+                               }
+                       }
+                       $ret[] = $row;
+               }
+
+               return $ret;
+       }
+
+       public function getDefault() {
+               $ret = parent::getDefault();
+
+               // The default default is one entry with all subfields at their
+               // defaults.
+               if ( $ret === null ) {
+                       $fields = $this->createFieldsForKey( $this->uniqueId );
+                       $row = [];
+                       foreach ( $fields as $fieldname => $field ) {
+                               if ( !empty( $field->mParams['nodata'] ) ) {
+                                       continue;
+                               } else {
+                                       $row[$fieldname] = $field->getDefault();
+                               }
+                       }
+                       $ret = [ $row ];
+               }
+
+               return $ret;
+       }
+
+       public function cancelSubmit( $values, $alldata ) {
+               if ( isset( $values['nonjs'] ) ) {
+                       return true;
+               }
+
+               foreach ( $values as $key => $value ) {
+                       $fields = $this->createFieldsForKey( $key );
+                       foreach ( $fields as $fieldname => $field ) {
+                               if ( !array_key_exists( $fieldname, $value ) ) {
+                                       continue;
+                               }
+                               if ( $field->cancelSubmit( $value[$fieldname], $alldata ) ) {
+                                       return true;
+                               }
+                       }
+               }
+
+               return parent::cancelSubmit( $values, $alldata );
+       }
+
+       public function validate( $values, $alldata ) {
+               if ( isset( $this->mParams['required'] )
+                       && $this->mParams['required'] !== false
+                       && !$values
+               ) {
+                       return $this->msg( 'htmlform-cloner-required' )->parseAsBlock();
+               }
+
+               if ( isset( $values['nonjs'] ) ) {
+                       // The submission was a non-JS create/delete click, so fail
+                       // validation in case cancelSubmit() somehow didn't already handle
+                       // it.
+                       return false;
+               }
+
+               foreach ( $values as $key => $value ) {
+                       $fields = $this->createFieldsForKey( $key );
+                       foreach ( $fields as $fieldname => $field ) {
+                               if ( !array_key_exists( $fieldname, $value ) ) {
+                                       continue;
+                               }
+                               $ok = $field->validate( $value[$fieldname], $alldata );
+                               if ( $ok !== true ) {
+                                       return false;
+                               }
+                       }
+               }
+
+               return parent::validate( $values, $alldata );
+       }
+
+       /**
+        * Get the input HTML for the specified key.
+        *
+        * @param string $key Array key under which the fields should be named
+        * @param array $values
+        * @return string
+        */
+       protected function getInputHTMLForKey( $key, $values ) {
+               $displayFormat = isset( $this->mParams['format'] )
+                       ? $this->mParams['format']
+                       : $this->mParent->getDisplayFormat();
+
+               // Conveniently, PHP method names are case-insensitive.
+               $getFieldHtmlMethod = $displayFormat == 'table' ? 'getTableRow' : ( 'get' . $displayFormat );
+
+               $html = '';
+               $hidden = '';
+               $hasLabel = false;
+
+               $fields = $this->createFieldsForKey( $key );
+               foreach ( $fields as $fieldname => $field ) {
+                       $v = array_key_exists( $fieldname, $values )
+                               ? $values[$fieldname]
+                               : $field->getDefault();
+
+                       if ( $field instanceof HTMLHiddenField ) {
+                               // HTMLHiddenField doesn't generate its own HTML
+                               list( $name, $value, $params ) = $field->getHiddenFieldData( $v );
+                               $hidden .= Html::hidden( $name, $value, $params ) . "\n";
+                       } else {
+                               $html .= $field->$getFieldHtmlMethod( $v );
+
+                               $labelValue = trim( $field->getLabel() );
+                               if ( $labelValue != '&#160;' && $labelValue !== '' ) {
+                                       $hasLabel = true;
+                               }
+                       }
+               }
+
+               if ( !isset( $fields['delete'] ) ) {
+                       $name = "{$this->mName}[$key][delete]";
+                       $label = isset( $this->mParams['delete-button-message'] )
+                               ? $this->mParams['delete-button-message']
+                               : 'htmlform-cloner-delete';
+                       $field = HTMLForm::loadInputFromParameters( $name, [
+                               'type' => 'submit',
+                               'name' => $name,
+                               'id' => Sanitizer::escapeId( "{$this->mID}--$key--delete" ),
+                               'cssclass' => 'mw-htmlform-cloner-delete-button',
+                               'default' => $this->getMessage( $label )->text(),
+                       ], $this->mParent );
+                       $v = $field->getDefault();
+
+                       if ( $displayFormat === 'table' ) {
+                               $html .= $field->$getFieldHtmlMethod( $v );
+                       } else {
+                               $html .= $field->getInputHTML( $v );
+                       }
+               }
+
+               if ( $displayFormat !== 'raw' ) {
+                       $classes = [
+                               'mw-htmlform-cloner-row',
+                       ];
+
+                       if ( !$hasLabel ) { // Avoid strange spacing when no labels exist
+                               $classes[] = 'mw-htmlform-nolabel';
+                       }
+
+                       $attribs = [
+                               'class' => implode( ' ', $classes ),
+                       ];
+
+                       if ( $displayFormat === 'table' ) {
+                               $html = Html::rawElement( 'table',
+                                       $attribs,
+                                       Html::rawElement( 'tbody', [], "\n$html\n" ) ) . "\n";
+                       } else {
+                               $html = Html::rawElement( 'div', $attribs, "\n$html\n" );
+                       }
+               }
+
+               $html .= $hidden;
+
+               if ( !empty( $this->mParams['row-legend'] ) ) {
+                       $legend = $this->msg( $this->mParams['row-legend'] )->text();
+                       $html = Xml::fieldset( $legend, $html );
+               }
+
+               return $html;
+       }
+
+       public function getInputHTML( $values ) {
+               $html = '';
+
+               foreach ( (array)$values as $key => $value ) {
+                       if ( $key === 'nonjs' ) {
+                               continue;
+                       }
+                       $html .= Html::rawElement( 'li', [ 'class' => 'mw-htmlform-cloner-li' ],
+                               $this->getInputHTMLForKey( $key, $value )
+                       );
+               }
+
+               $template = $this->getInputHTMLForKey( $this->uniqueId, null );
+               $html = Html::rawElement( 'ul', [
+                       'id' => "mw-htmlform-cloner-list-{$this->mID}",
+                       'class' => 'mw-htmlform-cloner-ul',
+                       'data-template' => $template,
+                       'data-unique-id' => $this->uniqueId,
+               ], $html );
+
+               $name = "{$this->mName}[create]";
+               $label = isset( $this->mParams['create-button-message'] )
+                       ? $this->mParams['create-button-message']
+                       : 'htmlform-cloner-create';
+               $field = HTMLForm::loadInputFromParameters( $name, [
+                       'type' => 'submit',
+                       'name' => $name,
+                       'id' => Sanitizer::escapeId( "{$this->mID}--create" ),
+                       'cssclass' => 'mw-htmlform-cloner-create-button',
+                       'default' => $this->getMessage( $label )->text(),
+               ], $this->mParent );
+               $html .= $field->getInputHTML( $field->getDefault() );
+
+               return $html;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLFormFieldWithButton.php b/includes/htmlform/fields/HTMLFormFieldWithButton.php
new file mode 100644 (file)
index 0000000..bcb07bd
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Enables HTMLFormField elements to be build with a button.
+ */
+class HTMLFormFieldWithButton extends HTMLFormField {
+       /** @var string $mButtonClass CSS class for the button in this field */
+       protected $mButtonClass = '';
+
+       /** @var string|integer $mButtonId Element ID for the button in this field */
+       protected $mButtonId = '';
+
+       /** @var string $mButtonName Name the button in this field */
+       protected $mButtonName = '';
+
+       /** @var string $mButtonType Type of the button in this field (e.g. button or submit) */
+       protected $mButtonType = 'submit';
+
+       /** @var string $mButtonType Value for the button in this field */
+       protected $mButtonValue;
+
+       /** @var string $mButtonType Value for the button in this field */
+       protected $mButtonFlags = [ 'progressive' ];
+
+       public function __construct( $info ) {
+               if ( isset( $info['buttonclass'] ) ) {
+                       $this->mButtonClass = $info['buttonclass'];
+               }
+               if ( isset( $info['buttonid'] ) ) {
+                       $this->mButtonId = $info['buttonid'];
+               }
+               if ( isset( $info['buttonname'] ) ) {
+                       $this->mButtonName = $info['buttonname'];
+               }
+               if ( isset( $info['buttondefault'] ) ) {
+                       $this->mButtonValue = $info['buttondefault'];
+               }
+               if ( isset( $info['buttontype'] ) ) {
+                       $this->mButtonType = $info['buttontype'];
+               }
+               if ( isset( $info['buttonflags'] ) ) {
+                       $this->mButtonFlags = $info['buttonflags'];
+               }
+               parent::__construct( $info );
+       }
+
+       public function getInputHTML( $value ) {
+               $attr = [
+                       'class' => 'mw-htmlform-submit ' . $this->mButtonClass,
+                       'id' => $this->mButtonId,
+               ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
+
+               return Html::input( $this->mButtonName, $this->mButtonValue, $this->mButtonType, $attr );
+       }
+
+       public function getInputOOUI( $value ) {
+               return new OOUI\ButtonInputWidget( [
+                       'name' => $this->mButtonName,
+                       'value' => $this->mButtonValue,
+                       'type' => $this->mButtonType,
+                       'label' => $this->mButtonValue,
+                       'flags' => $this->mButtonFlags,
+               ] + OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               ) );
+       }
+
+       /**
+        * Combines the passed element with a button.
+        * @param String $element Element to combine the button with.
+        * @return String
+        */
+       public function getElement( $element ) {
+               return $element . '&#160;' . $this->getInputHTML( '' );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLHiddenField.php b/includes/htmlform/fields/HTMLHiddenField.php
new file mode 100644 (file)
index 0000000..c0fce2b
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+
+class HTMLHiddenField extends HTMLFormField {
+       protected $outputAsDefault = true;
+
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               if ( isset( $this->mParams['output-as-default'] ) ) {
+                       $this->outputAsDefault = (bool)$this->mParams['output-as-default'];
+               }
+
+               # Per HTML5 spec, hidden fields cannot be 'required'
+               # http://www.w3.org/TR/html5/forms.html#hidden-state-%28type=hidden%29
+               unset( $this->mParams['required'] );
+       }
+
+       public function getHiddenFieldData( $value ) {
+               $params = [];
+               if ( $this->mID ) {
+                       $params['id'] = $this->mID;
+               }
+
+               if ( $this->outputAsDefault ) {
+                       $value = $this->mDefault;
+               }
+
+               return [ $this->mName, $value, $params ];
+       }
+
+       public function getTableRow( $value ) {
+               list( $name, $value, $params ) = $this->getHiddenFieldData( $value );
+               $this->mParent->addHiddenField( $name, $value, $params );
+               return '';
+       }
+
+       /**
+        * @param string $value
+        * @return string
+        * @since 1.20
+        */
+       public function getDiv( $value ) {
+               return $this->getTableRow( $value );
+       }
+
+       /**
+        * @param string $value
+        * @return string
+        * @since 1.20
+        */
+       public function getRaw( $value ) {
+               return $this->getTableRow( $value );
+       }
+
+       public function getInputHTML( $value ) {
+               return '';
+       }
+
+       public function canDisplayErrors() {
+               return false;
+       }
+
+       public function hasVisibleOutput() {
+               return false;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLInfoField.php b/includes/htmlform/fields/HTMLInfoField.php
new file mode 100644 (file)
index 0000000..ada4fb6
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * An information field (text blob), not a proper input.
+ */
+class HTMLInfoField extends HTMLFormField {
+       public function __construct( $info ) {
+               $info['nodata'] = true;
+
+               parent::__construct( $info );
+       }
+
+       public function getInputHTML( $value ) {
+               return !empty( $this->mParams['raw'] ) ? $value : htmlspecialchars( $value );
+       }
+
+       public function getInputOOUI( $value ) {
+               if ( !empty( $this->mParams['raw'] ) ) {
+                       $value = new OOUI\HtmlSnippet( $value );
+               }
+
+               return new OOUI\LabelWidget( [
+                       'label' => $value,
+               ] );
+       }
+
+       public function getTableRow( $value ) {
+               if ( !empty( $this->mParams['rawrow'] ) ) {
+                       return $value;
+               }
+
+               return parent::getTableRow( $value );
+       }
+
+       /**
+        * @param string $value
+        * @return string
+        * @since 1.20
+        */
+       public function getDiv( $value ) {
+               if ( !empty( $this->mParams['rawrow'] ) ) {
+                       return $value;
+               }
+
+               return parent::getDiv( $value );
+       }
+
+       /**
+        * @param string $value
+        * @return string
+        * @since 1.20
+        */
+       public function getRaw( $value ) {
+               if ( !empty( $this->mParams['rawrow'] ) ) {
+                       return $value;
+               }
+
+               return parent::getRaw( $value );
+       }
+
+       protected function needsLabel() {
+               return false;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLIntField.php b/includes/htmlform/fields/HTMLIntField.php
new file mode 100644 (file)
index 0000000..b0148d9
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * A field that must contain a number
+ */
+class HTMLIntField extends HTMLFloatField {
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               # http://www.w3.org/TR/html5/infrastructure.html#signed-integers
+               # with the addition that a leading '+' sign is ok. Note that leading zeros
+               # are fine, and will be left in the input, which is useful for things like
+               # phone numbers when you know that they are integers (the HTML5 type=tel
+               # input does not require its value to be numeric).  If you want a tidier
+               # value to, eg, save in the DB, clean it up with intval().
+               if ( !preg_match( '/^((\+|\-)?\d+)?$/', trim( $value ) ) ) {
+                       return $this->msg( 'htmlform-int-invalid' )->parseAsBlock();
+               }
+
+               return true;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLMultiSelectField.php b/includes/htmlform/fields/HTMLMultiSelectField.php
new file mode 100644 (file)
index 0000000..a231b2f
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * Multi-select field
+ */
+class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable {
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               if ( !is_array( $value ) ) {
+                       return false;
+               }
+
+               # If all options are valid, array_intersect of the valid options
+               # and the provided options will return the provided options.
+               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
+
+               $validValues = array_intersect( $value, $validOptions );
+               if ( count( $validValues ) == count( $value ) ) {
+                       return true;
+               } else {
+                       return $this->msg( 'htmlform-select-badoption' )->parse();
+               }
+       }
+
+       function getInputHTML( $value ) {
+               $value = HTMLFormField::forceToStringRecursive( $value );
+               $html = $this->formatOptions( $this->getOptions(), $value );
+
+               return $html;
+       }
+
+       function formatOptions( $options, $value ) {
+               $html = '';
+
+               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
+
+               foreach ( $options as $label => $info ) {
+                       if ( is_array( $info ) ) {
+                               $html .= Html::rawElement( 'h1', [], $label ) . "\n";
+                               $html .= $this->formatOptions( $info, $value );
+                       } else {
+                               $thisAttribs = [
+                                       'id' => "{$this->mID}-$info",
+                                       'value' => $info,
+                               ];
+                               $checked = in_array( $info, $value, true );
+
+                               $checkbox = $this->getOneCheckbox( $checked, $attribs + $thisAttribs, $label );
+
+                               $html .= ' ' . Html::rawElement(
+                                       'div',
+                                       [ 'class' => 'mw-htmlform-flatlist-item' ],
+                                       $checkbox
+                               );
+                       }
+               }
+
+               return $html;
+       }
+
+       protected function getOneCheckbox( $checked, $attribs, $label ) {
+               if ( $this->mParent instanceof OOUIHTMLForm ) {
+                       throw new MWException( 'HTMLMultiSelectField#getOneCheckbox() is not supported' );
+               } else {
+                       $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
+                       $checkbox =
+                               Xml::check( "{$this->mName}[]", $checked, $attribs ) .
+                               '&#160;' .
+                               call_user_func( $elementFunc,
+                                       'label',
+                                       [ 'for' => $attribs['id'] ],
+                                       $label
+                               );
+                       if ( $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                               $checkbox = Html::openElement( 'div', [ 'class' => 'mw-ui-checkbox' ] ) .
+                                       $checkbox .
+                                       Html::closeElement( 'div' );
+                       }
+                       return $checkbox;
+               }
+       }
+
+       /**
+        * Get the OOUI version of this field.
+        *
+        * @since 1.28
+        * @param string[] $value
+        * @return OOUI\CheckboxMultiselectInputWidget
+        */
+       public function getInputOOUI( $value ) {
+               $attr = $this->getTooltipAndAccessKey();
+               $attr['id'] = $this->mID;
+               $attr['name'] = "{$this->mName}[]";
+
+               $attr['value'] = $value;
+               $attr['options'] = $this->getOptionsOOUI();
+
+               if ( $this->mOptionsLabelsNotFromMessage ) {
+                       foreach ( $attr['options'] as &$option ) {
+                               $option['label'] = new OOUI\HtmlSnippet( $option['label'] );
+                       }
+               }
+
+               $attr += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               );
+
+               if ( $this->mClass !== '' ) {
+                       $attr['classes'] = [ $this->mClass ];
+               }
+
+               return new OOUI\CheckboxMultiselectInputWidget( $attr );
+       }
+
+       /**
+        * @param WebRequest $request
+        *
+        * @return string
+        */
+       function loadDataFromRequest( $request ) {
+               if ( $this->isSubmitAttempt( $request ) ) {
+                       // Checkboxes are just not added to the request arrays if they're not checked,
+                       // so it's perfectly possible for there not to be an entry at all
+                       return $request->getArray( $this->mName, [] );
+               } else {
+                       // That's ok, the user has not yet submitted the form, so show the defaults
+                       return $this->getDefault();
+               }
+       }
+
+       function getDefault() {
+               if ( isset( $this->mDefault ) ) {
+                       return $this->mDefault;
+               } else {
+                       return [];
+               }
+       }
+
+       function filterDataForSubmit( $data ) {
+               $data = HTMLFormField::forceToStringRecursive( $data );
+               $options = HTMLFormField::flattenOptions( $this->getOptions() );
+
+               $res = [];
+               foreach ( $options as $opt ) {
+                       $res["$opt"] = in_array( $opt, $data, true );
+               }
+
+               return $res;
+       }
+
+       protected function needsLabel() {
+               return false;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLRadioField.php b/includes/htmlform/fields/HTMLRadioField.php
new file mode 100644 (file)
index 0000000..e5b5e68
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * Radio checkbox fields.
+ */
+class HTMLRadioField extends HTMLFormField {
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               if ( !is_string( $value ) && !is_int( $value ) ) {
+                       return false;
+               }
+
+               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
+
+               if ( in_array( strval( $value ), $validOptions, true ) ) {
+                       return true;
+               } else {
+                       return $this->msg( 'htmlform-select-badoption' )->parse();
+               }
+       }
+
+       /**
+        * This returns a block of all the radio options, in one cell.
+        * @see includes/HTMLFormField#getInputHTML()
+        *
+        * @param string $value
+        *
+        * @return string
+        */
+       function getInputHTML( $value ) {
+               $html = $this->formatOptions( $this->getOptions(), strval( $value ) );
+
+               return $html;
+       }
+
+       function getInputOOUI( $value ) {
+               $options = [];
+               foreach ( $this->getOptions() as $label => $data ) {
+                       $options[] = [
+                               'data' => $data,
+                               'label' => $this->mOptionsLabelsNotFromMessage ? new OOUI\HtmlSnippet( $label ) : $label,
+                       ];
+               }
+
+               return new OOUI\RadioSelectInputWidget( [
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+                       'value' => $value,
+                       'options' => $options,
+               ] + OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               ) );
+       }
+
+       function formatOptions( $options, $value ) {
+               global $wgUseMediaWikiUIEverywhere;
+
+               $html = '';
+
+               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
+               $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
+
+               # @todo Should this produce an unordered list perhaps?
+               foreach ( $options as $label => $info ) {
+                       if ( is_array( $info ) ) {
+                               $html .= Html::rawElement( 'h1', [], $label ) . "\n";
+                               $html .= $this->formatOptions( $info, $value );
+                       } else {
+                               $id = Sanitizer::escapeId( $this->mID . "-$info" );
+                               $classes = [ 'mw-htmlform-flatlist-item' ];
+                               if ( $wgUseMediaWikiUIEverywhere || $this->mParent instanceof VFormHTMLForm ) {
+                                       $classes[] = 'mw-ui-radio';
+                               }
+                               $radio = Xml::radio( $this->mName, $info, $info === $value, $attribs + [ 'id' => $id ] );
+                               $radio .= '&#160;' . call_user_func( $elementFunc, 'label', [ 'for' => $id ], $label );
+
+                               $html .= ' ' . Html::rawElement(
+                                       'div',
+                                       [ 'class' => $classes ],
+                                       $radio
+                               );
+                       }
+               }
+
+               return $html;
+       }
+
+       protected function needsLabel() {
+               return false;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSelectAndOtherField.php b/includes/htmlform/fields/HTMLSelectAndOtherField.php
new file mode 100644 (file)
index 0000000..e75c2b2
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * Double field with a dropdown list constructed from a system message in the format
+ *     * Optgroup header
+ *     ** <option value>
+ *     * New Optgroup header
+ * Plus a text field underneath for an additional reason.  The 'value' of the field is
+ * "<select>: <extra reason>", or "<extra reason>" if nothing has been selected in the
+ * select dropdown.
+ * @todo FIXME: If made 'required', only the text field should be compulsory.
+ */
+class HTMLSelectAndOtherField extends HTMLSelectField {
+       function __construct( $params ) {
+               if ( array_key_exists( 'other', $params ) ) {
+                       // Do nothing
+               } elseif ( array_key_exists( 'other-message', $params ) ) {
+                       $params['other'] = $this->getMessage( $params['other-message'] )->plain();
+               } else {
+                       $params['other'] = $this->msg( 'htmlform-selectorother-other' )->plain();
+               }
+
+               parent::__construct( $params );
+
+               if ( $this->getOptions() === null ) {
+                       // Sulk
+                       throw new MWException( 'HTMLSelectAndOtherField called without any options' );
+               }
+               if ( !in_array( 'other', $this->mOptions, true ) ) {
+                       // Have 'other' always as first element
+                       $this->mOptions = [ $params['other'] => 'other' ] + $this->mOptions;
+               }
+               $this->mFlatOptions = self::flattenOptions( $this->getOptions() );
+
+       }
+
+       function getInputHTML( $value ) {
+               $select = parent::getInputHTML( $value[1] );
+
+               $textAttribs = [
+                       'id' => $this->mID . '-other',
+                       'size' => $this->getSize(),
+                       'class' => [ 'mw-htmlform-select-and-other-field' ],
+                       'data-id-select' => $this->mID,
+               ];
+
+               if ( $this->mClass !== '' ) {
+                       $textAttribs['class'][] = $this->mClass;
+               }
+
+               $allowedParams = [
+                       'required',
+                       'autofocus',
+                       'multiple',
+                       'disabled',
+                       'tabindex',
+                       'maxlength', // gets dynamic with javascript, see mediawiki.htmlform.js
+               ];
+
+               $textAttribs += $this->getAttributes( $allowedParams );
+
+               $textbox = Html::input( $this->mName . '-other', $value[2], 'text', $textAttribs );
+
+               return "$select<br />\n$textbox";
+       }
+
+       function getInputOOUI( $value ) {
+               return false;
+       }
+
+       /**
+        * @param WebRequest $request
+        *
+        * @return array("<overall message>","<select value>","<text field value>")
+        */
+       function loadDataFromRequest( $request ) {
+               if ( $request->getCheck( $this->mName ) ) {
+                       $list = $request->getText( $this->mName );
+                       $text = $request->getText( $this->mName . '-other' );
+
+                       // Should be built the same as in mediawiki.htmlform.js
+                       if ( $list == 'other' ) {
+                               $final = $text;
+                       } elseif ( !in_array( $list, $this->mFlatOptions, true ) ) {
+                               # User has spoofed the select form to give an option which wasn't
+                               # in the original offer.  Sulk...
+                               $final = $text;
+                       } elseif ( $text == '' ) {
+                               $final = $list;
+                       } else {
+                               $final = $list . $this->msg( 'colon-separator' )->inContentLanguage()->text() . $text;
+                       }
+               } else {
+                       $final = $this->getDefault();
+
+                       $list = 'other';
+                       $text = $final;
+                       foreach ( $this->mFlatOptions as $option ) {
+                               $match = $option . $this->msg( 'colon-separator' )->inContentLanguage()->text();
+                               if ( strpos( $text, $match ) === 0 ) {
+                                       $list = $option;
+                                       $text = substr( $text, strlen( $match ) );
+                                       break;
+                               }
+                       }
+               }
+
+               return [ $final, $list, $text ];
+       }
+
+       function getSize() {
+               return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45;
+       }
+
+       function validate( $value, $alldata ) {
+               # HTMLSelectField forces $value to be one of the options in the select
+               # field, which is not useful here.  But we do want the validation further up
+               # the chain
+               $p = parent::validate( $value[1], $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               if ( isset( $this->mParams['required'] )
+                       && $this->mParams['required'] !== false
+                       && $value[1] === ''
+               ) {
+                       return $this->msg( 'htmlform-required' )->parse();
+               }
+
+               return true;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSelectField.php b/includes/htmlform/fields/HTMLSelectField.php
new file mode 100644 (file)
index 0000000..b6ad46c
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * A select dropdown field.  Basically a wrapper for Xmlselect class
+ */
+class HTMLSelectField extends HTMLFormField {
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
+
+               if ( in_array( strval( $value ), $validOptions, true ) ) {
+                       return true;
+               } else {
+                       return $this->msg( 'htmlform-select-badoption' )->parse();
+               }
+       }
+
+       function getInputHTML( $value ) {
+               $select = new XmlSelect( $this->mName, $this->mID, strval( $value ) );
+
+               if ( !empty( $this->mParams['disabled'] ) ) {
+                       $select->setAttribute( 'disabled', 'disabled' );
+               }
+
+               $allowedParams = [ 'tabindex', 'size' ];
+               $customParams = $this->getAttributes( $allowedParams );
+               foreach ( $customParams as $name => $value ) {
+                       $select->setAttribute( $name, $value );
+               }
+
+               if ( $this->mClass !== '' ) {
+                       $select->setAttribute( 'class', $this->mClass );
+               }
+
+               $select->addOptions( $this->getOptions() );
+
+               return $select->getHTML();
+       }
+
+       function getInputOOUI( $value ) {
+               $disabled = false;
+               $allowedParams = [ 'tabindex' ];
+               $attribs = OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['classes'] = [ $this->mClass ];
+               }
+
+               if ( !empty( $this->mParams['disabled'] ) ) {
+                       $disabled = true;
+               }
+
+               return new OOUI\DropdownInputWidget( [
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+                       'options' => $this->getOptionsOOUI(),
+                       'value' => strval( $value ),
+                       'disabled' => $disabled,
+               ] + $attribs );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSelectLimitField.php b/includes/htmlform/fields/HTMLSelectLimitField.php
new file mode 100644 (file)
index 0000000..e7f1c04
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * A limit dropdown, which accepts any valid number
+ */
+class HTMLSelectLimitField extends HTMLSelectField {
+       /**
+        * Basically don't do any validation. If it's a number that's fine. Also,
+        * add it to the list if it's not there already
+        *
+        * @param string $value
+        * @param array $alldata
+        * @return bool
+        */
+       function validate( $value, $alldata ) {
+               if ( $value == '' ) {
+                       return true;
+               }
+
+               // Let folks pick an explicit limit not from our list, as long as it's a real numbr.
+               if ( !in_array( $value, $this->mParams['options'] )
+                       && $value == intval( $value )
+                       && $value > 0
+               ) {
+                       // This adds the explicitly requested limit value to the drop-down,
+                       // then makes sure it's sorted correctly so when we output the list
+                       // later, the custom option doesn't just show up last.
+                       $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] =
+                               intval( $value );
+                       asort( $this->mParams['options'] );
+               }
+
+               return true;
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSelectNamespace.php b/includes/htmlform/fields/HTMLSelectNamespace.php
new file mode 100644 (file)
index 0000000..ef21969
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Wrapper for Html::namespaceSelector to use in HTMLForm
+ */
+class HTMLSelectNamespace extends HTMLFormField {
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               $this->mAllValue = array_key_exists( 'all', $params )
+                       ? $params['all']
+                       : 'all';
+
+       }
+
+       function getInputHTML( $value ) {
+               return Html::namespaceSelector(
+                       [
+                               'selected' => $value,
+                               'all' => $this->mAllValue
+                       ], [
+                               'name' => $this->mName,
+                               'id' => $this->mID,
+                               'class' => 'namespaceselector',
+                       ]
+               );
+       }
+
+       public function getInputOOUI( $value ) {
+               return new MediaWiki\Widget\NamespaceInputWidget( [
+                       'value' => $value,
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+                       'includeAllValue' => $this->mAllValue,
+               ] );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSelectNamespaceWithButton.php b/includes/htmlform/fields/HTMLSelectNamespaceWithButton.php
new file mode 100644 (file)
index 0000000..5225983
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Creates a Html::namespaceSelector input field with a button assigned to the input field.
+ */
+class HTMLSelectNamespaceWithButton extends HTMLSelectNamespace {
+       /** @var HTMLFormFieldWithButton $mClassWithButton */
+       protected $mClassWithButton = null;
+
+       public function __construct( $info ) {
+               $this->mClassWithButton = new HTMLFormFieldWithButton( $info );
+               parent::__construct( $info );
+       }
+
+       public function getInputHTML( $value ) {
+               return $this->mClassWithButton->getElement( parent::getInputHTML( $value ) );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSelectOrOtherField.php b/includes/htmlform/fields/HTMLSelectOrOtherField.php
new file mode 100644 (file)
index 0000000..8f7750c
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Select dropdown field, with an additional "other" textbox.
+ *
+ * HTMLComboboxField implements the same functionality using a single form field
+ * and should be used instead.
+ */
+class HTMLSelectOrOtherField extends HTMLTextField {
+       function __construct( $params ) {
+               parent::__construct( $params );
+               $this->getOptions();
+               if ( !in_array( 'other', $this->mOptions, true ) ) {
+                       $msg =
+                               isset( $params['other'] )
+                                       ? $params['other']
+                                       : wfMessage( 'htmlform-selectorother-other' )->text();
+                       // Have 'other' always as first element
+                       $this->mOptions = [ $msg => 'other' ] + $this->mOptions;
+               }
+
+       }
+
+       function getInputHTML( $value ) {
+               $valInSelect = false;
+
+               if ( $value !== false ) {
+                       $value = strval( $value );
+                       $valInSelect = in_array(
+                               $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
+                       );
+               }
+
+               $selected = $valInSelect ? $value : 'other';
+
+               $select = new XmlSelect( $this->mName, $this->mID, $selected );
+               $select->addOptions( $this->getOptions() );
+
+               $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
+
+               $tbAttribs = [ 'id' => $this->mID . '-other', 'size' => $this->getSize() ];
+
+               if ( !empty( $this->mParams['disabled'] ) ) {
+                       $select->setAttribute( 'disabled', 'disabled' );
+                       $tbAttribs['disabled'] = 'disabled';
+               }
+
+               if ( isset( $this->mParams['tabindex'] ) ) {
+                       $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
+                       $tbAttribs['tabindex'] = $this->mParams['tabindex'];
+               }
+
+               $select = $select->getHTML();
+
+               if ( isset( $this->mParams['maxlength'] ) ) {
+                       $tbAttribs['maxlength'] = $this->mParams['maxlength'];
+               }
+
+               if ( $this->mClass !== '' ) {
+                       $tbAttribs['class'] = $this->mClass;
+               }
+
+               $textbox = Html::input( $this->mName . '-other', $valInSelect ? '' : $value, 'text', $tbAttribs );
+
+               return "$select<br />\n$textbox";
+       }
+
+       function getInputOOUI( $value ) {
+               return false;
+       }
+
+       /**
+        * @param WebRequest $request
+        *
+        * @return string
+        */
+       function loadDataFromRequest( $request ) {
+               if ( $request->getCheck( $this->mName ) ) {
+                       $val = $request->getText( $this->mName );
+
+                       if ( $val === 'other' ) {
+                               $val = $request->getText( $this->mName . '-other' );
+                       }
+
+                       return $val;
+               } else {
+                       return $this->getDefault();
+               }
+       }
+}
diff --git a/includes/htmlform/fields/HTMLSubmitField.php b/includes/htmlform/fields/HTMLSubmitField.php
new file mode 100644 (file)
index 0000000..cb98549
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * Add a submit button inline in the form (as opposed to
+ * HTMLForm::addButton(), which will add it at the end).
+ */
+class HTMLSubmitField extends HTMLButtonField {
+       protected $buttonType = 'submit';
+
+       protected $mFlags = [ 'primary', 'constructive' ];
+
+       public function skipLoadData( $request ) {
+               return !$request->getCheck( $this->mName );
+       }
+
+       public function loadDataFromRequest( $request ) {
+               return $request->getCheck( $this->mName );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLTagFilter.php b/includes/htmlform/fields/HTMLTagFilter.php
new file mode 100644 (file)
index 0000000..8075de5
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Wrapper for ChangeTags::buildTagFilterSelector to use in HTMLForm
+ */
+class HTMLTagFilter extends HTMLFormField {
+       protected $tagFilter;
+
+       function getTableRow( $value ) {
+               $this->tagFilter = ChangeTags::buildTagFilterSelector( $value );
+               if ( $this->tagFilter ) {
+                       return parent::getTableRow( $value );
+               }
+               return '';
+       }
+
+       function getDiv( $value ) {
+               $this->tagFilter = ChangeTags::buildTagFilterSelector( $value );
+               if ( $this->tagFilter ) {
+                       return parent::getDiv( $value );
+               }
+               return '';
+       }
+
+       function getInputHTML( $value ) {
+               if ( $this->tagFilter ) {
+                       // we only need the select field, HTMLForm should handle the label
+                       return $this->tagFilter[1];
+               }
+               return '';
+       }
+}
diff --git a/includes/htmlform/fields/HTMLTextAreaField.php b/includes/htmlform/fields/HTMLTextAreaField.php
new file mode 100644 (file)
index 0000000..8ffff43
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+
+class HTMLTextAreaField extends HTMLFormField {
+       const DEFAULT_COLS = 80;
+       const DEFAULT_ROWS = 25;
+
+       protected $mPlaceholder = '';
+
+       /**
+        * @param array $params
+        *   - cols, rows: textarea size
+        *   - placeholder/placeholder-message: set HTML placeholder attribute
+        *   - spellcheck: set HTML spellcheck attribute
+        */
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               if ( isset( $params['placeholder-message'] ) ) {
+                       $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->parse();
+               } elseif ( isset( $params['placeholder'] ) ) {
+                       $this->mPlaceholder = $params['placeholder'];
+               }
+       }
+
+       function getCols() {
+               return isset( $this->mParams['cols'] ) ? $this->mParams['cols'] : static::DEFAULT_COLS;
+       }
+
+       function getRows() {
+               return isset( $this->mParams['rows'] ) ? $this->mParams['rows'] : static::DEFAULT_ROWS;
+       }
+
+       function getSpellCheck() {
+               $val = isset( $this->mParams['spellcheck'] ) ? $this->mParams['spellcheck'] : null;
+               if ( is_bool( $val ) ) {
+                       // "spellcheck" attribute literally requires "true" or "false" to work.
+                       return $val === true ? 'true' : 'false';
+               }
+               return null;
+       }
+
+       function getInputHTML( $value ) {
+               $attribs = [
+                               'id' => $this->mID,
+                               'cols' => $this->getCols(),
+                               'rows' => $this->getRows(),
+                               'spellcheck' => $this->getSpellCheck(),
+                       ] + $this->getTooltipAndAccessKey();
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['class'] = $this->mClass;
+               }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
+
+               $allowedParams = [
+                       'tabindex',
+                       'disabled',
+                       'readonly',
+                       'required',
+                       'autofocus'
+               ];
+
+               $attribs += $this->getAttributes( $allowedParams );
+               return Html::textarea( $this->mName, $value, $attribs );
+       }
+
+       function getInputOOUI( $value ) {
+               if ( isset( $this->mParams['cols'] ) ) {
+                       throw new Exception( "OOUIHTMLForm does not support the 'cols' parameter for textareas" );
+               }
+
+               $attribs = $this->getTooltipAndAccessKey();
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['classes'] = [ $this->mClass ];
+               }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
+
+               $allowedParams = [
+                       'tabindex',
+                       'disabled',
+                       'readonly',
+                       'required',
+                       'autofocus',
+               ];
+
+               $attribs += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
+
+               return new OOUI\TextInputWidget( [
+                       'id' => $this->mID,
+                       'name' => $this->mName,
+                       'multiline' => true,
+                       'value' => $value,
+                       'rows' => $this->getRows(),
+               ] + $attribs );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLTextField.php b/includes/htmlform/fields/HTMLTextField.php
new file mode 100644 (file)
index 0000000..3ab7176
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+
+class HTMLTextField extends HTMLFormField {
+       protected $mPlaceholder = '';
+
+       /**
+        * @param array $params
+        *   - type: HTML textfield type
+        *   - size: field size in characters (defaults to 45)
+        *   - placeholder/placeholder-message: set HTML placeholder attribute
+        *   - spellcheck: set HTML spellcheck attribute
+        *   - persistent: upon unsuccessful requests, retain the value (defaults to true, except
+        *     for password fields)
+        */
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               if ( isset( $params['placeholder-message'] ) ) {
+                       $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->parse();
+               } elseif ( isset( $params['placeholder'] ) ) {
+                       $this->mPlaceholder = $params['placeholder'];
+               }
+       }
+
+       function getSize() {
+               return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45;
+       }
+
+       function getSpellCheck() {
+               $val = isset( $this->mParams['spellcheck'] ) ? $this->mParams['spellcheck'] : null;
+               if ( is_bool( $val ) ) {
+                       // "spellcheck" attribute literally requires "true" or "false" to work.
+                       return $val === true ? 'true' : 'false';
+               }
+               return null;
+       }
+
+       public function isPersistent() {
+               if ( isset( $this->mParams['persistent'] ) ) {
+                       return $this->mParams['persistent'];
+               }
+               // don't put passwords into the HTML body, they could get cached or otherwise leaked
+               return !( isset( $this->mParams['type'] ) && $this->mParams['type'] === 'password' );
+       }
+
+       function getInputHTML( $value ) {
+               if ( !$this->isPersistent() ) {
+                       $value = '';
+               }
+
+               $attribs = [
+                               'id' => $this->mID,
+                               'name' => $this->mName,
+                               'size' => $this->getSize(),
+                               'value' => $value,
+                               'dir' => $this->mDir,
+                               'spellcheck' => $this->getSpellCheck(),
+                       ] + $this->getTooltipAndAccessKey() + $this->getDataAttribs();
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['class'] = $this->mClass;
+               }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
+
+               # @todo Enforce pattern, step, required, readonly on the server side as
+               # well
+               $allowedParams = [
+                       'type',
+                       'min',
+                       'max',
+                       'pattern',
+                       'title',
+                       'step',
+                       'list',
+                       'maxlength',
+                       'tabindex',
+                       'disabled',
+                       'required',
+                       'autofocus',
+                       'multiple',
+                       'readonly'
+               ];
+
+               $attribs += $this->getAttributes( $allowedParams );
+
+               # Extract 'type'
+               $type = $this->getType( $attribs );
+               return Html::input( $this->mName, $value, $type, $attribs );
+       }
+
+       protected function getType( &$attribs ) {
+               $type = isset( $attribs['type'] ) ? $attribs['type'] : 'text';
+               unset( $attribs['type'] );
+
+               # Implement tiny differences between some field variants
+               # here, rather than creating a new class for each one which
+               # is essentially just a clone of this one.
+               if ( isset( $this->mParams['type'] ) ) {
+                       switch ( $this->mParams['type'] ) {
+                               case 'int':
+                                       $type = 'number';
+                                       break;
+                               case 'float':
+                                       $type = 'number';
+                                       $attribs['step'] = 'any';
+                                       break;
+                               # Pass through
+                               case 'email':
+                               case 'password':
+                               case 'file':
+                               case 'url':
+                                       $type = $this->mParams['type'];
+                                       break;
+                       }
+               }
+
+               return $type;
+       }
+
+       function getInputOOUI( $value ) {
+               if ( !$this->isPersistent() ) {
+                       $value = '';
+               }
+
+               $attribs = $this->getTooltipAndAccessKey();
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['classes'] = [ $this->mClass ];
+               }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
+
+               # @todo Enforce pattern, step, required, readonly on the server side as
+               # well
+               $allowedParams = [
+                       'autofocus',
+                       'autosize',
+                       'disabled',
+                       'flags',
+                       'indicator',
+                       'maxlength',
+                       'readonly',
+                       'required',
+                       'tabindex',
+                       'type',
+               ];
+
+               $attribs += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
+
+               $type = $this->getType( $attribs );
+
+               return $this->getInputWidget( [
+                       'id' => $this->mID,
+                       'name' => $this->mName,
+                       'value' => $value,
+                       'type' => $type,
+               ] + $attribs );
+       }
+
+       protected function getInputWidget( $params ) {
+               return new OOUI\TextInputWidget( $params );
+       }
+
+       /**
+        * Returns an array of data-* attributes to add to the field.
+        *
+        * @return array
+        */
+       protected function getDataAttribs() {
+               return [];
+       }
+}
diff --git a/includes/htmlform/fields/HTMLTextFieldWithButton.php b/includes/htmlform/fields/HTMLTextFieldWithButton.php
new file mode 100644 (file)
index 0000000..7c1c673
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Creates a text input field with a button assigned to the input field.
+ */
+class HTMLTextFieldWithButton extends HTMLTextField {
+       /** @var HTMLFormFieldWithButton $mClassWithButton */
+       protected $mClassWithButton = null;
+
+       public function __construct( $info ) {
+               $this->mClassWithButton = new HTMLFormFieldWithButton( $info );
+               parent::__construct( $info );
+       }
+
+       public function getInputHTML( $value ) {
+               return $this->mClassWithButton->getElement( parent::getInputHTML( $value ) );
+       }
+}
diff --git a/includes/htmlform/fields/HTMLTitleTextField.php b/includes/htmlform/fields/HTMLTitleTextField.php
new file mode 100644 (file)
index 0000000..fcf721a
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+
+use MediaWiki\Widget\TitleInputWidget;
+
+/**
+ * Implements a text input field for page titles.
+ * Automatically does validation that the title is valid,
+ * as well as autocompletion if using the OOUI display format.
+ *
+ * Note: Forms using GET requests will need to make sure the title value is not
+ * an empty string.
+ *
+ * Optional parameters:
+ * 'namespace' - Namespace the page must be in
+ * 'relative' - If true and 'namespace' given, strip/add the namespace from/to the title as needed
+ * 'creatable' - Whether to validate the title is creatable (not a special page)
+ * 'exists' - Whether to validate that the title already exists
+ *
+ * @since 1.26
+ */
+class HTMLTitleTextField extends HTMLTextField {
+       public function __construct( $params ) {
+               $params += [
+                       'namespace' => false,
+                       'relative' => false,
+                       'creatable' => false,
+                       'exists' => false,
+               ];
+
+               parent::__construct( $params );
+       }
+
+       public function validate( $value, $alldata ) {
+               if ( $this->mParent->getMethod() === 'get' && $value === '' ) {
+                       // If the form is a GET form and has no value, assume it hasn't been
+                       // submitted yet, and skip validation
+                       return parent::validate( $value, $alldata );
+               }
+               try {
+                       if ( !$this->mParams['relative'] ) {
+                               $title = Title::newFromTextThrow( $value );
+                       } else {
+                               // Can't use Title::makeTitleSafe(), because it doesn't throw useful exceptions
+                               global $wgContLang;
+                               $namespaceName = $wgContLang->getNsText( $this->mParams['namespace'] );
+                               $title = Title::newFromTextThrow( $namespaceName . ':' . $value );
+                       }
+               } catch ( MalformedTitleException $e ) {
+                       $msg = $this->msg( $e->getErrorMessage() );
+                       $params = $e->getErrorMessageParameters();
+                       if ( $params ) {
+                               $msg->params( $params );
+                       }
+                       return $msg->parse();
+               }
+
+               $text = $title->getPrefixedText();
+               if ( $this->mParams['namespace'] !== false &&
+                       !$title->inNamespace( $this->mParams['namespace'] )
+               ) {
+                       return $this->msg( 'htmlform-title-badnamespace', $this->mParams['namespace'], $text )->parse();
+               }
+
+               if ( $this->mParams['creatable'] && !$title->canExist() ) {
+                       return $this->msg( 'htmlform-title-not-creatable', $text )->escaped();
+               }
+
+               if ( $this->mParams['exists'] && !$title->exists() ) {
+                       return $this->msg( 'htmlform-title-not-exists', $text )->parse();
+               }
+
+               return parent::validate( $value, $alldata );
+       }
+
+       protected function getInputWidget( $params ) {
+               $this->mParent->getOutput()->addModules( 'mediawiki.widgets' );
+               if ( $this->mParams['namespace'] !== false ) {
+                       $params['namespace'] = $this->mParams['namespace'];
+               }
+               $params['relative'] = $this->mParams['relative'];
+               return new TitleInputWidget( $params );
+       }
+
+       public function getInputHtml( $value ) {
+               // add mw-searchInput class to enable search suggestions for non-OOUI, too
+               $this->mClass .= 'mw-searchInput';
+
+               // return the HTMLTextField html
+               return parent::getInputHTML( $value );
+       }
+
+       protected function getDataAttribs() {
+               return [
+                       'data-mw-searchsuggest' => FormatJson::encode( [
+                               'wrapAsLink' => false,
+                       ] ),
+               ];
+       }
+}
diff --git a/includes/htmlform/fields/HTMLUserTextField.php b/includes/htmlform/fields/HTMLUserTextField.php
new file mode 100644 (file)
index 0000000..5a7e0b9
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+use MediaWiki\Widget\UserInputWidget;
+
+/**
+ * Implements a text input field for user names.
+ * Automatically auto-completes if using the OOUI display format.
+ *
+ * FIXME: Does not work for forms that support GET requests.
+ *
+ * Optional parameters:
+ * 'exists' - Whether to validate that the user already exists
+ *
+ * @since 1.26
+ */
+class HTMLUserTextField extends HTMLTextField {
+       public function __construct( $params ) {
+               $params += [
+                       'exists' => false,
+                       'ipallowed' => false,
+               ];
+
+               parent::__construct( $params );
+       }
+
+       public function validate( $value, $alldata ) {
+               // check, if a user exists with the given username
+               $user = User::newFromName( $value, false );
+
+               if ( !$user ) {
+                       return $this->msg( 'htmlform-user-not-valid', $value )->parse();
+               } elseif (
+                       ( $this->mParams['exists'] && $user->getId() === 0 ) &&
+                       !( $this->mParams['ipallowed'] && User::isIP( $value ) )
+               ) {
+                       return $this->msg( 'htmlform-user-not-exists', $user->getName() )->parse();
+               }
+
+               return parent::validate( $value, $alldata );
+       }
+
+       protected function getInputWidget( $params ) {
+               $this->mParent->getOutput()->addModules( 'mediawiki.widgets.UserInputWidget' );
+
+               return new UserInputWidget( $params );
+       }
+
+       public function getInputHtml( $value ) {
+               // add the required module and css class for user suggestions in non-OOUI mode
+               $this->mParent->getOutput()->addModules( 'mediawiki.userSuggest' );
+               $this->mClass .= ' mw-autocomplete-user';
+
+               // return parent html
+               return parent::getInputHTML( $value );
+       }
+}
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 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 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 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 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 59b250b..20a026c 100644 (file)
        "passwordreset-text-one": "Запоўніце гэтую форму, каб атрымаць часовы пароль электроннай поштай.",
        "passwordreset-text-many": "{{PLURAL:$1|Запоўніце адно з палёў, каб атрымаць часовы пароль праз электронную пошту.}}",
        "passwordreset-disabled": "Магчымасьць ачысткі паролю была адключаная ў гэтай вікі.",
-       "passwordreset-emaildisabled": "Функцыі e-mail у гэтай вікі былі адключаныя.",
+       "passwordreset-emaildisabled": "Функцыі электроннай пошты ў гэтай вікі былі адключаныя.",
        "passwordreset-username": "Імя ўдзельніка:",
        "passwordreset-domain": "Дамэн:",
        "passwordreset-capture": "Паказаць канчатковы электронны ліст?",
        "action-applychangetags": "дадаваньне метак пры рэдагаваньні",
        "action-changetags": "дадаваньне і выдаленьне адвольных метак да асобных вэрсіяў і запісаў у журнале падзеяў",
        "action-deletechangetags": "выдаленьне метак з базы зьвестак",
+       "action-purge": "ачыстку кэшу гэтай старонкі",
        "nchanges": "$1 {{PLURAL:$1|зьмена|зьмены|зьменаў}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|з апошняга візыту}}",
        "enhancedrc-history": "гісторыя",
        "mw-widgets-titleinput-description-new-page": "старонка яшчэ не існуе",
        "mw-widgets-titleinput-description-redirect": "перанакіраваньне на $1",
        "randomrootpage": "Выпадковая карэнная старонка",
+       "log-action-filter-block": "Тып блякаваньня:",
+       "log-action-filter-delete": "Тып выдаленьня:",
+       "log-action-filter-import": "Тып імпарту:",
        "changecredentials": "Зьмена ўліковых зьвестак",
        "removecredentials": "Выдаленьне ўліковых зьвестак",
        "removecredentials-submit": "Выдаліць уліковыя зьвесткі",
index ec4475c..aa16b7a 100644 (file)
@@ -32,7 +32,8 @@
                        "LordMsz",
                        "Matma Rex",
                        "Dvorapa",
-                       "Walter Klosse"
+                       "Walter Klosse",
+                       "Martin Urbanec"
                ]
        },
        "tog-underline": "Podtrhávat odkazy:",
        "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",
        "listgrouprights-namespaceprotection-namespace": "Jmenný prostor",
        "listgrouprights-namespaceprotection-restrictedto": "Oprávnění umožňující uživateli editovat",
        "listgrants": "Skupiny oprávnění",
-       "listgrants-summary": "Následující seznam obsahuje svolení a jim odpovídající přístup k uživatelským právům. Uživatelé mohou aplikace autorizovat k využití jejich účtu, ale s omezenými právy na základě svolení, která uživatel aplikaci poskytl. Aplikace konající jménem uživatele ale nemůže využít oprávnění, která uživatel nemá.\nK jednotlivým oprávněním mohou existovat [[{{MediaWiki:Listgrouprights-helppage}}|doplňující informace]].",
+       "listgrants-summary": "Následující seznam obsahuje skupiny oprávnění a jim odpovídající přístup k uživatelským právům. Uživatelé mohou aplikace autorizovat k využití jejich účtu, ale s omezenými právy na základě skupin oprávnění, která uživatel aplikaci dovolil použít. Aplikace konající jménem uživatele ale nemůže využít oprávnění, která uživatel nemá.\nK jednotlivým oprávněním mohou existovat [[{{MediaWiki:Listgrouprights-helppage}}|doplňující informace]].",
        "listgrants-grant": "Skupina oprávnění",
        "listgrants-rights": "Oprávnění",
        "trackingcategories": "Sledovací kategorie",
index cecccf6..20cce4c 100644 (file)
        "action-applychangetags": "Markierungen zusammen mit deinen Änderungen anzuwenden",
        "action-changetags": "beliebige Markierungen zu einzelnen Versionen und Logbucheinträgen hinzuzufügen und zu entfernen",
        "action-deletechangetags": "Markierungen aus der Datenbank zu löschen",
+       "action-purge": "den Cache dieser Seite zu leeren",
        "nchanges": "$1 {{PLURAL:$1|Änderung|Änderungen}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|seit dem letzten Besuch}}",
        "enhancedrc-history": "Versionsgeschichte",
index 5a789d4..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",
        "about": "Heqa cı de",
        "article": "Pela zerreki",
        "newwindow": "(pençereyê newey de beno a)",
-       "cancel": "Peyd ke",
+       "cancel": "Bıterkın",
        "moredotdotdot": "Vêşi...",
        "morenotlisted": "Vêşi lista nêbi...",
        "mypage": "Pele",
        "mytalk": "Mesac",
-       "anontalk": "Mışewre",
+       "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",
-       "permalink": "Gıreyo jûqere",
+       "printableversion": "Asayışê çapkerdışi",
+       "permalink": "Gıreyo daimi",
        "print": "Çap ke",
        "view": "Bıvêne",
        "view-foreign": "$1'i bıvin",
        "unprotectthispage": "Starkerdışe ena peler bıvurne",
        "newpage": "Pela newiye",
        "talkpage": "Ena pele sero werêne",
-       "talkpagelinktext": "vacenayış",
+       "talkpagelinktext": "werênayış",
        "specialpage": "Pela xısusiye",
        "personaltools": "Hacetê şexsiy",
        "articlepage": "Pela zerreki 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.",
        "botpasswords-label-appid": "Nameyê boti:",
        "botpasswords-label-create": "Vıraze",
        "botpasswords-label-update": "Rocane ke",
-       "botpasswords-label-cancel": "Bıtexelne",
+       "botpasswords-label-cancel": "Bıterkın",
        "botpasswords-label-delete": "Bestere",
        "botpasswords-label-resetpassword": "Parola raçarne",
        "botpasswords-label-grants-column": "Dayen",
        "resetpass_forbidden": "parolayi nêvuryayi",
        "resetpass-no-info": "şıma gani hesab akere u hona bıeşke bırese cı",
        "resetpass-submit-loggedin": "Parola bıvurne",
-       "resetpass-submit-cancel": "Bıtexelne",
+       "resetpass-submit-cancel": "Bıterkın",
        "resetpass-wrong-oldpass": "parolayo parola maqbul niyo.\nşıma ya parolaye xo vurnayo ya zi parolayo muwaqqat waşto.",
        "resetpass-recycled": "Parolaya şımaya newiye wa paroloya şımaya verêne ra ferqıne bo.",
        "resetpass-temp-emailed": "E postaya rışyayê yubkoda şıma ronıştış akerdo.  Ronıştışi xo temammkerdışi rê yu parolaya newi lazım a",
        "publishpage": "Perer bıhesırne",
        "publishchanges": "Vurnayışa vıla ke",
        "preview": "Verqayt",
-       "showpreview": "Verqayti bıasne",
-       "showdiff": "Vurriyayışan bıasne",
+       "showpreview": "Verqayti bımocne",
+       "showdiff": "Vurriyayışan bımocne",
        "anoneditwarning": "<strong>İqaz:</strong> Şıma be hesabê xo nêkewtê cı. \nAdresê şımayê IP tarixê vırnayışê na pele de do qeyd bo. Eke şıma <strong>[$1 cıkewê]</strong> ya zi <strong>[$2 hesab vırazê]</strong>, vurnayışê şıma be zewbina kare ra nameyê şıma rê bar beno.",
        "anonpreviewwarning": "\"Şıma be hesabê xo nêkewtê cı. Eke qeyd kerê, adresê şımaê IP tarixê vırnayışê na pele de do qeyd bo.\"",
        "missingsummary": "'''DİQET:''' Şıma jû xulasa nênuşte.\nEke şıma \"{{int:savearticle}}\" reyna bıtıknê, vırnayışê şıma bê xulasa qeyd beno.",
        "showingresults": "#<strong>$2</strong> netican ra {{PLURAL:$1|<strong>1</strong> netice cêr dero|<strong>$1</strong> neticey cêr derê}}.",
        "showingresultsinrange": "{{PLURAL:$1|<strong>1</strong> netice|<strong>$1</strong> neticey}} be mabeynê #<strong>$2</strong> ra be #<strong>$3</strong> cêr asenê.",
        "search-showingresults": "{{PLURAL:$4|Netice <strong>$1</strong> be <strong>$3</strong>|Neticeyi <strong>$1 - $2</strong> be <strong>$3</strong>}}",
-       "search-nonefound": "Zey perskerdışê şıma netice nêvêniya.",
+       "search-nonefound": "Zey perskerdışê şıma peyniye çıniya.",
        "search-nonefound-thiswiki": "Ena sita dı zey waşten da şıma theba nêvineya",
        "powersearch-legend": "Cıgeyrayışo hera",
        "powersearch-ns": "Cayanê nameyan de cıgeyrayış:",
        "upload-http-error": "Yew ğeletê HTTPî biyo: $1",
        "upload-copy-upload-invalid-domain": "Na domain ra kopyayê barkerdışanê nêbenê.",
        "upload-dialog-title": "Dosya bar ke",
-       "upload-dialog-button-cancel": "Bıtexelne",
+       "upload-dialog-button-cancel": "Bıterkın",
        "upload-dialog-button-done": "Temam",
        "upload-dialog-button-save": "Bışevekne",
        "upload-dialog-button-upload": "Bar ke",
        "uploadstash-badtoken": "Karkerdışê cı nêbı, muhtemelen desture şımayê timarkerdışi zeman do şıma ravêrdo. Fına bıcerbnê.",
        "uploadstash-errclear": "Besternayışê dosyayan nêbı",
        "uploadstash-refresh": "Listanê dosyayan aneweke",
-       "uploadstash-thumbnail": "Asayışê qıteki bıvêne",
+       "uploadstash-thumbnail": "asayışê qıckeki bıvêne",
        "invalid-chunk-offset": "Ofseto nêravyarde",
        "img-auth-accessdenied": "Cıresnayış vındarnayo.",
        "img-auth-nopathinfo": "PATH_INFO kemiyo.\nTeqdimkerê şıma seba ravurnayışê nê melumati eyar nêkerdo.\nBeno ke be CGI-bıngeyın bo u img_auth rê desteg nêbeno.\nhttps://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization Selahiyetê resımi bıvêne.",
        "newpages-submit": "Bıasene",
        "newpages-username": "Nameyê karberi:",
        "ancientpages": "Pelê kehenêri",
-       "move": "Wegi",
-       "movethispage": "Ena peler wegi",
+       "move": "Bıkırış",
+       "movethispage": "Ena pele bıkırışe",
        "unusedimagestext": "Enê dosyey estê, feqet zerrey yew pele de wedardey niyê.\nXo vira mekerê ke, sıteyê webiê bini şenê direkt ebe URLi yew dosya ra gırê bê, u wına şenê verba gurênayışo feal de tiya hewna lista bê.",
        "unusedcategoriestext": "Kategoriyê ke cêr derê, nê bıbê zi, terefê qet madeyan ya zi kategoriyan ra nêgureniyenê.",
        "notargettitle": "Hedef çini yo",
        "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:",
        "maximum-size": "Ebatê maximumî",
        "pagesize": "(bitî)",
        "restriction-edit": "Bıvurne",
-       "restriction-move": "Berr",
+       "restriction-move": "Bıkırış",
        "restriction-create": "Bıvıraz",
        "restriction-upload": "Bar ke",
        "restriction-level-sysop": "tam pawiyayo",
        "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": "mışewre",
+       "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",
        "lockfilenotwritable": "dosyaya qefılnayişê databaseyi ser ra çiyek nênusyena.",
        "databasenotlocked": "Database a nibiya.",
        "lockedbyandtime": "({{GENDER:$1|$1}} ra $2 tepya $3 biyo)",
-       "move-page": "$1 Bere",
+       "move-page": "$1 Bıkırış",
        "move-page-legend": "Pele bere",
        "movepagetext": "Pe form ki ho bın de, tı eşkeno name yew pele bıvurni u tarixê pele hemi ya zi pyeran beri.\nMa nameyê kıhanyeri keno pele redireksiyoni ser nameyê newe.\nTı eşkeno pele redireksiyoni ki şıno nameyê originali bıvurni.\nEg tı nıwazeno, ma tı ra rica keni tı [[Special:DoubleRedirects|double]] ya zi [[Special:BrokenRedirects|broken redirects]] qontrol bıki.\nTı gani qontrol bıki eg gıreyan şıno peleyanê raşti.\n\nTeme eka ser yew name de yew nuşte esti, sistemê ma '''nıeşkeno''' nuşte tı beri. Eka ser ena name de yew pele vengi esti, sistemê ma eşkeno nuşte tı beri.\nTı nıeşkeni name yew pele reyna bıvurni.\n\n'''Teme!'''\nEna transfer ser peleyanê populari zaf muhumo;\nMa tu ra rica keni, tı en verni dı qontrol bıki u bışıravi.",
        "movepagetext-noredirectfixer": "Pe form ki ho bın de, tı eşkeno name yew pele bıvurni u tarixê pele hemi ya zi pyeran beri.\nMa nameyê kıhanyeri keno pele redireksiyoni ser nameyê newe.\nTı eşkeno pele redireksiyoni ki şıno nameyê originali bıvurni.\nEg tı nıwazeno, ma tı ra rica keni tı [[Special:DoubleRedirects|raçarnayışo dılet]] ya zi [[Special:BrokenRedirects|raçarnayışo xırab]]i qontrol bıke.\nTı gani qontrol bıki eg gıreyan şıno peleyanê raşti.\n\nTeme eka ser yew name de yew nuşte esti, sistemê ma '''nıeşkeno''' nuşte tı beri. Eka ser ena name de yew pele vengi esti, sistemê ma eşkeno nuşte tı beri.\nTı nıeşkeni name yew pele reyna bıvurni.\n\n'''İkaz!'''\nEna transfer ser peleyanê populari zaf muhumo;\nMa tu ra rica keni, tı en verni dı qontrol bıki u bışıravi.",
        "tooltip-ca-unprotect": "Starkerdışe ena peler bıvurne",
        "tooltip-ca-delete": "Ena pele bestere",
        "tooltip-ca-undelete": "peli biyarê halê ver hewnakerdışi",
-       "tooltip-ca-move": "Ena peler wegi",
+       "tooltip-ca-move": "Ena pele bıkırışe",
        "tooltip-ca-watch": "Ena pele lista xoya seyrkerdışi ke",
        "tooltip-ca-unwatch": "Ena pele lista xoya seyrkerdışi ra vece",
        "tooltip-search": "{{SITENAME}} de cı geyre",
        "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ê",
        "anonymous": "{{PLURAL:$1|karberê|karberê}} anonimi yê keyepelê {{SITENAME}}i",
        "siteuser": "karberê {{SITENAME}}i $1",
        "anonuser": "karberê anonim o {{SITENAME}}i $1",
-       "lastmodifiedatby": "Ena pele tewr peyên roca $2, $1 by $3. de biya rocaniye",
+       "lastmodifiedatby": "Ena pele tewr peyên roca $2, $1 de tereftê $3 ra vuriya ya.",
        "othercontribs": "xebatê $1 ıney geriyayo diqqeti/geriyayo nezer.",
        "others": "bini",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|karberê ey|karberanê ey}} $1",
        "feedback-bugcheck": "Harika! Sadece [xırabina ke $1 ] çınyayışê cı kontrol keno.",
        "feedback-bugnew": "Mı qontrol ke. Xetaya newi xeber ke",
        "feedback-bugornote": "Jew mersela teferruato teknik esta şıma reca malumatê şıma hazıro se [ $1  jew xırab rapor] bıvinê.Zewbi zi, formê cerê xo rê şenê karfiyê. Vatışê xo pela da \"[ $3  $2 ]\", namey karber dê xoya piya u wasteriya karfiye.",
-       "feedback-cancel": "Bıtexelne",
+       "feedback-cancel": "Bıterkın",
        "feedback-close": "Biya star",
        "feedback-error1": "Xeta: API ra neticey ne vıcyay",
        "feedback-error2": "Xeta: Timar kerdış nebı",
index 7c755f7..e64a80e 100644 (file)
        "action-applychangetags": "apply tags along with your changes",
        "action-changetags": "add and remove arbitrary tags on individual revisions and log entries",
        "action-deletechangetags": "delete tags from the database",
+       "action-purge": "purge this page",
        "nchanges": "$1 {{PLURAL:$1|change|changes}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|since last visit}}",
        "enhancedrc-history": "history",
index 5fa1a5d..c899eca 100644 (file)
        "anontalkpagetext": "----<em>این صفحهٔ بحث برای کاربر گمنامی است که هنوز حسابی درست نکرده است یا از آن استفاده نمی‌کند.\nبنا بر این برای شناسایی‌اش مجبوریم از نشانی آی‌پی عددی استفاده کنیم.</em>\nچنین نشانی‌های آی‌پی ممکن است توسط چندین کاربر به شکل مشترک استفاده شود.\nاگر شما کاربر گمنامی هستید و تصور می‌کنید اظهار نظرات نامربوط به شما صورت گرفته است، لطفاً برای پیشگیری از اشتباه گرفته شدن با کاربران گمنام دیگر در آینده [[Special:CreateAccount|حسابی ایجاد کنید]] یا [[Special:UserLogin|به سامانه وارد شوید]].",
        "noarticletext": "این صفحه هم‌اکنون دارای هیچ متنی نیست.\nشما می‌توانید در صفحه‌های دیگر [[Special:Search/{{PAGENAME}}|عنوان این صفحه را جستجو کنید]]،\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} سیاهه‌های مرتبط را جستجو کنید]،\nیا [{{fullurl:{{FULLPAGENAME}}|action=edit}} این صفحه را ایجاد کنید]</span>.",
        "noarticletext-nopermission": "این صفحه هم‌اکنون متنی ندارد.\nشما می‌توانید در دیگر صفحات [[Special:Search/{{PAGENAME}}|این عنوان را جستجو کنید]]،\nیا <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} سیاهه‌های مرتبط را بگردید]</span> ولی شما اجازه ایجاد این صفحه را ندارید.",
-       "missing-revision": "ویرایش #$1 از صفحهٔ «{{FULLPAGENAME}}» موجود نیست.\n\nمعمولاً در اثر پیوند به تاریخچهٔ به‌روز نشدهٔ صفحهٔ حذف شده است.\nمی‌توانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.",
+       "missing-revision": "ویرایش #$1 از صفحهٔ «{{FULLPAGENAME}}» موجود نیست.\n\nاین اتفاق معمولاً در اثر دنبال کردن پیوندی به تاریخچهٔ یک صفحهٔ حذف‌شده پیش می‌آید.\nمی‌توانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.",
        "userpage-userdoesnotexist": "حساب کاربر «<nowiki>$1</nowiki>» ثبت نشده‌است.\nلطفاً مطمئن شوید که می‌خواهید این صفحه را ایجاد یا ویرایش کنید.",
        "userpage-userdoesnotexist-view": "حساب کاربری «$1» ثبت نشده‌است.",
        "blocked-notice-logextract": "دسترسی این کاربر در حال حاضر بسته است.\nآخرین مورد سیاهه قطع دسترسی در زیر آمده‌است:",
        "diff-multi-sameuser": "({{PLURAL:$1|یک نسخهٔ میانی|$1 نسخهٔ میانی}}ِ همین کاربر نمایش داده نشده است)",
        "diff-multi-otherusers": "({{PLURAL:$1|۱ نسخهٔ میانی|$1 نسخه‌ٔ میانی}} ویرایش شده توسط {{PLURAL:$2|۱ کاربر|$2 کاربر}} نشان داده نشده)",
        "diff-multi-manyusers": "({{PLURAL:$1|یک|$1}} نسخه‌ٔ میانی ویرایش شده توسط بیش از {{PLURAL:$2|یک|$2}} کاربر نشان داده نشده است)",
-       "difference-missing-revision": "{{PLURAL:$2|یک ویرایش|$2 ویرایش}}  از تفاوت نسخه‌ها ($1) {{PLURAL:$2|یافت|یافت}}  نشد.\n\nمعمولاً در اثر پیوند به تاریخچهٔ به‌روز نشدهٔ صفحهٔ حذف شده است.\nمی‌توانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.",
+       "difference-missing-revision": "{{PLURAL:$2|یک ویرایش|$2 ویرایش}}  از تفاوت نسخه‌ها ($1) {{PLURAL:$2|یافت|یافت}}  نشد.\n\nاین اتفاق معمولاً در اثر دنبال کردن پیوند تفاوتی به یک صفحهٔ حذف‌شده پیش می‌آید.\nمی‌توانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.",
        "searchresults": "نتایج جستجو",
        "searchresults-title": "نتایج جستجو برای «$1»",
        "titlematches": "تطبیق عنوان مقاله",
index d984da4..8d7cb8b 100644 (file)
        "post-expand-template-argument-warning": "<strong>Attention :</strong> cette page contient au moins un paramètre de modèle dont la taille après expansion est trop importante. \nCes arguments n’ont donc pas été inclus.",
        "post-expand-template-argument-category": "Pages contenant des paramètres de modèle non évalués",
        "parser-template-loop-warning": "Modèle en boucle détecté : [[$1]]",
-       "parser-template-recursion-depth-warning": "Limite de profondeur des appels de modèles dépassée ($1)",
+       "parser-template-recursion-depth-warning": "Limite de profondeur des appels récursifs de modèles dépassée ($1)",
        "language-converter-depth-warning": "Limite de profondeur du convertisseur de langue dépassée ($1)",
        "node-count-exceeded-category": "Pages dépassant le nombre de nœuds maximal",
        "node-count-exceeded-category-desc": "Ces pages dépassent le nombre maximal de nœuds.",
        "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 8e09dd7..2182253 100644 (file)
        "minoredit": "આ એક નાનો સુધારો છે",
        "watchthis": "આ પાનાને ધ્યાનમાં રાખો",
        "savearticle": "પાનું સાચવો",
+       "publishpage": "પાનું પ્રકાશિત કરો",
+       "publishchanges": "ફેરફારો પ્રકાશિત કરો",
        "preview": "પૂર્વાવલોકન",
        "showpreview": "ઝલક જુવો",
        "showdiff": "ફેરફારો દર્શાવો",
        "special-characters-group-thai": "થાઈ",
        "special-characters-group-lao": "લાઓ",
        "special-characters-group-khmer": "ખ્મેર",
-       "mw-widgets-titleinput-description-new-page": "પાનું અસ્તિત્વ ધરાવતું નથી.",
-       "api-error-blacklisted": "મહેરબાની કરી વધુ વિસ્તૃત અર્થ સભર શીર્ષક આપો."
+       "mw-widgets-titleinput-description-new-page": "પાનું અસ્તિત્વ ધરાવતું નથી."
 }
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 2bbaebe..1c15fc7 100644 (file)
        "minoredit": "Apró változtatás",
        "watchthis": "A lap figyelése",
        "savearticle": "Lap mentése",
-       "publishpage": "Lap mentése",
+       "publishpage": "Lap közzététele",
+       "publishchanges": "Változtatások közzététele",
        "preview": "Előnézet",
        "showpreview": "Előnézet megtekintése",
        "showdiff": "Változtatások megtekintése",
index f1d8048..8abca6a 100644 (file)
@@ -6,7 +6,8 @@
                        "Marmase",
                        "Mirzali",
                        "아라",
-                       "Macofe"
+                       "Macofe",
+                       "Kumkumuk"
                ]
        },
        "tog-underline": "Bınê gırey de xete bonce:",
        "retypenew": "Parola newiye tekrar ke:",
        "resetpass_submit": "Parola ayar ke u cı kuye",
        "changepassword-success": "Parola sıma ebe serkotene vurriye! Nıka hesabê sıma beno ra...",
+       "botpasswords-label-cancel": "Bıtexelne",
        "resetpass_forbidden": "Paroley nêşikinê bıvurniyê",
        "resetpass-submit-loggedin": "Parola bıvurne",
        "resetpass-submit-cancel": "Bıtexelne",
        "watchthis": "Na pele de şêr ke",
        "savearticle": "Pele qeyd ke",
        "preview": "Verqayt",
-       "showpreview": "Verqayti bıasne",
+       "showpreview": "Verqayti bımocne",
        "showdiff": "Vurnaisun bıasne",
        "anoneditwarning": "'''Diqet:''' Tı cınêkota.\nTarixê vurnaena na pele de, hurêndia leqeme de numra tuya IPy qeyd bena.",
        "missingcommenttext": "Cêr de jü xulasa bınuse.",
        "upload-source": "Dosya çımey",
        "sourcefilename": "Namê dosya çımey:",
        "watchthisupload": "Na dosya de şêr ke",
+       "upload-dialog-button-cancel": "Bıtexelne",
        "license": "Lisans:",
        "license-header": "Lisansdais",
        "imgfile": "dosya",
        "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",
        "compare-page1": "Pele 1",
        "compare-page2": "Pele 2",
        "rightsnone": "(qet jü)",
-       "revdelete-summary": "xulasa vurnaene"
+       "revdelete-summary": "xulasa vurnaene",
+       "feedback-cancel": "Bıtexelne"
 }
index dfbe52b..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": "당신의 주시문서로 상호작용",
        "protectlogtext": "아래의 목록은 문서 보호에 관한 바뀜에 대한 기록입니다.\n현재 보호된 문서의 목록에 대해서는 [[Special:ProtectedPages|보호된 문서 목록]]을 참조하세요.",
        "protectedarticle": "님이 \"[[$1]]\" 문서를 보호했습니다",
        "modifiedarticleprotection": "님이 \"[[$1]]\" 문서의 보호 설정을 바꿨습니다",
-       "unprotectedarticle": "님이 \"[[$1]]\" 문서를 보호 해제했습니다",
+       "unprotectedarticle": "\"[[$1]]\" 문서를 보호 해제했습니다",
        "movedarticleprotection": "님이 문서의 보호 설정을 \"[[$2]]\"에서 \"[[$1]]\"(으)로 이동했습니다",
        "protect-title": "\"$1\" 보호하기",
        "protect-title-notallowed": "\"$1\" 문서의 보호 수준 보기",
index 708f61b..af6b90c 100644 (file)
        "retrievedfrom": "Lähte - \"$1\"",
        "youhavenewmessages": "{{PLURAL:$3|Šiula on}} $1 ($2).",
        "editsection": "kohentele",
-       "editold": "kohenna",
+       "editold": "kohentele",
        "viewsourceold": "näytä wikiteksti",
        "editlink": "kohentele",
        "viewsourcelink": "näytä lähtehkoodi",
        "databaseerror-query": "Kyšely: $1",
        "databaseerror-error": "Hairahuš: $1",
        "badtitle": "Šivun nimi ei kelpua",
-       "badtitletext": "Šiun annetti šivunimi oli virheellini, tyhjä tahi viärin linkitetty kielienvälini tahi wikienvälini nimi.\nSiinä suattau olla yksi tahi usiempi sellani merkki, kumpasta ei voi käyttyä šivujen nimissä.",
+       "badtitletext": "Šiun pyytämä šivunimi oli virhiellini, tyhjä tahi viärin linkitetty kielienvälini tahi wikienvälini nimi.\nŠiinä šuattau olla yksi tahi ušiempi šemmoni merkki, kumpaista ei voi käyttyä šivujen nimilöissä.",
        "viewsource": "näytä lähtehkoodi",
        "yourname": "Käyttäjänimi:",
        "userlogin-yourname": "Käyttäjänimi",
        "userlogin-yourname-ph": "Kirjuta käyttäjänimi",
        "yourpassword": "Tunnuššana:",
-       "userlogin-yourpassword": "Tunnuššana",
-       "userlogin-yourpassword-ph": "Kirjuta tunnuššana",
-       "createacct-yourpassword-ph": "Kirjuta tunnuššana",
-       "createacct-yourpasswordagain": "Vahvista tunnuššana",
-       "createacct-yourpasswordagain-ph": "Kirjuta tunnuššana uuvveštah",
+       "userlogin-yourpassword": "Šalašana",
+       "userlogin-yourpassword-ph": "Kirjuta šalašana",
+       "createacct-yourpassword-ph": "Kirjuta šalašana",
+       "createacct-yourpasswordagain": "Vahvista šalašana",
+       "createacct-yourpasswordagain-ph": "Kirjuta šalašana uuvveštah",
        "userlogin-remembermypassword": "Pijä miut kirjuttautunuona",
        "login": "Kirjauvu šiämeh",
        "nav-login-createaccount": "Kirjauvu šiämeh / rekisteriyvy",
        "userlogin-joinproject": "Liity {{SITENAME}}",
        "createaccount": "Luaji käyttäjätili",
        "gotaccountlink": "Kirjauvu šiämeh",
-       "userlogin-resetpassword-link": "Unohitko tunnuššanan?",
+       "userlogin-resetpassword-link": "Unohitko šalašanan?",
        "userlogin-helplink2": "Apu kirjuttautumiseh",
-       "createacct-emailoptional": "Sähköpostiadressi (ei tarviče vältämättäh kirjuttua)",
-       "createacct-email-ph": "Kirjuta oma sähkopostiadressi",
+       "createacct-emailoptional": "Šähköpoštiošoiteh (ei tarviče välttämättä kirjuttua)",
+       "createacct-email-ph": "Kirjuta oma šähköpoštiošoiteh",
        "createaccountreason": "Šyy:",
        "createacct-reason": "Šyy",
        "createacct-submit": "Luaji oma käyttäjätunnuš",
        "sig_tip": "Teijän allakirjutuš ta aika",
        "hr_tip": "Vuakašuora viiva (elä käytä liijakši)",
        "summary": "Yhtehveto",
-       "minoredit": "Tämä on pieni muutoš",
+       "minoredit": "Tämä on pieni kohennuš",
        "watchthis": "Tarkkaile tätä šivuo",
        "savearticle": "Tallenna šivu",
        "showpreview": "Esikačo",
        "blockednoreason": "ei šyytä annettu",
        "loginreqlink": "kirjauvu šiämeh",
        "newarticle": "(Uuši)",
-       "newarticletext": "Olet piätynyn šivulla, kumpasta ei ole. Ku luatie šivu, rupie kirjuttamah alla olijah juaššiekkah (kačo [$1 ohjavošivulta] lisätietuo).\nKu ollet piätynyn tänne petties, käytä livaimen <strong>mennä järilleh</strong>-toimintuo.",
+       "newarticletext": "Linkki toi šivulla, kumpaista ei vielä ole.\nVoit luuvva šivun kirjuttamalla alla olijah ikkunah (kačo [$1 ohješivulta] lisätietoja). \nJoš et haluo luuvva šivuo, käytä šelaimen paluutoimintuo.",
        "noarticletext": "Tällä šivulla ei ole juuri nyt tekstie.\nVoit [[Special:Search/{{PAGENAME}}|eččie šivun nimellä]] muilta šivuilta,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} eččie šitä koškijua logie],\ntahi [{{fullurl:{{FULLPAGENAME}}|action=edit}} luuvva tämän šivun]</span>.",
        "noarticletext-nopermission": "Tällä šivulla ei ole juuri nyt tekstie.\nVoit [[Special:Search/{{PAGENAME}}|eččie šivun nimellä]] muilta šivuilta, tahi <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} eččie šivuo koškijua logie]</span>, ka šiula ei ole oikeutta luuvva tätä šivuo.",
-       "editing": "Kohennellah sivuu $1",
-       "creating": "Luajitah šivuu \"$1\"",
+       "editing": "Kohennellah šivuo $1",
+       "creating": "Luajitah šivuo \"$1\"",
        "editingsection": "Kohennellah $1 (alaluku)",
        "templatesused": "Tällä šivulla {{PLURAL:$1|käytetty malli|käytetyt mallit}}:",
        "template-protected": "(šuojattu)",
        "template-semiprotected": "(ošittain šuojattu)",
        "hiddencategories": "Tämä šivu kuuluu {{PLURAL:$1|1 peitettyh kategorijah|$1 peitettylöih kategorijoih}}:",
        "permissionserrorstext-withaction": "Šiula ei ole oikeutta {{lcfirst:$2}} {{PLURAL:$1|šeuruavašta šyyštä|šeuruavista šyistä}}:",
-       "moveddeleted-notice": "Tämä šivu on otettu iäre. Šivun iäreotanta- ta siirtoistorija ollah annettu alla viittavuksena.",
+       "moveddeleted-notice": "Tämä šivu on poistettu.\nAlla on tämän šivun poisto- ta šiirtoistorija.",
        "viewpagelogs": "Näytä tämän šivun lokit",
        "currentrev-asof": "Nykyni versija $1",
        "revisionasof": "Versija $1",
        "difference-title": "Ero šivun ”$1” versijien välillä",
        "lineno": "Rivi $1:",
        "editundo": "lakauttua",
-       "diff-multi-sameuser": "({{PLURAL:$1|Yksi keskitason versija |$1 keskitason versijua}} samalta käyttäjältä ei näytetty)",
+       "diff-multi-sameuser": "({{PLURAL:$1|Yksi keškitasšon versija |$1 keškitašon versijua}} šamalta käyttäjältä ei näytetty)",
        "searchresults": "Eččimisen tulokšet",
        "searchresults-title": "Eči \"$1\"",
        "prevn": "iellini {{PLURAL:$1|$1}}",
        "search-result-size": "$1 ({{PLURAL:$2|1 šana|$2 šanua}})",
        "search-redirect": "(šiirretty $1)",
        "search-section": "(alaluku $1)",
-       "search-suggest": "Tarkoititko: $1",
+       "search-suggest": "Tarkotitko: $1",
        "searchall": "kaikki",
        "search-showingresults": "{{PLURAL:$4|Tuloš <strong>$1</strong> / <strong>$3</strong>|Tulokšet <strong>$1 - $2</strong> / <strong>$3</strong>}}",
        "search-nonefound": "Kyšelyh ei löytyn tulokšie.",
        "booksources-search-legend": "Eči kirjalähtehie",
        "booksources-search": "Eči",
        "log": "Lokit",
-       "allarticles": "Kai artikkelit",
+       "allarticles": "Kaikki šivut",
        "allpagessubmit": "Mäne",
        "categories": "Kategorijat",
        "linksearch-ok": "Ečindy",
        "watchlist": "Kaččuolistu",
        "mywatchlist": "Valvontaluvettelo",
        "watch": "Valvo",
-       "dellogpage": "Iäreotantaistorija",
+       "dellogpage": "Poistoloki",
        "rollbacklink": "Tuo entini versija",
        "rollbacklinkcount": "palauta $1 {{PLURAL:$1|muutoš|muutošta}}",
-       "protectlogpage": "Šuojavusistorija",
+       "protectlogpage": "Šuojaušloki",
        "protectcomment": "Šyy",
        "restriction-edit": "Kohennuš",
        "undelete-search-submit": "Ečindy",
        "tooltip-namespace_association": "Valiče tämä kohta, još haluot lisätä niise valittuh nimitilah liittyjät pakina- tahi aihenimitilat",
        "blanknamespace": "(Piä)",
        "contributions": "{{GENDER:$1|Käyttäjän}} panoš",
-       "mycontris": "Omat kohennukšet",
+       "mycontris": "Kirjutukšet",
        "anoncontribs": "Omat kohennukšet",
-       "month": "Täššä kuušša (tahi aijempi)",
+       "month": "Kuukauši",
        "year": "Vuosi",
        "sp-contributions-submit": "Ečindy",
        "whatlinkshere": "Linkit tänne",
-       "whatlinkshere-title": "Šivut, kumpaset košketah šivuu \"$1\"",
+       "whatlinkshere-title": "Šivut, kumpaset viitatah šivulla \"$1\"",
        "whatlinkshere-page": "Šivu:",
        "linkshere": "Šeuruavilta šivuilta on linkki šivulla <strong>[[:$1]]</strong>:",
        "isredirect": "ohjauššivu",
        "istemplate": "šisällytetty",
        "isimage": "failin linkki",
-       "whatlinkshere-prev": "{{PLURAL:$1|iellini|iellini $1}}",
-       "whatlinkshere-next": "{{PLURAL:$1|tulija|tulija $1}}",
+       "whatlinkshere-prev": "{{PLURAL:$1|iellini|iellistä $1}}",
+       "whatlinkshere-next": "{{PLURAL:$1|tulija|tulijua $1}}",
        "whatlinkshere-links": "← linkit",
        "whatlinkshere-hideredirs": "$1 ohjaukšet",
        "whatlinkshere-hidetrans": "$1 šisällytykšet",
        "allmessages-filter-translate": "Kiännä",
        "thumbnail-more": "Šuurenna",
        "tooltip-pt-userpage": "{{GENDER:|Oma käyttäjäšivu}}",
-       "tooltip-pt-mytalk": "Oma paginsivu",
-       "tooltip-pt-preferences": "{{GENDER:|Omat ašetukset}}",
+       "tooltip-pt-mytalk": "Oma pakinašivu",
+       "tooltip-pt-preferences": "{{GENDER:|Omat ašetukšet}}",
        "tooltip-pt-watchlist": "Lista šivuista, kumpasien muutokšie valvot",
        "tooltip-pt-mycontris": "Luvettelo {{GENDER:|šiun}} kirjutukšista",
        "tooltip-pt-login": "Täššä voit kirjuttautuo, ka še ei ole välttämätöintä",
        "tooltip-preview": "Esikačo muutokšet. Ole hyvä, luaji šitä aina ennen tallennušta.",
        "tooltip-diff": "Näytä luajitut muutokšet",
        "tooltip-rollback": "Pyyhi pois viimesen kohentelijan luatimat muutokšet yhellä kertua",
-       "tooltip-undo": "Kumoamini palauttau tämän muutokšen ta avuau artikkelin esikaččelussa. Yhtehvetokenttäh voi kirjuttua palautukšen šyyn.",
+       "tooltip-undo": "Kumuomini palauttau tämän muutokšen ta avuau artikkelin esikaččelušša. Yhtehvetokenttäh voi kirjuttua palautukšen šyyn.",
        "tooltip-summary": "Kirjuta lyhyt kuvauš",
        "simpleantispam-label": "Anti-spam-tarkissuš. \n<strong>älä</strong> täytä tätä!",
        "pageinfo-toolboxlink": "Šivun tiijot",
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 f0f3e1e..8044922 100644 (file)
        "savearticle": "Зачувај",
        "savechanges": "Зачувај промени",
        "publishpage": "Објави ја страницата",
-       "publishchanges": "Ð\9eбÑ\98ави Ð¿Ñ\80омени",
+       "publishchanges": "Ð\9eбÑ\98ави Ð³Ð¸ Ð¿Ñ\80омениÑ\82е",
        "preview": "Преглед",
        "showpreview": "Преглед",
        "showdiff": "Прикажи промени",
        "prefs-skin": "Руво",
        "skin-preview": "Преглед",
        "datedefault": "Небитно",
-       "prefs-labs": "Ð\95кÑ\81пеÑ\80именÑ\82ални можности",
+       "prefs-labs": "Ð\9fÑ\80обни можности",
        "prefs-user-pages": "Кориснички страници",
        "prefs-personal": "Кориснички профил",
        "prefs-rc": "Скорешни промени",
index 73eef2a..057cac7 100644 (file)
@@ -48,7 +48,8 @@
                        "Tarjeimo",
                        "Matma Rex",
                        "SuperPotato",
-                       "Nemo bis"
+                       "Nemo bis",
+                       "Telaneo"
                ]
        },
        "tog-underline": "Strek under lenker:",
        "minoredit": "Dette er en mindre endring",
        "watchthis": "Overvåk denne siden",
        "savearticle": "Lagre siden",
+       "publishpage": "Publiser siden",
+       "publishchanges": "Publiser endringene",
        "preview": "Forhåndsvisning",
        "showpreview": "Forhåndsvisning",
        "showdiff": "Vis endringer",
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 1f93a26..81b7976 100644 (file)
        "title-invalid-interwiki": "O título da página solicitada contém uma ligação interlíngua que não pode ser utilizada em títulos.",
        "title-invalid-talk-namespace": "O título da página solicitada refere-se a uma página de discussão que não existe.",
        "title-invalid-characters": "O título da página solicitada contém carateres inválidos: \"$1\".",
+       "title-invalid-relative": "O título contém um caminho relativo. Os títulos relativos (./, ../) são inválidos porque estarão inacessíveis muitas vezes ao serem carregados pelo navegador do utilizador.",
        "title-invalid-magic-tilde": "O título da página solicitada possui uma sequência de tis inválida (<nowiki>~~~</nowiki>).",
        "title-invalid-too-long": "O título da página solicitada é demasiado longo. Não deverá ser maior que $1 {{PLURAL:$1|byte|bytes}} na codificação UTF-8.",
        "title-invalid-leading-colon": "O título da página solicitada contém um erro de pontuação (:) no início.",
        "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",
        "apisandbox-submit-invalid-fields-title": "Alguns campos são inválidos",
        "apisandbox-submit-invalid-fields-message": "Por favor, corrija os campos marcados e tente novamente.",
        "apisandbox-results": "Resultados",
+       "apisandbox-sending-request": "A enviar solicitação de API...",
+       "apisandbox-loading-results": "A receber resultados da API...",
        "apisandbox-request-url-label": "URL do pedido:",
        "apisandbox-request-time": "Tempo de processamento: {{PLURAL:$1|$1 ms}}",
        "apisandbox-alert-field": "O valor deste campo não é válido.",
        "changecontentmodel-success-text": "O tipo de conteúdo de [[:$1]] foi alterado.",
        "changecontentmodel-cannot-convert": "O conteúdo em [[:$1]] não pode ser convertido para um tipo de $2.",
        "changecontentmodel-nodirectediting": "O modelo de conteúdo $1 não suporta edição direta",
+       "changecontentmodel-emptymodels-title": "Não há modelos de conteúdo disponíveis",
+       "changecontentmodel-emptymodels-text": "O conteúdo em [[:$1]] não pode ser convertido para qualquer tipo.",
        "log-name-contentmodel": "Registo de alteração de modelo de conteúdo",
        "log-description-contentmodel": "Eventos relacionados com os modelos de conteúdo de uma página",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|criou}} a página $3 com o modelo de conteúdo desconhecido \"$5\"",
        "lockdbsuccesstext": "A base de dados da {{SITENAME}} foi bloqueada.<br />\nLembre-se de [[Special:UnlockDB|remover o bloqueio]] após a manutenção.",
        "unlockdbsuccesstext": "A base de dados foi desbloqueada.",
        "lockfilenotwritable": "O ficheiro de bloqueio da base de dados não pode ser escrito.\nPara bloquear ou desbloquear a base de dados, este precisa de poder ser escrito pelo servidor de internet.",
+       "databaselocked": "A base de dados já está bloqueada.",
        "databasenotlocked": "A base de dados não está bloqueada.",
        "lockedbyandtime": "(por {{GENDER:$1|$1}} em $2 às $3)",
        "move-page": "Mover $1",
        "timezone-local": "Local",
        "duplicate-defaultsort": "<strong>Aviso:</strong> A chave de ordenação padrão \"$2\" sobrepõe-se à anterior \"$1\".",
        "duplicate-displaytitle": "<strong>Aviso:</strong> O título em exibição \"$2\" anula o título anteriormente em exibição \"$1\".",
+       "restricted-displaytitle": "<strong>Aviso</strong>: A apresentação do título \"$1\" foi ignorada porque não é equivalente ao título atual da página.",
        "invalid-indicator-name": "<strong>Erro:</strong> O atributo <code>name</code>, da página de estados, não deve estar em branco.",
        "version": "Versão",
        "version-extensions": "Extensões instaladas",
        "tags-deactivate": "desativar",
        "tags-hitcount": "$1 {{PLURAL:$1|modificação|modificações}}",
        "tags-manage-no-permission": "Não possui permissão para gerir alterações de etiquetas.",
+       "tags-manage-blocked": "Não pode gerir alterações de etiquetas enquanto estiver bloqueado.",
        "tags-create-heading": "Criar nova etiqueta",
        "tags-create-explanation": "Por definição, etiquetas recém-criadas estarão disponíveis para utilização por utilizadores e robôs.",
        "tags-create-tag-name": "Nome da etiqueta:",
        "log-action-filter-managetags-delete": "Eliminação de etiqueta",
        "log-action-filter-managetags-activate": "Ativação de etiqueta",
        "log-action-filter-managetags-deactivate": "Desativação de etiqueta",
+       "log-action-filter-move-move": "Mover sem a substituição de páginas de redirecionamento",
+       "log-action-filter-move-move_redir": "Mover com a substituição de páginas de redirecionamento",
        "log-action-filter-newusers-create": "Criação por utilizador anónimo",
        "log-action-filter-newusers-create2": "Criação por utilizador registado",
        "log-action-filter-newusers-autocreate": "Criação automática",
        "authmanager-email-help": "Endereço de correio eletrónico",
        "authmanager-realname-label": "Nome verdadeiro",
        "authmanager-realname-help": "Nome verdadeiro do(a) utilizador(a)",
+       "authmanager-provider-password": "Autenticação baseada em palavra-passe",
+       "authmanager-provider-password-domain": "Autenticação baseada em palavra-passe e domínio",
        "authmanager-provider-temporarypassword": "Palavra-passe temporária",
+       "authprovider-confirmlink-message": "Com base nas tuas últimas tentativas para iniciar sessão, as seguintes contas podem ser ligadas à tua conta wiki. Vinculá-las permite que inicie sessão através das mesmas. Selecione quais pretende vincular.",
        "authprovider-confirmlink-success-line": "$1: Ligado com êxito.",
        "authprovider-resetpass-skip-label": "Ignorar",
        "authprovider-resetpass-skip-help": "Ignorar redefinição de palavra-passe",
+       "authform-newtoken": "Chave em falta. $1",
+       "authform-notoken": "Chave em falta",
+       "authform-wrongtoken": "Chave errada",
        "specialpage-securitylevel-not-allowed-title": "Não permitido",
        "specialpage-securitylevel-not-allowed": "Desculpe, não tem permissão para utilizar esta página porque a sua identidade não pôde ser verificada.",
        "authpage-cannot-login": "Não é possível iniciar sessão.",
index 099504d..ceb2fef 100644 (file)
        "action-applychangetags": "{{doc-action|applychangetags}}",
        "action-changetags": "{{doc-action|changetags}}",
        "action-deletechangetags": "{{doc-action|deletechangetags}}",
+       "action-purge": "{{doc-action|purge}}",
        "nchanges": "Appears on enhanced watchlist and recent changes when page has more than one change on given date, linking to a diff of the changes.\n\nParameters:\n* $1 - the number of changes on that day (2 or more)\nThree messages are shown side-by-side: ({{msg-mw|Nchanges}} | {{msg-mw|Enhancedrc-since-last-visit}} | {{msg-mw|Enhancedrc-history}}).",
        "enhancedrc-since-last-visit": "Appears on enhanced watchlist and recent changes when page has more than one change on given date and at least one that the user hasn't seen yet, linking to a diff of the unviewed changes.\n\nParameters:\n* $1 - the number of unviewed changes (1 or more)\nThree messages are shown side-by-side: ({{msg-mw|nchanges}} | {{msg-mw|enhancedrc-since-last-visit}} | {{msg-mw|enhancedrc-history}}).",
        "enhancedrc-history": "Appears on enhanced watchlist and recent changes when page has more than one change on given date, linking to its history.\n\nThis is the same as {{msg-mw|hist}}, but not abbreviated.\n\nThree messages are shown side-by-side: ({{msg-mw|nchanges}} | {{msg-mw|enhancedrc-since-last-visit}} | {{msg-mw|enhancedrc-history}}).\n{{Identical|History}}",
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 20a8591..277baa3 100644 (file)
        "watchthis": "Vëzhgoje këtë faqe",
        "savearticle": "Kryej ndryshimet",
        "publishpage": "Publiko faqen",
+       "publishchanges": "Publiko ndryshimet",
        "preview": "Shqyrto",
        "showpreview": "Shfaq për shqyrtim",
        "showdiff": "Trego ndryshimet",
index 757e97e..d2a098f 100644 (file)
        "databaseerror": "Медээ шыгжамыры алдаг",
        "laggedslavemode": "'''Оваарымчалыг:''' Бо арында чаартыышкыннар чок болуп болур.",
        "readonly": "шоочалаарынга медээ шыгжамыры",
-       "missing-article": "Данныйлар базазында тывар ужурлуг «$1» $2 деп арынның негеттинип турар сөзүглели тывылбаан.\n\nНургулайында ындыг байдал эрги шөлүг-биле казыттынган арынның өскерилге төөгүзүнче дамчып оралдажырга тыптыр.\n\nА шынында ындыг эвес болза, Силер программа хандырылгазының алдаанга душканыңар хөңнү.\n\nОоң дугайында кайы-бир [[Special:ListUsers/sysop|удуртукчуларга]], мүн URL-ин айытпышаан, дамчыдыңарам.",
+       "missing-article": "«$1» $2 деп арында дилеп турганың сөстер медээ үндезининден тывылбады.\n\nБаладып каапкан арынның төөгүзүн, эрги айтыг таварыштыр киргеш көөр болзуңза ындыг чүвеге таваржып болур сен.\n\nБир эвес хамыктың ужуру ындыг эвес боор болза, сен программаның шын эвес ажылдааныга душканыңар ол болур. \nОоң дугайында бээр [[Special:ListUsers/sysop|удуртукчуларга]] бижипкеш, шын эвес ажылдаан арынның URL адрезин база албан айып каар сен.",
        "missingarticle-rev": "(үндүрериниң саны: $1)",
        "missingarticle-diff": "(Ылгал: $1, $2)",
        "internalerror": "Иштики алдаг",
        "createaccountreason": "Чылдагаан:",
        "badretype": "Силерниң парлаан чажыт сөзүңер таарышпас.",
        "userexists": "Силерниң парлаан адыңар амгы үеде ажыглаттынып турар.\nӨске аттан шилип алыңар.",
-       "loginerror": "Ð\9aиÑ\80им Ð°Ð»Ð´Ð°Ð° (ЧазÑ\8bглÑ\8bг ÐºÐ¸Ñ\80им)",
+       "loginerror": "Ð\9aиÑ\80ип Ñ\88Ñ\8bдавадÑ\8bÒ£, Ñ\81ени Ñ\82анÑ\8bваан Ð±Ð¾Ð¾Ñ\80",
        "loginsuccesstitle": "Чедимчелиг кирери",
        "login-userblocked": "Бо ажыглакчы blocked.  Кирери хоржок.",
        "password-login-forbidden": "Бо ажыглакчының ады болгаш чажыт сөс хоржок.",
        "searchmenu-new": "Бо вики-төлевилелге «[[:$1]]» деп арынны кылыр.{{PLURAL:$2|0=|Ол ышкаш дилээшкиниңерниң түңнелинде тывылган арынны база көрүңер.|Ол ышкаш дилээшкиниңерниң түңнелдерин база көрүңер.}}",
        "searchprofile-articles": "үндезин арыннар",
        "searchprofile-images": "Мультимедиа",
-       "searchprofile-everything": "каяа-даа",
+       "searchprofile-everything": "Ð\9aаяа-даа",
        "searchprofile-advanced": "Делгереңгей",
        "searchprofile-articles-tooltip": "$1 иштинден дилээри",
        "searchprofile-images-tooltip": "Файлдар дилээри",
        "allmessages-language": "Дыл:",
        "allmessages-filter-submit": "Күүcедири",
        "thumbnail-more": "Улгаттыр",
-       "thumbnail_error": "Биче чурумал (миниатюра) чаяарының алдаа: $1",
+       "thumbnail_error": "Бичежек чурук болдунмады: $1",
        "import-comment": "Тайылбыр:",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|үндүрери}}",
        "tooltip-pt-userpage": "Силерниң ажыглакчы арыныңнар",
        "specialpages-group-pages": "Арыннарның даңзызы",
        "specialpages-group-pagetools": "Арын херекселдери",
        "blankpage": "Куруг арын",
-       "external_image_whitelist": " #Ð\91о Ð¾Ð´Ñ\83Ñ\80Ñ\83гнÑ\83 Ð¾Ð»-ла Ñ\85евÑ\8dÑ\8dÑ\80 Ð°Ñ\80Ñ\82Ñ\82Ñ\8bÑ\80Ñ\8bңаÑ\80<pre>\n#ТÑ\83Ñ\80Ñ\83м Ð¸Ð»ÐµÑ\80едиглеÑ\80 (Ñ\80егÑ\83лÑ\8fÑ\80нÑ\8bе Ð²Ñ\8bÑ\80ажениÑ\8f) Ñ\84Ñ\80агменÑ\82илеÑ\80ин Ð¼Ð°Ò£Ð°Ð° Ñ\81алÑ\8bңаÑ\80 (// Ð°Ñ\80азÑ\8bнга Ñ\82Ñ\83Ñ\80аÑ\80 ÐºÐµÐ·Ñ\8dÑ\8dн)\n#Ð\94аÑ\88Ñ\82Ñ\8bкÑ\8b Ñ\87Ñ\83Ñ\80Ñ\83малдаÑ\80 URL-биле Ð¾Ð»Ð°Ñ\80 Ñ\85олбааÑ\88кан Ð±Ð¾Ð»Ñ\83Ñ\80.\n#Ð\94Ñ\83жа Ð±ÐµÑ\80геннеÑ\80и Ñ\87Ñ\83Ñ\80Ñ\83малдаÑ\80 ÐºÑ\8bлдÑ\8bÑ\80 ÐºÓ©Ñ\81Ñ\82үп ÐºÐµÐ»Ð¸Ñ\80, Ð°Ñ\80Ñ\82каннаÑ\80Ñ\8b Ñ\87Ñ\83Ñ\80Ñ\83малдаÑ\80же Ñ\88өлүг ÐºÑ\8bлдÑ\8bÑ\80 ÐºÓ©Ñ\81Ñ\82Ò¯Ñ\80.\n# \"#\" Ð´ÐµÐ¿ Ð´ÐµÐ¼Ð´ÐµÐºÑ\82ен Ñ\8dгелÑ\8dÑ\8dн Ð¾Ð´Ñ\83Ñ\80Ñ\83глаÑ\80нÑ\8b Ñ\81аналдаÑ\80 ÐºÑ\8bлдÑ\8bÑ\80 Ð±Ð¸Ð»Ð´Ð¸Ð½ÐµÑ\80.\n#Ð\9eдÑ\83Ñ\80Ñ\83глаÑ\80 Ñ\80егиÑ\81Ñ\82Ñ\80ге ÐºÑ\83нÑ\83к Ñ\8dвеÑ\81 (билинмеÑ\81)\n\n#ТÑ\83Ñ\80Ñ\83м Ð¸Ð»ÐµÑ\80едиглеÑ\80 Ñ\84Ñ\80агменÑ\82илеÑ\80ин Ð±Ð¾ Ð¾Ð´Ñ\83Ñ\80Ñ\83гнÑ\83Ò£ ÐºÑ\8bÑ\80Ñ\8bнга Ñ\81алÑ\8bңаÑ\80. Ð\90 Ð±Ð¾ Ð¾Ð´Ñ\83Ñ\80Ñ\83гнÑ\83 Ð¾Ð»Ñ\87аан Ñ\85евÑ\8dÑ\8dÑ\80 Ð°Ñ\80Ñ\82тырыңар</pre>",
+       "external_image_whitelist": " #Ð\91о Ð¾Ð´Ñ\83Ñ\80Ñ\83гнÑ\83 Ð¾Ð»-ла Ñ\85евÑ\8dÑ\8dÑ\80 Ð°Ñ\80Ñ\82Ñ\8bÑ\80Ñ\8bңаÑ\80<pre>\n#ТÑ\83Ñ\80Ñ\83м Ð¸Ð»ÐµÑ\80едигниң (Ñ\80егÑ\83лÑ\8fÑ\80нÑ\8bе Ð²Ñ\8bÑ\80ажениÑ\8f) Ò¯Ð·Ò¯ÐºÑ\82еÑ\80ин Ð¼Ð°Ò£Ð°Ð° Ð±Ð¸Ð¶Ð¸Ð¿Ñ\82иңеÑ\80 (// Ð´ÐµÐ¿ Ð´ÐµÐ¼Ð´ÐµÐº Ð°Ñ\80азÑ\8bнда Ñ\82Ñ\83Ñ\80аÑ\80 ÐºÐµÐ·Ñ\8dÑ\8d) Ð´Ð°Ñ\80аазÑ\8bнда Ð±Ð¾Ð»Ð·Ð°\n#олаÑ\80 Ó©Ñ\81ке URL Ð°Ð´Ñ\80еÑ\81Ñ\82е Ñ\82Ñ\83Ñ\80аÑ\80 Ñ\87Ñ\83Ñ\80Ñ\83кÑ\82аÑ\80-биле Ñ\85аÑ\80Ñ\8bлзаа Ñ\82Ñ\83дÑ\83п Ñ\82Ñ\83Ñ\80аÑ\80.\n#ТааÑ\80Ñ\8bÑ\88кан Ñ\87Ñ\83Ñ\80Ñ\83кÑ\82аÑ\80, Ñ\87Ñ\83Ñ\80Ñ\83к Ð±Ð¾Ð¾Ð¿ Ð¾Ð»-ла Ñ\85евÑ\8dÑ\8dÑ\80 ÐºÓ©Ñ\81Ñ\82үп ÐºÐµÐ»Ð¸Ñ\80, Ð°Ñ\80Ñ\82аннаÑ\80Ñ\8b Ñ\87Ñ\83Ñ\80Ñ\83кÑ\82аÑ\80же Ð°Ð¹Ñ\8bÑ\82кан Ð°Ð¹Ñ\82Ñ\8bг Ð±Ð¾Ð¾Ð¿ Ð°Ñ\80Ñ\82Ñ\8bп ÐºÐ°Ð°Ñ\80.\n# \"#\" Ð´ÐµÐ¿ Ð´ÐµÐ¼Ð´ÐµÐºÑ\82ен Ñ\8dгелÑ\8dÑ\8dн Ð¾Ð´Ñ\83Ñ\80Ñ\83глаÑ\80 Ð±Ð¾Ð»Ð·Ð°, Ð±Ð¸Ð¶Ð¸ÐºÑ\82иң Ñ\82Ñ\83Ñ\81кай Ñ\82айÑ\8bлбÑ\8bÑ\80 Ñ\82Ñ\83Ñ\80аÑ\80 ÐºÐµÐ·Ñ\8dÑ\8d-диÑ\80.\n#Ð\9eдÑ\83Ñ\80Ñ\83гга Ñ\83лÑ\83г-даа, Ð±Ð¸Ñ\87ии-даа Ò¯Ð¶Ò¯ÐºÑ\82еÑ\80 Ð±Ð¸Ð¶Ð¸Ð¿ Ð±Ð¾Ð»Ñ\83Ñ\80.\n\n#ТÑ\83Ñ\80Ñ\83м Ð¸Ð»ÐµÑ\80едигниң ÐºÐµÐ·ÐµÐºÑ\82еÑ\80ин Ð±Ð¾ Ð¾Ð´Ñ\83Ñ\80Ñ\83гнÑ\83Ò£ ÐºÑ\8bÑ\80Ñ\8bнга Ð±Ð¸Ð¶Ð¸Ð¿ Ñ\81алÑ\8bÑ\80 Ñ\81илеÑ\80. Ð\91о Ð¾Ð´Ñ\83Ñ\80Ñ\83гнÑ\83 Ð¾Ð»Ñ\87аан, Ñ\85евÑ\8dÑ\8dÑ\80 Ð°Ñ\80тырыңар</pre>",
        "tag-filter": "[[Special:Tags|демдек]] шүүрү:",
        "tag-filter-submit": "Шүүрү",
        "tags-title": "Демдеглелдер",
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 d34e2df..d807319 100644 (file)
        "minoredit": "דאס איז א מינערדיגע ענדערונג",
        "watchthis": "טוט אױפֿפּאַסן דעם בלאט",
        "savearticle": "אויפהיטן בלאַט",
-       "publishpage": "פובליצירן בלאט",
+       "publishpage": "פובליקירן בלאַט",
+       "publishchanges": "פובליקירן ענדערונגען",
        "preview": "פֿאראויסקוק",
        "showpreview": "ווייזן פאָרױסקוק",
        "showdiff": "ווײַז די ענדערונגען",
        "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": "בלעטער מיט צופֿיל טייערע פאַרזער פֿונקציאן רופֿן",
        "tooltip-ca-nstab-category": "באקוקט דעם קאטעגאריע בלאט",
        "tooltip-minoredit": "באצייכענען דאס אלס מינערדיגע ענדערונג",
        "tooltip-save": "אויפֿהיטן אייערע ענדערונגען",
+       "tooltip-publish": "פובליקירן אייערע ענדערונגען",
        "tooltip-preview": "פֿארויסדיגע ווײַזונג, זײַט אזוי גוט באניצט די געלעגנהייט פֿארן אויפֿהיטן!",
        "tooltip-diff": "ווײַזן אייערע ענדערונגען צום טעקסט",
        "tooltip-compareselectedversions": "פארגלײַכם די צוויי ווערסיעס פון דעם בלאט",
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( '-' ) + '-';
diff --git a/tests/phpunit/data/templates/conds.mustache b/tests/phpunit/data/templates/conds.mustache
deleted file mode 100644 (file)
index 5ebd2ea..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{{#list}}oh no{{/list}}{{#foo}}none of this should render{{/foo}}
\ No newline at end of file
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.' );
+       }
 }