Merge "mediawiki.util: Add debounce() function"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 11 Sep 2019 19:33:40 +0000 (19:33 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 11 Sep 2019 19:33:40 +0000 (19:33 +0000)
70 files changed:
RELEASE-NOTES-1.34
composer.json
includes/ServiceWiring.php
includes/api/ApiRevisionDelete.php
includes/block/BlockManager.php
includes/deferred/SearchUpdate.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialRevisionDelete.php
includes/specials/SpecialRunJobs.php
includes/user/User.php
jsduck.json
resources/Resources.php
resources/lib/foreign-resources.yaml
resources/lib/ooui/History.md
resources/lib/ooui/i18n/fr.json
resources/lib/ooui/i18n/pl.json
resources/lib/ooui/oojs-ui-apex.js
resources/lib/ooui/oojs-ui-core-apex.css
resources/lib/ooui/oojs-ui-core-wikimediaui.css
resources/lib/ooui/oojs-ui-core.js
resources/lib/ooui/oojs-ui-toolbars-apex.css
resources/lib/ooui/oojs-ui-toolbars-wikimediaui.css
resources/lib/ooui/oojs-ui-toolbars.js
resources/lib/ooui/oojs-ui-widgets-apex.css
resources/lib/ooui/oojs-ui-widgets-wikimediaui.css
resources/lib/ooui/oojs-ui-widgets.js
resources/lib/ooui/oojs-ui-wikimediaui.js
resources/lib/ooui/oojs-ui-windows-apex.css
resources/lib/ooui/oojs-ui-windows-wikimediaui.css
resources/lib/ooui/oojs-ui-windows.js
resources/lib/ooui/themes/apex/icons-editing-advanced.json
resources/lib/ooui/themes/apex/icons-user.json
resources/lib/ooui/themes/wikimediaui/icons-editing-advanced.json
resources/lib/ooui/themes/wikimediaui/icons-user.json
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline-invert.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline-progressive.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg [new file with mode: 0644]
resources/src/jquery.color/jquery.color.js [new file with mode: 0644]
resources/src/jquery.color/jquery.colorUtil.js [new file with mode: 0644]
resources/src/jquery/jquery.color.js [deleted file]
resources/src/jquery/jquery.colorUtil.js [deleted file]
tests/phpunit/includes/api/ApiRevisionDeleteTest.php
tests/phpunit/includes/block/BlockManagerTest.php
tests/phpunit/includes/user/UserTest.php
tests/qunit/QUnitTestResources.php

index 09195e1..07f52d0 100644 (file)
@@ -302,6 +302,7 @@ because of Phabricator reports.
   Use the mediawiki.String module instead.
 * mw.language.specialCharacters, deprecated in 1.33, has been removed.
   Use require( 'mediawiki.language.specialCharacters' ) instead.
+* The jquery.colorUtil module was removed. Use jquery.color instead.
 * EditPage::submit(), deprecated in 1.29, has been removed. Use $this->edit()
   directly.
 * HTMLForm::getErrors(), deprecated in 1.28, has been removed. Use
index c1f9037..5785873 100644 (file)
@@ -28,7 +28,7 @@
                "ext-xml": "*",
                "guzzlehttp/guzzle": "6.3.3",
                "liuggio/statsd-php-client": "1.0.18",
-               "oojs/oojs-ui": "0.34.0",
+               "oojs/oojs-ui": "0.34.1",
                "pear/mail": "1.4.1",
                "pear/mail_mime": "1.10.2",
                "pear/net_smtp": "1.8.1",
index 0b0aaf5..c7ad75c 100644 (file)
@@ -107,13 +107,10 @@ return [
        },
 
        'BlockManager' => function ( MediaWikiServices $services ) : BlockManager {
-               $context = RequestContext::getMain();
                return new BlockManager(
                        new ServiceOptions(
                                BlockManager::$constructorOptions, $services->getMainConfig()
                        ),
-                       $context->getUser(),
-                       $context->getRequest(),
                        $services->getPermissionManager()
                );
        },
index 1ee91c2..60b24f0 100644 (file)
@@ -38,12 +38,6 @@ class ApiRevisionDelete extends ApiBase {
                $user = $this->getUser();
                $this->checkUserRightsAny( RevisionDeleter::getRestriction( $params['type'] ) );
 
-               // @TODO Use PermissionManager::isBlockedFrom() instead.
-               $block = $user->getBlock();
-               if ( $block ) {
-                       $this->dieBlocked( $block );
-               }
-
                if ( !$params['ids'] ) {
                        $this->dieWithError( [ 'apierror-paramempty', 'ids' ], 'paramempty_ids' );
                }
@@ -97,6 +91,10 @@ class ApiRevisionDelete extends ApiBase {
                        $this->dieWithError( [ 'apierror-revdel-needtarget' ], 'needtarget' );
                }
 
+               if ( $this->getPermissionManager()->isBlockedFrom( $user, $targetObj ) ) {
+                       $this->dieBlocked( $user->getBlock() );
+               }
+
                $list = RevisionDeleter::createList(
                        $params['type'], $this->getContext(), $targetObj, $params['ids']
                );
index e27ebac..2e20529 100644 (file)
@@ -41,16 +41,6 @@ use Wikimedia\IPSet;
  * @since 1.34 Refactored from User and Block.
  */
 class BlockManager {
-       // TODO: This should be UserIdentity instead of User
-       /** @var User */
-       private $currentUser;
-
-       /** @var WebRequest */
-       private $currentRequest;
-
-       /** @var PermissionManager */
-       private $permissionManager;
-
        /**
         * TODO Make this a const when HHVM support is dropped (T192166)
         *
@@ -71,20 +61,14 @@ class BlockManager {
 
        /**
         * @param ServiceOptions $options
-        * @param User $currentUser
-        * @param WebRequest $currentRequest
         * @param PermissionManager $permissionManager
         */
        public function __construct(
                ServiceOptions $options,
-               User $currentUser,
-               WebRequest $currentRequest,
                PermissionManager $permissionManager
        ) {
                $options->assertRequiredOptions( self::$constructorOptions );
                $this->options = $options;
-               $this->currentUser = $currentUser;
-               $this->currentRequest = $currentRequest;
                $this->permissionManager = $permissionManager;
        }
 
@@ -93,51 +77,116 @@ class BlockManager {
         * return a composite block that combines the strictest features of the applicable
         * blocks.
         *
-        * TODO: $user should be UserIdentity instead of User
+        * Different blocks may be sought, depending on the user and their permissions. The
+        * user may be:
+        * (1) The global user (and can be affected by IP blocks). The global request object
+        * is needed for checking the IP address, the XFF header and the cookies.
+        * (2) The global user (and exempt from IP blocks). The global request object is
+        * needed for checking the cookies.
+        * (3) Another user (not the global user). No request object is available or needed;
+        * just look for a block against the user account.
+        *
+        * Cases #1 and #2 check whether the global user is blocked in practice; the block
+        * may due to their user account being blocked or to an IP address block or cookie
+        * block (or multiple of these). Case #3 simply checks whether a user's account is
+        * blocked, and does not determine whether the person using that account is affected
+        * in practice by any IP address or cookie blocks.
         *
         * @internal This should only be called by User::getBlockedStatus
         * @param User $user
+        * @param WebRequest|null $request The global request object if the user is the
+        *  global user (cases #1 and #2), otherwise null (case #3). The IP address and
+        *  information from the request header are needed to find some types of blocks.
         * @param bool $fromReplica Whether to check the replica DB first.
         *  To improve performance, non-critical checks are done against replica DBs.
         *  Check when actually saving should be done against master.
         * @return AbstractBlock|null The most relevant block, or null if there is no block.
         */
-       public function getUserBlock( User $user, $fromReplica ) {
-               $isAnon = $user->getId() === 0;
+       public function getUserBlock( User $user, $request, $fromReplica ) {
                $fromMaster = !$fromReplica;
+               $ip = null;
 
-               // TODO: If $user is the current user, we should use the current request. Otherwise,
-               // we should not look for XFF or cookie blocks.
-               $request = $user->getRequest();
+               // If this is the global user, they may be affected by IP blocks (case #1),
+               // or they may be exempt (case #2). If affected, look for additional blocks
+               // against the IP address.
+               $checkIpBlocks = $request &&
+                       !$this->permissionManager->userHasRight( $user, 'ipblock-exempt' );
 
-               # We only need to worry about passing the IP address to the block generator if the
-               # user is not immune to autoblocks/hardblocks, and they are the current user so we
-               # know which IP address they're actually coming from
-               $ip = null;
-               $sessionUser = $this->currentUser;
-               // the session user is set up towards the end of Setup.php. Until then,
-               // assume it's a logged-out user.
-               $globalUserName = $sessionUser->isSafeToLoad()
-                       ? $sessionUser->getName()
-                       : IP::sanitizeIP( $this->currentRequest->getIP() );
-               if ( $user->getName() === $globalUserName &&
-                        !$this->permissionManager->userHasRight( $user, 'ipblock-exempt' ) ) {
-                       $ip = $this->currentRequest->getIP();
+               if ( $request && $checkIpBlocks ) {
+
+                       // Case #1: checking the global user, including IP blocks
+                       $ip = $request->getIP();
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $blocks = DatabaseBlock::newListFromTarget( $user, $ip, $fromMaster );
+                       $this->getAdditionalIpBlocks( $blocks, $request, !$user->isRegistered(), $fromMaster );
+                       $this->getCookieBlock( $blocks, $user, $request );
+
+               } elseif ( $request ) {
+
+                       // Case #2: checking the global user, but they are exempt from IP blocks
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $blocks = DatabaseBlock::newListFromTarget( $user, null, $fromMaster );
+                       $this->getCookieBlock( $blocks, $user, $request );
+
+               } else {
+
+                       // Case #3: checking whether a user's account is blocked
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $blocks = DatabaseBlock::newListFromTarget( $user, null, $fromMaster );
+
+               }
+
+               // Filter out any duplicated blocks, e.g. from the cookie
+               $blocks = $this->getUniqueBlocks( $blocks );
+
+               $block = null;
+               if ( count( $blocks ) > 0 ) {
+                       if ( count( $blocks ) === 1 ) {
+                               $block = $blocks[ 0 ];
+                       } else {
+                               $block = new CompositeBlock( [
+                                       'address' => $ip,
+                                       'byText' => 'MediaWiki default',
+                                       'reason' => wfMessage( 'blockedtext-composite-reason' )->plain(),
+                                       'originalBlocks' => $blocks,
+                               ] );
+                       }
                }
 
-               // User/IP blocking
-               // After this, $blocks is an array of blocks or an empty array
-               // TODO: remove dependency on DatabaseBlock
-               $blocks = DatabaseBlock::newListFromTarget( $user, $ip, $fromMaster );
+               Hooks::run( 'GetUserBlock', [ clone $user, $ip, &$block ] );
+
+               return $block;
+       }
 
-               // Cookie blocking
+       /**
+        * Get the cookie block, if there is one.
+        *
+        * @param AbstractBlock[] &$blocks
+        * @param UserIdentity $user
+        * @param WebRequest $request
+        * @return void
+        */
+       private function getCookieBlock( &$blocks, UserIdentity $user, WebRequest $request ) {
                $cookieBlock = $this->getBlockFromCookieValue( $user, $request );
-               if ( $cookieBlock instanceof AbstractBlock ) {
+               if ( $cookieBlock instanceof DatabaseBlock ) {
                        $blocks[] = $cookieBlock;
                }
+       }
+
+       /**
+        * Check for any additional blocks against the IP address or any IPs in the XFF header.
+        *
+        * @param AbstractBlock[] &$blocks Blocks found so far
+        * @param WebRequest $request
+        * @param bool $isAnon The user is logged out
+        * @param bool $fromMaster
+        * @return void
+        */
+       private function getAdditionalIpBlocks( &$blocks, WebRequest $request, $isAnon, $fromMaster ) {
+               $ip = $request->getIP();
 
                // Proxy blocking
-               if ( $ip !== null && !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) ) ) {
+               if ( !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) ) ) {
                        // Local list
                        if ( $this->isLocallyBlockedProxy( $ip ) ) {
                                $blocks[] = new SystemBlock( [
@@ -156,24 +205,8 @@ class BlockManager {
                        }
                }
 
-               // (T25343) Apply IP blocks to the contents of XFF headers, if enabled
-               if ( $this->options->get( 'ApplyIpBlocksToXff' )
-                       && $ip !== null
-                       && !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) )
-               ) {
-                       $xff = $request->getHeader( 'X-Forwarded-For' );
-                       $xff = array_map( 'trim', explode( ',', $xff ) );
-                       $xff = array_diff( $xff, [ $ip ] );
-                       // TODO: remove dependency on DatabaseBlock
-                       $xffblocks = DatabaseBlock::getBlocksForIPList( $xff, $isAnon, $fromMaster );
-                       $blocks = array_merge( $blocks, $xffblocks );
-               }
-
                // Soft blocking
-               if ( $ip !== null
-                       && $isAnon
-                       && IP::isInRanges( $ip, $this->options->get( 'SoftBlockRanges' ) )
-               ) {
+               if ( $isAnon && IP::isInRanges( $ip, $this->options->get( 'SoftBlockRanges' ) ) ) {
                        $blocks[] = new SystemBlock( [
                                'address' => $ip,
                                'byText' => 'MediaWiki default',
@@ -183,26 +216,17 @@ class BlockManager {
                        ] );
                }
 
-               // Filter out any duplicated blocks, e.g. from the cookie
-               $blocks = $this->getUniqueBlocks( $blocks );
-
-               $block = null;
-               if ( count( $blocks ) > 0 ) {
-                       if ( count( $blocks ) === 1 ) {
-                               $block = $blocks[ 0 ];
-                       } else {
-                               $block = new CompositeBlock( [
-                                       'address' => $ip,
-                                       'byText' => 'MediaWiki default',
-                                       'reason' => wfMessage( 'blockedtext-composite-reason' )->plain(),
-                                       'originalBlocks' => $blocks,
-                               ] );
-                       }
+               // (T25343) Apply IP blocks to the contents of XFF headers, if enabled
+               if ( $this->options->get( 'ApplyIpBlocksToXff' )
+                       && !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) )
+               ) {
+                       $xff = $request->getHeader( 'X-Forwarded-For' );
+                       $xff = array_map( 'trim', explode( ',', $xff ) );
+                       $xff = array_diff( $xff, [ $ip ] );
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $xffblocks = DatabaseBlock::getBlocksForIPList( $xff, $isAnon, $fromMaster );
+                       $blocks = array_merge( $blocks, $xffblocks );
                }
-
-               Hooks::run( 'GetUserBlock', [ clone $user, $ip, &$block ] );
-
-               return $block;
        }
 
        /**
@@ -255,7 +279,7 @@ class BlockManager {
 
                $blockCookieId = $this->getIdFromCookieValue( $cookieValue );
                if ( !is_null( $blockCookieId ) ) {
-                       // TODO: remove dependency on DatabaseBlock
+                       // TODO: remove dependency on DatabaseBlock (T221075)
                        $block = DatabaseBlock::newFromID( $blockCookieId );
                        if (
                                $block instanceof DatabaseBlock &&
index a508746..84f6fc0 100644 (file)
@@ -50,7 +50,7 @@ class SearchUpdate implements DeferrableUpdate {
         */
        public function __construct( $id, $title, $c = null ) {
                if ( is_string( $title ) ) {
-                       wfDeprecated( __METHOD__ . " with a string for the title", 1.34 );
+                       wfDeprecated( __METHOD__ . " with a string for the title", '1.34' );
                        $this->title = Title::newFromText( $title );
                        if ( $this->title === null ) {
                                throw new InvalidArgumentException( "Cannot construct the title: $title" );
@@ -62,10 +62,10 @@ class SearchUpdate implements DeferrableUpdate {
                $this->id = $id;
                // is_string() check is back-compat for ApprovedRevs
                if ( is_string( $c ) ) {
-                       wfDeprecated( __METHOD__ . " with a string for the content", 1.34 );
+                       wfDeprecated( __METHOD__ . " with a string for the content", '1.34' );
                        $c = new TextContent( $c );
                } elseif ( is_bool( $c ) ) {
-                       wfDeprecated( __METHOD__ . " with a boolean for the content", 1.34 );
+                       wfDeprecated( __METHOD__ . " with a boolean for the content", '1.34' );
                        $c = null;
                }
                $this->content = $c;
index 5ac5f82..b83be91 100644 (file)
@@ -209,7 +209,12 @@ class SpecialPageFactory {
                'NewSection' => \SpecialNewSection::class,
                'PermanentLink' => \SpecialPermanentLink::class,
                'Redirect' => \SpecialRedirect::class,
-               'Revisiondelete' => \SpecialRevisionDelete::class,
+               'Revisiondelete' => [
+                       'class' => \SpecialRevisionDelete::class,
+                       'services' => [
+                               'PermissionManager',
+                       ],
+               ],
                'RunJobs' => \SpecialRunJobs::class,
                'Specialpages' => \SpecialSpecialpages::class,
                'PageData' => \SpecialPageData::class,
index 3c009c3..527b910 100644 (file)
@@ -39,6 +39,11 @@ class SpecialPagesWithProp extends QueryPage {
         */
        private $existingPropNames = null;
 
+       /**
+        * @var string|null
+        */
+       private $ns;
+
        /**
         * @var bool
         */
@@ -78,6 +83,13 @@ class SpecialPagesWithProp extends QueryPage {
                                'label-message' => 'pageswithprop-prop',
                                'required' => true,
                        ],
+                       'namespace' => [
+                               'type' => 'namespaceselect',
+                               'name' => 'namespace',
+                               'label-message' => 'namespace',
+                               'all' => null,
+                               'default' => null,
+                       ],
                        'reverse' => [
                                'type' => 'check',
                                'name' => 'reverse',
@@ -108,6 +120,7 @@ class SpecialPagesWithProp extends QueryPage {
 
        public function onSubmit( $data, $form ) {
                $this->propName = $data['propname'];
+               $this->ns = $data['namespace'];
                parent::execute( $data['propname'] );
        }
 
@@ -134,7 +147,7 @@ class SpecialPagesWithProp extends QueryPage {
        }
 
        public function getQueryInfo() {
-               return [
+               $query = [
                        'tables' => [ 'page_props', 'page' ],
                        'fields' => [
                                'page_id' => 'pp_page',
@@ -153,6 +166,12 @@ class SpecialPagesWithProp extends QueryPage {
                        ],
                        'options' => []
                ];
+
+               if ( $this->ns && isset( $this->ns ) ) {
+                       $query['conds']['page_namespace'] = $this->ns;
+               }
+
+               return $query;
        }
 
        function getOrderFields() {
index 7444225..437263f 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Permissions\PermissionManager;
 
 /**
  * Special page allowing users with the appropriate permissions to view
@@ -66,6 +67,9 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
        /** @var string */
        private $otherReason;
 
+       /** @var PermissionManager */
+       private $permissionManager;
+
        /**
         * UI labels for each type.
         */
@@ -107,8 +111,15 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                ],
        ];
 
-       public function __construct() {
+       /**
+        * @inheritDoc
+        *
+        * @param PermissionManager $permissionManager
+        */
+       public function __construct( PermissionManager $permissionManager ) {
                parent::__construct( 'Revisiondelete', 'deleterevision' );
+
+               $this->permissionManager = $permissionManager;
        }
 
        public function doesWrites() {
@@ -124,13 +135,6 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                $output = $this->getOutput();
                $user = $this->getUser();
 
-               // Check blocks
-               // @TODO Use PermissionManager::isBlockedFrom() instead.
-               $block = $user->getBlock();
-               if ( $block ) {
-                       throw new UserBlockedError( $block );
-               }
-
                $this->setHeaders();
                $this->outputHeader();
                $request = $this->getRequest();
@@ -180,6 +184,11 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        return;
                }
 
+               // Check blocks
+               if ( $this->permissionManager->isBlockedFrom( $user, $this->targetObj ) ) {
+                       throw new UserBlockedError( $user->getBlock() );
+               }
+
                $this->typeLabels = self::$UILabels[$this->typeName];
                $list = $this->getList();
                $list->reset();
index 375694b..530c580 100644 (file)
@@ -52,7 +52,8 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                }
 
                // Validate request parameters
-               $optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false, 'async' => true ];
+               $optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false,
+                       'async' => true, 'stats' => false ];
                $required = array_flip( [ 'title', 'tasks', 'signature', 'sigexpiry' ] );
                $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
                $missing = array_diff_key( $required, $params );
@@ -95,14 +96,20 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                                DeferredUpdates::POSTSEND
                        );
                } else {
-                       $this->doRun( $params );
-                       print "Done\n";
+                       $stats = $this->doRun( $params );
+
+                       if ( $params['stats'] ) {
+                               $this->getRequest()->response()->header( 'Content-Type: application/json' );
+                               print FormatJson::encode( $stats );
+                       } else {
+                               print "Done\n";
+                       }
                }
        }
 
        protected function doRun( array $params ) {
                $runner = new JobRunner( LoggerFactory::getInstance( 'runJobs' ) );
-               $runner->run( [
+               return $runner->run( [
                        'type'     => $params['type'],
                        'maxJobs'  => $params['maxjobs'] ?: 1,
                        'maxTime'  => $params['maxtime'] ?: 30
index 4445e1d..d71750b 100644 (file)
@@ -1718,9 +1718,31 @@ class User implements IDBAccessObject, UserIdentity {
                // overwriting mBlockedby, surely?
                $this->load();
 
+               // TODO: Block checking shouldn't really be done from the User object. Block
+               // checking can involve checking for IP blocks, cookie blocks, and/or XFF blocks,
+               // which need more knowledge of the request context than the User should have.
+               // Since we do currently check blocks from the User, we have to do the following
+               // here:
+               // - Check if this is the user associated with the main request
+               // - If so, pass the relevant request information to the block manager
+               $request = null;
+
+               // The session user is set up towards the end of Setup.php. Until then,
+               // assume it's a logged-out user.
+               $sessionUser = RequestContext::getMain()->getUser();
+               $globalUserName = $sessionUser->isSafeToLoad()
+                       ? $sessionUser->getName()
+                       : IP::sanitizeIP( $sessionUser->getRequest()->getIP() );
+
+               if ( $this->getName() === $globalUserName ) {
+                       // This is the global user, so we need to pass the request
+                       $request = $this->getRequest();
+               }
+
                // @phan-suppress-next-line PhanAccessMethodInternal It's the only allowed use
                $block = MediaWikiServices::getInstance()->getBlockManager()->getUserBlock(
                        $this,
+                       $request,
                        $fromReplica
                );
 
index 6ba7796..e675889 100644 (file)
@@ -12,7 +12,7 @@
        "--exclude": [
                "resources/src/jquery.tablesorter",
                "resources/src/jquery.tipsy",
-               "resources/src/jquery/jquery.color.js",
+               "resources/src/jquery.color/jquery.color.js",
                "resources/src/jquery/jquery.highlightText.js",
                "resources/src/jquery/jquery.mw-jump.js",
                "resources/src/mediawiki.base/legacy.wikibits.js",
index 0960e83..726a3fe 100644 (file)
@@ -175,11 +175,10 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.color' => [
-               'scripts' => 'resources/src/jquery/jquery.color.js',
-               'dependencies' => 'jquery.colorUtil',
-       ],
-       'jquery.colorUtil' => [
-               'scripts' => 'resources/src/jquery/jquery.colorUtil.js',
+               'scripts' => [
+                       'resources/src/jquery.color/jquery.colorUtil.js',
+                       'resources/src/jquery.color/jquery.color.js',
+               ],
        ],
        'jquery.confirmable' => [
                'scripts' => [
index 9ab1b49..5db52a4 100644 (file)
@@ -253,8 +253,8 @@ oojs-router:
 
 ooui:
   type: tar
-  src: https://registry.npmjs.org/oojs-ui/-/oojs-ui-0.34.0.tgz
-  integrity: sha384-DVG3XayKF02r0rqXSJUEWJImcK8XJeiIVC/Ii5R20cINYpTaAs+x4rdCU52VaKKw
+  src: https://registry.npmjs.org/oojs-ui/-/oojs-ui-0.34.1.tgz
+  integrity: sha384-QXYp5vK60xpu4nkv/JStszI6U4TYGCNe7uXb5rYb7FYURLTR41mtNO74gl7HXgpz
 
   dest:
     # Main stuff
index 9408e9b..501b768 100644 (file)
@@ -1,4 +1,16 @@
 # OOUI Release History
+## v0.34.1 / 2019-09-10
+### Deprecating changes
+* [DEPRECATING CHANGE] icons: Rename 'beaker' to 'labFlask' (Volker E.)
+
+### Styles
+* icons: Add 'userGroup' (Volker E.)
+
+### Code
+* Wrap long strings in popups (Sam Wilson)
+* demos: Add missing file to PHP demo to fix infusion (Bartosz DziewoÅ„ski)
+
+
 ## v0.34.0 / 2019-09-04
 ### Breaking changes
 * [BREAKING CHANGE] Use OOjs v3.0.0, up from v2.2.2 (James D. Forrester)
index 6bfe4d6..8595f61 100644 (file)
        "ooui-item-remove": "Supprimer",
        "ooui-dialog-message-accept": "OK",
        "ooui-dialog-message-reject": "Annuler",
-       "ooui-dialog-process-error": "Quelque chose s'est mal passé",
+       "ooui-dialog-process-error": "Quelque chose s’est mal passé",
        "ooui-dialog-process-dismiss": "Fermer",
        "ooui-dialog-process-retry": "Réessayer",
        "ooui-dialog-process-continue": "Continuer",
-       "ooui-combobox-button-label": "Liste déroulante de combobox",
+       "ooui-combobox-button-label": "Liste déroulante pour boîte de saisie",
        "ooui-selectfile-button-select": "Sélectionner un fichier",
        "ooui-selectfile-not-supported": "La sélection de fichier n’est pas prise en charge",
        "ooui-selectfile-placeholder": "Aucun fichier sélectionné",
index affc066..d13cb45 100644 (file)
@@ -18,7 +18,8 @@
                        "Gloria sah",
                        "Andrzej aa",
                        "The Polish",
-                       "Railfail536"
+                       "Railfail536",
+                       "Rail"
                ]
        },
        "ooui-outline-control-move-down": "PrzesuÅ„ w dół",
index d48a492..667f11e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index bb58190..e06ece0 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-element-hidden {
   display: none !important;
@@ -917,6 +917,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 .oo-ui-popupWidget-popup {
   position: relative;
   overflow: hidden;
+  word-wrap: break-word;
+  overflow-wrap: break-word;
 }
 .oo-ui-popupWidget-anchor {
   display: none;
index cfbf7d6..d4eaea5 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-element-hidden {
   display: none !important;
@@ -1059,6 +1059,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 .oo-ui-popupWidget-popup {
   position: relative;
   overflow: hidden;
+  word-wrap: break-word;
+  overflow-wrap: break-word;
 }
 .oo-ui-popupWidget-anchor {
   display: none;
index 11e132e..9754fb8 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index fda6a81..768d107 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-tool > .oo-ui-tool-link > .oo-ui-tool-checkIcon {
   display: none;
index c011942..5e8b9c9 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-tool {
   -webkit-box-sizing: border-box;
index 000b9eb..e8a571e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 854d8e3..f94e98b 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ).oo-ui-widget {
   cursor: move;
index 73da6f8..8bc82a8 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ).oo-ui-widget {
   cursor: move;
index bdf0d2f..7afac69 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 75f1acd..5355835 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 8ac442f..5a11914 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 
 .oo-ui-window {
index e406188..b1a067b 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 
 .oo-ui-window {
index 8885525..d8db8d1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 732d70f..516dc08 100644 (file)
@@ -15,7 +15,8 @@
                        "file": "../wikimediaui/images/icons/attachment.svg"
                },
                "beaker": {
-                       "file": "../wikimediaui/images/icons/beaker.svg"
+                       "file": "../wikimediaui/images/icons/labFlask.svg",
+                       "deprecated": "Renamed since v0.34.1, use 'labFlask' instead."
                },
                "calendar": {
                        "file": "../wikimediaui/images/icons/calendar.svg"
@@ -38,6 +39,9 @@
                "imageLayoutThumbnail": {
                        "file": "../wikimediaui/images/icons/imageLayoutThumbnail.svg"
                },
+               "labFlask": {
+                       "file": "../wikimediaui/images/icons/labFlask.svg"
+               },
                "language": {
                        "file": "../wikimediaui/images/icons/language.svg"
                },
index e13bb1d..de7a118 100644 (file)
                "userAvatarOutline": {
                        "file": "../wikimediaui/images/icons/userAvatarOutline.svg"
                },
+               "userGroup": {
+                       "file": {
+                               "ltr": "../wikimediaui/images/icons/userGroup-ltr.svg",
+                               "rtl": "../wikimediaui/images/icons/userGroup-rtl.svg"
+                       }
+               },
                "userTalk": {
                        "file": {
                                "ltr": "../wikimediaui/images/icons/userTalk-ltr.svg",
index 4f4fd4e..23dd607 100644 (file)
@@ -38,7 +38,8 @@
                        "file": "images/icons/attachment.svg"
                },
                "beaker": {
-                       "file": "images/icons/beaker.svg"
+                       "file": "images/icons/labFlask.svg",
+                       "deprecated": "Renamed since v0.34.1, use 'labFlask' instead."
                },
                "calendar": {
                        "file": "images/icons/calendar.svg"
@@ -61,6 +62,9 @@
                "imageLayoutThumbnail": {
                        "file": "images/icons/imageLayoutThumbnail.svg"
                },
+               "labFlask": {
+                       "file": "images/icons/labFlask.svg"
+               },
                "language": {
                        "file": "images/icons/language.svg"
                },
index 7266d34..5a382ce 100644 (file)
                "userAvatarOutline": {
                        "file": "images/icons/userAvatarOutline.svg"
                },
+               "userGroup": {
+                       "file": {
+                               "ltr": "images/icons/userGroup-ltr.svg",
+                               "rtl": "images/icons/userGroup-rtl.svg"
+                       }
+               },
                "userTalk": {
                        "file": {
                                "ltr": "images/icons/userTalk-ltr.svg",
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png
deleted file mode 100644 (file)
index 89d2d3d..0000000
Binary files a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png and /dev/null differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg
deleted file mode 100644 (file)
index c031daf..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
-       <title>
-               beaker
-       </title><g fill="#fff">
-       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
-</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png
deleted file mode 100644 (file)
index 78736ac..0000000
Binary files a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png and /dev/null differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg
deleted file mode 100644 (file)
index 1f8efbd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
-       <title>
-               beaker
-       </title><g fill="#36c">
-       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
-</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png
deleted file mode 100644 (file)
index 63a1a80..0000000
Binary files a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png and /dev/null differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg
deleted file mode 100644 (file)
index 7a37c5a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
-       <title>
-               beaker
-       </title>
-       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
-</svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png
new file mode 100644 (file)
index 0000000..89d2d3d
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg
new file mode 100644 (file)
index 0000000..bfb66da
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               laboratory flask
+       </title><g fill="#fff">
+       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png
new file mode 100644 (file)
index 0000000..78736ac
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg
new file mode 100644 (file)
index 0000000..1db0d6b
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               laboratory flask
+       </title><g fill="#36c">
+       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png
new file mode 100644 (file)
index 0000000..63a1a80
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg
new file mode 100644 (file)
index 0000000..c95a51a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               laboratory flask
+       </title>
+       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
+</svg>
index 3b5187d..268dc30 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
        <title>
                user avatar
index 047a18c..681a468 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
        <title>
                user avatar
index 7608cd2..8236235 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
        <title>
                user avatar
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png
new file mode 100644 (file)
index 0000000..bc9c111
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg
new file mode 100644 (file)
index 0000000..d05ad38
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#fff">
+       <path d="M14 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zM6 3c1.66 0 3 1.34 3 3S7.66 9 6 9 3 7.66 3 6s1.34-3 3-3zm8 7c3.31 0 6 1.79 6 4v2h-6v-2c0-1.48-1.21-2.77-3-3.46.88-.35 1.91-.54 3-.54zm-8 0c3.31 0 6 1.79 6 4v2H0v-2c0-2.21 2.69-4 6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png
new file mode 100644 (file)
index 0000000..5cd3d1c
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg
new file mode 100644 (file)
index 0000000..71d354a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#36c">
+       <path d="M14 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zM6 3c1.66 0 3 1.34 3 3S7.66 9 6 9 3 7.66 3 6s1.34-3 3-3zm8 7c3.31 0 6 1.79 6 4v2h-6v-2c0-1.48-1.21-2.77-3-3.46.88-.35 1.91-.54 3-.54zm-8 0c3.31 0 6 1.79 6 4v2H0v-2c0-2.21 2.69-4 6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png
new file mode 100644 (file)
index 0000000..43c0be2
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg
new file mode 100644 (file)
index 0000000..248d056
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title>
+       <path d="M14 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zM6 3c1.66 0 3 1.34 3 3S7.66 9 6 9 3 7.66 3 6s1.34-3 3-3zm8 7c3.31 0 6 1.79 6 4v2h-6v-2c0-1.48-1.21-2.77-3-3.46.88-.35 1.91-.54 3-.54zm-8 0c3.31 0 6 1.79 6 4v2H0v-2c0-2.21 2.69-4 6-4z"/>
+</svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png
new file mode 100644 (file)
index 0000000..2147e81
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg
new file mode 100644 (file)
index 0000000..5604358
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#fff">
+       <path d="M6 3C4.34 3 3 4.34 3 6s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-8 7c-3.31 0-6 1.79-6 4v2h6v-2c0-1.48 1.21-2.77 3-3.46-.88-.35-1.91-.54-3-.54zm8 0c-3.31 0-6 1.79-6 4v2h12v-2c0-2.21-2.69-4-6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png
new file mode 100644 (file)
index 0000000..d9082d3
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg
new file mode 100644 (file)
index 0000000..75436e9
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#36c">
+       <path d="M6 3C4.34 3 3 4.34 3 6s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-8 7c-3.31 0-6 1.79-6 4v2h6v-2c0-1.48 1.21-2.77 3-3.46-.88-.35-1.91-.54-3-.54zm8 0c-3.31 0-6 1.79-6 4v2h12v-2c0-2.21-2.69-4-6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png
new file mode 100644 (file)
index 0000000..4eedd2e
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg
new file mode 100644 (file)
index 0000000..5bd5bf5
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title>
+       <path d="M6 3C4.34 3 3 4.34 3 6s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-8 7c-3.31 0-6 1.79-6 4v2h6v-2c0-1.48 1.21-2.77 3-3.46-.88-.35-1.91-.54-3-.54zm8 0c-3.31 0-6 1.79-6 4v2h12v-2c0-2.21-2.69-4-6-4z"/>
+</svg>
diff --git a/resources/src/jquery.color/jquery.color.js b/resources/src/jquery.color/jquery.color.js
new file mode 100644 (file)
index 0000000..6df02ad
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * jQuery Color Animations
+ *
+ * @author John Resig, 2007
+ * @author Krinkle, 2011
+ * Released under the MIT and GPL licenses.
+ *
+ * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
+ */
+( function () {
+
+       function getColor( elem, attr ) {
+               var color;
+
+               do {
+                       color = $.css( elem, attr );
+
+                       // Keep going until we find an element that has color, or we hit the body
+                       if ( color !== '' && color !== 'transparent' || elem.nodeName.toLowerCase() === 'body' ) {
+                               break;
+                       }
+
+                       attr = 'backgroundColor';
+               // eslint-disable-next-line no-cond-assign
+               } while ( elem = elem.parentNode );
+
+               return $.colorUtil.getRGB( color );
+       }
+
+       // We override the animation for all of these color styles
+       [
+               'backgroundColor',
+               'borderBottomColor',
+               'borderLeftColor',
+               'borderRightColor',
+               'borderTopColor',
+               'color',
+               'outlineColor'
+       ].forEach( function ( attr ) {
+               $.fx.step[ attr ] = function ( fx ) {
+                       if ( !fx.colorInit ) {
+                               fx.start = getColor( fx.elem, attr );
+                               fx.end = $.colorUtil.getRGB( fx.end );
+                               fx.colorInit = true;
+                       }
+
+                       fx.elem.style[ attr ] = 'rgb(' + [
+                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 0 ] - fx.start[ 0 ] ) ) + fx.start[ 0 ], 10 ), 255 ), 0 ),
+                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 1 ] - fx.start[ 1 ] ) ) + fx.start[ 1 ], 10 ), 255 ), 0 ),
+                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 2 ] - fx.start[ 2 ] ) ) + fx.start[ 2 ], 10 ), 255 ), 0 )
+                       ].join( ',' ) + ')';
+               };
+       } );
+
+}() );
diff --git a/resources/src/jquery.color/jquery.colorUtil.js b/resources/src/jquery.color/jquery.colorUtil.js
new file mode 100644 (file)
index 0000000..009be1a
--- /dev/null
@@ -0,0 +1,268 @@
+/*!
+ * jQuery Color Utilities
+ *
+ * Released under the MIT and GPL licenses.
+ *
+ * Mostly based on other plugins and functions (linted and optimized a little).
+ * Sources cited inline.
+ */
+( function () {
+       /**
+        * @class jQuery.colorUtil
+        * @singleton
+        */
+       $.colorUtil = {
+
+               /**
+                * Parse CSS color strings looking for color tuples
+                *
+                * Based on highlightFade by Blair Mitchelmore
+                * <http://jquery.offput.ca/highlightFade/>
+                *
+                * @param {Array|string} color
+                * @return {Array}
+                */
+               getRGB: function ( color ) {
+                       var result;
+
+                       // Check if we're already dealing with an array of colors
+                       if ( color && Array.isArray( color ) && color.length === 3 ) {
+                               return color;
+                       }
+                       if ( typeof color !== 'string' ) {
+                               return undefined;
+                       }
+
+                       // Look for rgb(num,num,num)
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec( color ) ) {
+                               return [
+                                       parseInt( result[ 1 ], 10 ),
+                                       parseInt( result[ 2 ], 10 ),
+                                       parseInt( result[ 3 ], 10 )
+                               ];
+                       }
+
+                       // Look for rgb(num%,num%,num%)
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*\)/.exec( color ) ) {
+                               return [
+                                       parseFloat( result[ 1 ] ) * 2.55,
+                                       parseFloat( result[ 2 ] ) * 2.55,
+                                       parseFloat( result[ 3 ] ) * 2.55
+                               ];
+                       }
+
+                       // Look for #a0b1c2
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec( color ) ) {
+                               return [
+                                       parseInt( result[ 1 ], 16 ),
+                                       parseInt( result[ 2 ], 16 ),
+                                       parseInt( result[ 3 ], 16 )
+                               ];
+                       }
+
+                       // Look for #fff
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec( color ) ) {
+                               return [
+                                       parseInt( result[ 1 ] + result[ 1 ], 16 ),
+                                       parseInt( result[ 2 ] + result[ 2 ], 16 ),
+                                       parseInt( result[ 3 ] + result[ 3 ], 16 )
+                               ];
+                       }
+
+                       // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /rgba\(0, 0, 0, 0\)/.exec( color ) ) {
+                               return $.colorUtil.colors.transparent;
+                       }
+
+                       // Otherwise, we're most likely dealing with a named color
+                       return $.colorUtil.colors[ color.trim().toLowerCase() ];
+               },
+
+               /**
+                * Named color map
+                *
+                * Based on Interface by Stefan Petre
+                * <http://interface.eyecon.ro/>
+                *
+                * @property {Object}
+                */
+               colors: {
+                       aqua: [ 0, 255, 255 ],
+                       azure: [ 240, 255, 255 ],
+                       beige: [ 245, 245, 220 ],
+                       black: [ 0, 0, 0 ],
+                       blue: [ 0, 0, 255 ],
+                       brown: [ 165, 42, 42 ],
+                       cyan: [ 0, 255, 255 ],
+                       darkblue: [ 0, 0, 139 ],
+                       darkcyan: [ 0, 139, 139 ],
+                       darkgrey: [ 169, 169, 169 ],
+                       darkgreen: [ 0, 100, 0 ],
+                       darkkhaki: [ 189, 183, 107 ],
+                       darkmagenta: [ 139, 0, 139 ],
+                       darkolivegreen: [ 85, 107, 47 ],
+                       darkorange: [ 255, 140, 0 ],
+                       darkorchid: [ 153, 50, 204 ],
+                       darkred: [ 139, 0, 0 ],
+                       darksalmon: [ 233, 150, 122 ],
+                       darkviolet: [ 148, 0, 211 ],
+                       fuchsia: [ 255, 0, 255 ],
+                       gold: [ 255, 215, 0 ],
+                       green: [ 0, 128, 0 ],
+                       indigo: [ 75, 0, 130 ],
+                       khaki: [ 240, 230, 140 ],
+                       lightblue: [ 173, 216, 230 ],
+                       lightcyan: [ 224, 255, 255 ],
+                       lightgreen: [ 144, 238, 144 ],
+                       lightgrey: [ 211, 211, 211 ],
+                       lightpink: [ 255, 182, 193 ],
+                       lightyellow: [ 255, 255, 224 ],
+                       lime: [ 0, 255, 0 ],
+                       magenta: [ 255, 0, 255 ],
+                       maroon: [ 128, 0, 0 ],
+                       navy: [ 0, 0, 128 ],
+                       olive: [ 128, 128, 0 ],
+                       orange: [ 255, 165, 0 ],
+                       pink: [ 255, 192, 203 ],
+                       purple: [ 128, 0, 128 ],
+                       violet: [ 128, 0, 128 ],
+                       red: [ 255, 0, 0 ],
+                       silver: [ 192, 192, 192 ],
+                       white: [ 255, 255, 255 ],
+                       yellow: [ 255, 255, 0 ],
+                       transparent: [ 255, 255, 255 ]
+               },
+
+               /**
+                * Convert an RGB color value to HSL.
+                *
+                * Conversion formula based on
+                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
+                *
+                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
+                *
+                * Assumes `r`, `g`, and `b` are contained in the set `[0, 255]` and
+                * returns `h`, `s`, and `l` in the set `[0, 1]`.
+                *
+                * @param {number} r The red color value
+                * @param {number} g The green color value
+                * @param {number} b The blue color value
+                * @return {number[]} The HSL representation
+                */
+               rgbToHsl: function ( r, g, b ) {
+                       var d, h, s, l, min, max;
+
+                       r = r / 255;
+                       g = g / 255;
+                       b = b / 255;
+
+                       max = Math.max( r, g, b );
+                       min = Math.min( r, g, b );
+                       l = ( max + min ) / 2;
+
+                       if ( max === min ) {
+                               // achromatic
+                               h = s = 0;
+                       } else {
+                               d = max - min;
+                               s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min );
+                               switch ( max ) {
+                                       case r:
+                                               h = ( g - b ) / d + ( g < b ? 6 : 0 );
+                                               break;
+                                       case g:
+                                               h = ( b - r ) / d + 2;
+                                               break;
+                                       case b:
+                                               h = ( r - g ) / d + 4;
+                                               break;
+                               }
+                               h /= 6;
+                       }
+
+                       return [ h, s, l ];
+               },
+
+               /**
+                * Convert an HSL color value to RGB.
+                *
+                * Conversion formula based on
+                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
+                *
+                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
+                *
+                * Assumes `h`, `s`, and `l` are contained in the set `[0, 1]` and
+                * returns `r`, `g`, and `b` in the set `[0, 255]`.
+                *
+                * @param {number} h The hue
+                * @param {number} s The saturation
+                * @param {number} l The lightness
+                * @return {number[]} The RGB representation
+                */
+               hslToRgb: function ( h, s, l ) {
+                       var r, g, b, hue2rgb, q, p;
+
+                       if ( s === 0 ) {
+                               r = g = b = l; // achromatic
+                       } else {
+                               hue2rgb = function ( p, q, t ) {
+                                       if ( t < 0 ) {
+                                               t += 1;
+                                       }
+                                       if ( t > 1 ) {
+                                               t -= 1;
+                                       }
+                                       if ( t < 1 / 6 ) {
+                                               return p + ( q - p ) * 6 * t;
+                                       }
+                                       if ( t < 1 / 2 ) {
+                                               return q;
+                                       }
+                                       if ( t < 2 / 3 ) {
+                                               return p + ( q - p ) * ( 2 / 3 - t ) * 6;
+                                       }
+                                       return p;
+                               };
+
+                               q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s;
+                               p = 2 * l - q;
+                               r = hue2rgb( p, q, h + 1 / 3 );
+                               g = hue2rgb( p, q, h );
+                               b = hue2rgb( p, q, h - 1 / 3 );
+                       }
+
+                       return [ r * 255, g * 255, b * 255 ];
+               },
+
+               /**
+                * Get a brighter or darker rgb() value string.
+                *
+                * Usage:
+                *
+                *     $.colorUtil.getColorBrightness( 'red', +0.1 );
+                *     // > "rgb(255,50,50)"
+                *     $.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
+                *     // > "rgb(118,29,29)"
+                *
+                * @param {Mixed} currentColor Current value in css
+                * @param {number} mod Wanted brightness modification between -1 and 1
+                * @return {string} Like `'rgb(r,g,b)'`
+                */
+               getColorBrightness: function ( currentColor, mod ) {
+                       var rgbArr = $.colorUtil.getRGB( currentColor ),
+                               hslArr = $.colorUtil.rgbToHsl( rgbArr[ 0 ], rgbArr[ 1 ], rgbArr[ 2 ] );
+                       rgbArr = $.colorUtil.hslToRgb( hslArr[ 0 ], hslArr[ 1 ], hslArr[ 2 ] + mod );
+
+                       return 'rgb(' +
+                               [ parseInt( rgbArr[ 0 ], 10 ), parseInt( rgbArr[ 1 ], 10 ), parseInt( rgbArr[ 2 ], 10 ) ].join( ',' ) +
+                               ')';
+               }
+
+       };
+
+}() );
diff --git a/resources/src/jquery/jquery.color.js b/resources/src/jquery/jquery.color.js
deleted file mode 100644 (file)
index 6df02ad..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * jQuery Color Animations
- *
- * @author John Resig, 2007
- * @author Krinkle, 2011
- * Released under the MIT and GPL licenses.
- *
- * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
- */
-( function () {
-
-       function getColor( elem, attr ) {
-               var color;
-
-               do {
-                       color = $.css( elem, attr );
-
-                       // Keep going until we find an element that has color, or we hit the body
-                       if ( color !== '' && color !== 'transparent' || elem.nodeName.toLowerCase() === 'body' ) {
-                               break;
-                       }
-
-                       attr = 'backgroundColor';
-               // eslint-disable-next-line no-cond-assign
-               } while ( elem = elem.parentNode );
-
-               return $.colorUtil.getRGB( color );
-       }
-
-       // We override the animation for all of these color styles
-       [
-               'backgroundColor',
-               'borderBottomColor',
-               'borderLeftColor',
-               'borderRightColor',
-               'borderTopColor',
-               'color',
-               'outlineColor'
-       ].forEach( function ( attr ) {
-               $.fx.step[ attr ] = function ( fx ) {
-                       if ( !fx.colorInit ) {
-                               fx.start = getColor( fx.elem, attr );
-                               fx.end = $.colorUtil.getRGB( fx.end );
-                               fx.colorInit = true;
-                       }
-
-                       fx.elem.style[ attr ] = 'rgb(' + [
-                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 0 ] - fx.start[ 0 ] ) ) + fx.start[ 0 ], 10 ), 255 ), 0 ),
-                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 1 ] - fx.start[ 1 ] ) ) + fx.start[ 1 ], 10 ), 255 ), 0 ),
-                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 2 ] - fx.start[ 2 ] ) ) + fx.start[ 2 ], 10 ), 255 ), 0 )
-                       ].join( ',' ) + ')';
-               };
-       } );
-
-}() );
diff --git a/resources/src/jquery/jquery.colorUtil.js b/resources/src/jquery/jquery.colorUtil.js
deleted file mode 100644 (file)
index 009be1a..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*!
- * jQuery Color Utilities
- *
- * Released under the MIT and GPL licenses.
- *
- * Mostly based on other plugins and functions (linted and optimized a little).
- * Sources cited inline.
- */
-( function () {
-       /**
-        * @class jQuery.colorUtil
-        * @singleton
-        */
-       $.colorUtil = {
-
-               /**
-                * Parse CSS color strings looking for color tuples
-                *
-                * Based on highlightFade by Blair Mitchelmore
-                * <http://jquery.offput.ca/highlightFade/>
-                *
-                * @param {Array|string} color
-                * @return {Array}
-                */
-               getRGB: function ( color ) {
-                       var result;
-
-                       // Check if we're already dealing with an array of colors
-                       if ( color && Array.isArray( color ) && color.length === 3 ) {
-                               return color;
-                       }
-                       if ( typeof color !== 'string' ) {
-                               return undefined;
-                       }
-
-                       // Look for rgb(num,num,num)
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec( color ) ) {
-                               return [
-                                       parseInt( result[ 1 ], 10 ),
-                                       parseInt( result[ 2 ], 10 ),
-                                       parseInt( result[ 3 ], 10 )
-                               ];
-                       }
-
-                       // Look for rgb(num%,num%,num%)
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*\)/.exec( color ) ) {
-                               return [
-                                       parseFloat( result[ 1 ] ) * 2.55,
-                                       parseFloat( result[ 2 ] ) * 2.55,
-                                       parseFloat( result[ 3 ] ) * 2.55
-                               ];
-                       }
-
-                       // Look for #a0b1c2
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec( color ) ) {
-                               return [
-                                       parseInt( result[ 1 ], 16 ),
-                                       parseInt( result[ 2 ], 16 ),
-                                       parseInt( result[ 3 ], 16 )
-                               ];
-                       }
-
-                       // Look for #fff
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec( color ) ) {
-                               return [
-                                       parseInt( result[ 1 ] + result[ 1 ], 16 ),
-                                       parseInt( result[ 2 ] + result[ 2 ], 16 ),
-                                       parseInt( result[ 3 ] + result[ 3 ], 16 )
-                               ];
-                       }
-
-                       // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /rgba\(0, 0, 0, 0\)/.exec( color ) ) {
-                               return $.colorUtil.colors.transparent;
-                       }
-
-                       // Otherwise, we're most likely dealing with a named color
-                       return $.colorUtil.colors[ color.trim().toLowerCase() ];
-               },
-
-               /**
-                * Named color map
-                *
-                * Based on Interface by Stefan Petre
-                * <http://interface.eyecon.ro/>
-                *
-                * @property {Object}
-                */
-               colors: {
-                       aqua: [ 0, 255, 255 ],
-                       azure: [ 240, 255, 255 ],
-                       beige: [ 245, 245, 220 ],
-                       black: [ 0, 0, 0 ],
-                       blue: [ 0, 0, 255 ],
-                       brown: [ 165, 42, 42 ],
-                       cyan: [ 0, 255, 255 ],
-                       darkblue: [ 0, 0, 139 ],
-                       darkcyan: [ 0, 139, 139 ],
-                       darkgrey: [ 169, 169, 169 ],
-                       darkgreen: [ 0, 100, 0 ],
-                       darkkhaki: [ 189, 183, 107 ],
-                       darkmagenta: [ 139, 0, 139 ],
-                       darkolivegreen: [ 85, 107, 47 ],
-                       darkorange: [ 255, 140, 0 ],
-                       darkorchid: [ 153, 50, 204 ],
-                       darkred: [ 139, 0, 0 ],
-                       darksalmon: [ 233, 150, 122 ],
-                       darkviolet: [ 148, 0, 211 ],
-                       fuchsia: [ 255, 0, 255 ],
-                       gold: [ 255, 215, 0 ],
-                       green: [ 0, 128, 0 ],
-                       indigo: [ 75, 0, 130 ],
-                       khaki: [ 240, 230, 140 ],
-                       lightblue: [ 173, 216, 230 ],
-                       lightcyan: [ 224, 255, 255 ],
-                       lightgreen: [ 144, 238, 144 ],
-                       lightgrey: [ 211, 211, 211 ],
-                       lightpink: [ 255, 182, 193 ],
-                       lightyellow: [ 255, 255, 224 ],
-                       lime: [ 0, 255, 0 ],
-                       magenta: [ 255, 0, 255 ],
-                       maroon: [ 128, 0, 0 ],
-                       navy: [ 0, 0, 128 ],
-                       olive: [ 128, 128, 0 ],
-                       orange: [ 255, 165, 0 ],
-                       pink: [ 255, 192, 203 ],
-                       purple: [ 128, 0, 128 ],
-                       violet: [ 128, 0, 128 ],
-                       red: [ 255, 0, 0 ],
-                       silver: [ 192, 192, 192 ],
-                       white: [ 255, 255, 255 ],
-                       yellow: [ 255, 255, 0 ],
-                       transparent: [ 255, 255, 255 ]
-               },
-
-               /**
-                * Convert an RGB color value to HSL.
-                *
-                * Conversion formula based on
-                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
-                *
-                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
-                *
-                * Assumes `r`, `g`, and `b` are contained in the set `[0, 255]` and
-                * returns `h`, `s`, and `l` in the set `[0, 1]`.
-                *
-                * @param {number} r The red color value
-                * @param {number} g The green color value
-                * @param {number} b The blue color value
-                * @return {number[]} The HSL representation
-                */
-               rgbToHsl: function ( r, g, b ) {
-                       var d, h, s, l, min, max;
-
-                       r = r / 255;
-                       g = g / 255;
-                       b = b / 255;
-
-                       max = Math.max( r, g, b );
-                       min = Math.min( r, g, b );
-                       l = ( max + min ) / 2;
-
-                       if ( max === min ) {
-                               // achromatic
-                               h = s = 0;
-                       } else {
-                               d = max - min;
-                               s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min );
-                               switch ( max ) {
-                                       case r:
-                                               h = ( g - b ) / d + ( g < b ? 6 : 0 );
-                                               break;
-                                       case g:
-                                               h = ( b - r ) / d + 2;
-                                               break;
-                                       case b:
-                                               h = ( r - g ) / d + 4;
-                                               break;
-                               }
-                               h /= 6;
-                       }
-
-                       return [ h, s, l ];
-               },
-
-               /**
-                * Convert an HSL color value to RGB.
-                *
-                * Conversion formula based on
-                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
-                *
-                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
-                *
-                * Assumes `h`, `s`, and `l` are contained in the set `[0, 1]` and
-                * returns `r`, `g`, and `b` in the set `[0, 255]`.
-                *
-                * @param {number} h The hue
-                * @param {number} s The saturation
-                * @param {number} l The lightness
-                * @return {number[]} The RGB representation
-                */
-               hslToRgb: function ( h, s, l ) {
-                       var r, g, b, hue2rgb, q, p;
-
-                       if ( s === 0 ) {
-                               r = g = b = l; // achromatic
-                       } else {
-                               hue2rgb = function ( p, q, t ) {
-                                       if ( t < 0 ) {
-                                               t += 1;
-                                       }
-                                       if ( t > 1 ) {
-                                               t -= 1;
-                                       }
-                                       if ( t < 1 / 6 ) {
-                                               return p + ( q - p ) * 6 * t;
-                                       }
-                                       if ( t < 1 / 2 ) {
-                                               return q;
-                                       }
-                                       if ( t < 2 / 3 ) {
-                                               return p + ( q - p ) * ( 2 / 3 - t ) * 6;
-                                       }
-                                       return p;
-                               };
-
-                               q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s;
-                               p = 2 * l - q;
-                               r = hue2rgb( p, q, h + 1 / 3 );
-                               g = hue2rgb( p, q, h );
-                               b = hue2rgb( p, q, h - 1 / 3 );
-                       }
-
-                       return [ r * 255, g * 255, b * 255 ];
-               },
-
-               /**
-                * Get a brighter or darker rgb() value string.
-                *
-                * Usage:
-                *
-                *     $.colorUtil.getColorBrightness( 'red', +0.1 );
-                *     // > "rgb(255,50,50)"
-                *     $.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
-                *     // > "rgb(118,29,29)"
-                *
-                * @param {Mixed} currentColor Current value in css
-                * @param {number} mod Wanted brightness modification between -1 and 1
-                * @return {string} Like `'rgb(r,g,b)'`
-                */
-               getColorBrightness: function ( currentColor, mod ) {
-                       var rgbArr = $.colorUtil.getRGB( currentColor ),
-                               hslArr = $.colorUtil.rgbToHsl( rgbArr[ 0 ], rgbArr[ 1 ], rgbArr[ 2 ] );
-                       rgbArr = $.colorUtil.hslToRgb( hslArr[ 0 ], hslArr[ 1 ], hslArr[ 2 ] + mod );
-
-                       return 'rgb(' +
-                               [ parseInt( rgbArr[ 0 ], 10 ), parseInt( rgbArr[ 1 ], 10 ), parseInt( rgbArr[ 2 ], 10 ) ].join( ',' ) +
-                               ')';
-               }
-
-       };
-
-}() );
index 5dcea65..7dc63fb 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\Block\Restriction\PageRestriction;
+
 /**
  * Tests for action=revisiondelete
  * @covers APIRevisionDelete
@@ -113,4 +116,32 @@ class ApiRevisionDeleteTest extends ApiTestCase {
                $this->assertTrue( $item['texthidden'], 'texthidden' );
                $this->assertEquals( $item['id'], $revid );
        }
+
+       public function testPartiallyBlockedPage() {
+               $this->setExpectedApiException( 'apierror-blocked-partial' );
+
+               $user = static::getTestSysop()->getUser();
+
+               $block = new DatabaseBlock( [
+                       'address' => $user,
+                       'by' => static::getTestSysop()->getUser()->getId(),
+                       'sitewide' => false,
+               ] );
+
+               $block->setRestrictions( [
+                       new PageRestriction( 0, Title::newFromText( self::$page )->getArticleID() )
+               ] );
+               $block->insert();
+
+               $revid = array_shift( $this->revs );
+
+               $this->doApiRequest( [
+                       'action' => 'revisiondelete',
+                       'type' => 'revision',
+                       'target' => self::$page,
+                       'ids' => $revid,
+                       'hide' => 'content|user|comment',
+                       'token' => $user->getEditToken(),
+               ] );
+       }
 }
index d4133b7..6a00e67 100644 (file)
@@ -54,8 +54,6 @@ class BlockManagerTest extends MediaWikiTestCase {
                                BlockManager::$constructorOptions,
                                MediaWikiServices::getInstance()->getMainConfig()
                        ),
-                       $this->user,
-                       $this->user->getRequest(),
                        MediaWikiServices::getInstance()->getPermissionManager()
                ];
        }
index 3005ae9..2a4ba4b 100644 (file)
@@ -1488,10 +1488,6 @@ class UserTest extends MediaWikiTestCase {
                // logged in users should be inmune to cookie block of type ip/range
                $this->assertNull( $user->getBlock() );
 
-               // cookie is being cleared
-               $cookies = $request->response()->getCookies();
-               $this->assertEquals( '', $cookies['wikiBlockID']['value'] );
-
                // clean up
                $block->delete();
        }
index cab6c3b..a3a165f 100644 (file)
@@ -102,7 +102,6 @@ return [
                ],
                'dependencies' => [
                        'jquery.color',
-                       'jquery.colorUtil',
                        'jquery.getAttrs',
                        'jquery.highlightText',
                        'jquery.lengthLimit',