Merge "Make LBFactory return type docs more specific to avoid IDEA warnings"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 29 Sep 2016 02:45:29 +0000 (02:45 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 29 Sep 2016 02:45:29 +0000 (02:45 +0000)
12 files changed:
includes/MediaWikiServices.php
includes/Sanitizer.php
includes/ServiceWiring.php
includes/api/ApiContinuationManager.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllRevisions.php
includes/api/ApiQueryRecentChanges.php
includes/objectcache/ObjectCache.php
load.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/SanitizerTest.php

index b16044e..199472a 100644 (file)
@@ -589,6 +589,30 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'TitleParser' );
        }
 
+       /**
+        * @since 1.28
+        * @return \BagOStuff
+        */
+       public function getMainObjectStash() {
+               return $this->getService( 'MainObjectStash' );
+       }
+
+       /**
+        * @since 1.28
+        * @return \WANObjectCache
+        */
+       public function getMainWANObjectCache() {
+               return $this->getService( 'MainWANObjectCache' );
+       }
+
+       /**
+        * @since 1.28
+        * @return \BagOStuff
+        */
+       public function getLocalServerObjectCache() {
+               return $this->getService( 'LocalServerObjectCache' );
+       }
+
        /**
         * @since 1.28
         * @return VirtualRESTServiceClient
index c81c7bb..4069658 100644 (file)
@@ -1015,6 +1015,7 @@ class Sanitizer {
                                | url\s*\(
                                | image\s*\(
                                | image-set\s*\(
+                               | attr\s*\([^)]+[\s,]+url
                        !ix', $value ) ) {
                        return '/* insecure input */';
                }
index 6044911..0e4daa6 100644 (file)
@@ -218,6 +218,59 @@ return [
                return $services->getService( '_MediaWikiTitleCodec' );
        },
 
+       'MainObjectStash' => function( MediaWikiServices $services ) {
+               $mainConfig = $services->getMainConfig();
+
+               $id = $mainConfig->get( 'MainStash' );
+               if ( !isset( $mainConfig->get( 'ObjectCaches' )[$id] ) ) {
+                       throw new UnexpectedValueException(
+                               "Cache type \"$id\" is not present in \$wgObjectCaches." );
+               }
+
+               return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] );
+       },
+
+       'MainWANObjectCache' => function( MediaWikiServices $services ) {
+               $mainConfig = $services->getMainConfig();
+
+               $id = $mainConfig->get( 'MainWANCache' );
+               if ( !isset( $mainConfig->get( 'WANObjectCaches' )[$id] ) ) {
+                       throw new UnexpectedValueException(
+                               "WAN cache type \"$id\" is not present in \$wgWANObjectCaches." );
+               }
+
+               $params = $mainConfig->get( 'WANObjectCaches' )[$id];
+               $objectCacheId = $params['cacheId'];
+               if ( !isset( $mainConfig->get( 'ObjectCaches' )[$objectCacheId] ) ) {
+                       throw new UnexpectedValueException(
+                               "Cache type \"$objectCacheId\" is not present in \$wgObjectCaches." );
+               }
+               $params['store'] = $mainConfig->get( 'ObjectCaches' )[$objectCacheId];
+
+               return \ObjectCache::newWANCacheFromParams( $params );
+       },
+
+       'LocalServerObjectCache' => function( MediaWikiServices $services ) {
+               $mainConfig = $services->getMainConfig();
+
+               if ( function_exists( 'apc_fetch' ) ) {
+                       $id = 'apc';
+               } elseif ( function_exists( 'xcache_get' ) && wfIniGetBool( 'xcache.var_size' ) ) {
+                       $id = 'xcache';
+               } elseif ( function_exists( 'wincache_ucache_get' ) ) {
+                       $id = 'wincache';
+               } else {
+                       $id = CACHE_NONE;
+               }
+
+               if ( !isset( $mainConfig->get( 'ObjectCaches' )[$id] ) ) {
+                       throw new UnexpectedValueException(
+                               "Cache type \"$id\" is not present in \$wgObjectCaches." );
+               }
+
+               return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] );
+       },
+
        'VirtualRESTServiceClient' => function( MediaWikiServices $services ) {
                $config = $services->getMainConfig()->get( 'VirtualRestConfig' );
 
index 6601fb7..19e2453 100644 (file)
@@ -31,6 +31,7 @@ class ApiContinuationManager {
 
        private $continuationData = [];
        private $generatorContinuationData = [];
+       private $generatorNonContinuationData = [];
 
        private $generatorParams = [];
        private $generatorDone = false;
@@ -142,6 +143,26 @@ class ApiContinuationManager {
                $this->continuationData[$name][$paramName] = $paramValue;
        }
 
+       /**
+        * Set the non-continuation parameter for the generator module
+        *
+        * In case the generator isn't going to be continued, this sets the fields
+        * to return.
+        *
+        * @since 1.28
+        * @param ApiBase $module
+        * @param string $paramName
+        * @param string|array $paramValue
+        */
+       public function addGeneratorNonContinueParam( ApiBase $module, $paramName, $paramValue ) {
+               $name = $module->getModuleName();
+               $paramName = $module->encodeParamName( $paramName );
+               if ( is_array( $paramValue ) ) {
+                       $paramValue = implode( '|', $paramValue );
+               }
+               $this->generatorNonContinuationData[$name][$paramName] = $paramValue;
+       }
+
        /**
         * Set the continuation parameter for the generator module
         * @param ApiBase $module
@@ -165,6 +186,15 @@ class ApiContinuationManager {
                return array_merge_recursive( $this->continuationData, $this->generatorContinuationData );
        }
 
+       /**
+        * Fetch raw non-continuation data
+        * @since 1.28
+        * @return array
+        */
+       public function getRawNonContinuation() {
+               return $this->generatorNonContinuationData;
+       }
+
        /**
         * Fetch continuation result data
         * @return array [ (array)$data, (bool)$batchcomplete ]
@@ -192,8 +222,13 @@ class ApiContinuationManager {
                        foreach ( $continuationData as $module => $kvp ) {
                                $data += $kvp;
                        }
-                       $data += $this->generatorParams;
-                       $generatorKeys = implode( '|', array_keys( $this->generatorParams ) );
+                       $generatorParams = [];
+                       foreach ( $this->generatorNonContinuationData as $kvp ) {
+                               $generatorParams += $kvp;
+                       }
+                       $generatorParams += $this->generatorParams;
+                       $data += $generatorParams;
+                       $generatorKeys = implode( '|', array_keys( $generatorParams ) );
                } elseif ( $this->generatorContinuationData ) {
                        // All the generator-using modules are complete, but the
                        // generator isn't. Continue the generator and restart the
index 5e3c709..e8aa655 100644 (file)
@@ -258,6 +258,11 @@ class ApiQuery extends ApiBase {
                // Write the continuation data into the result
                $this->setContinuationManager( null );
                if ( $this->mParams['rawcontinue'] ) {
+                       $data = $continuationManager->getRawNonContinuation();
+                       if ( $data ) {
+                               $this->getResult()->addValue( null, 'query-noncontinue', $data,
+                                       ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
+                       }
                        $data = $continuationManager->getRawContinuation();
                        if ( $data ) {
                                $this->getResult()->addValue( null, 'query-continue', $data,
index 060e3e1..d548c46 100644 (file)
@@ -172,6 +172,13 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase {
                $nextIndex = 0;
                $generated = [];
                foreach ( $res as $row ) {
+                       if ( $count === 0 && $resultPageSet !== null ) {
+                               // Set the non-continue since the list of all revisions is
+                               // prone to having entries added at the start frequently.
+                               $this->getContinuationManager()->addGeneratorNonContinueParam(
+                                       $this, 'continue', "$row->rev_timestamp|$row->rev_id"
+                               );
+                       }
                        if ( ++$count > $this->limit ) {
                                // We've had enough
                                $this->setContinueEnumParameter( 'continue', "$row->rev_timestamp|$row->rev_id" );
index cc3ca60..c4c8afb 100644 (file)
@@ -372,6 +372,13 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                /* Iterate through the rows, adding data extracted from them to our query result. */
                foreach ( $res as $row ) {
+                       if ( $count === 0 && $resultPageSet !== null ) {
+                               // Set the non-continue since the list of recentchanges is
+                               // prone to having entries added at the start frequently.
+                               $this->getContinuationManager()->addGeneratorNonContinueParam(
+                                       $this, 'continue', "$row->rc_timestamp|$row->rc_id"
+                               );
+                       }
                        if ( ++$count > $params['limit'] ) {
                                // We've reached the one extra which shows that there are
                                // additional pages to be had. Stop here...
index d81f9e1..0f18479 100644 (file)
@@ -274,27 +274,18 @@ class ObjectCache {
         *     // From $wgObjectCaches via newFromParams()
         *     ObjectCache::getLocalServerInstance( [ 'fallback' => $fallbackType ] );
         *
-        * @param int|string|array $fallback Fallback cache or parameter map with 'fallback'
+        * @param int|string $fallback Fallback cache ID
         * @return BagOStuff
         * @throws InvalidArgumentException
         * @since 1.27
+        * @deprecated Since 1.28; use MediaWikiServices::getLocalServerObjectCache
         */
        public static function getLocalServerInstance( $fallback = CACHE_NONE ) {
-               if ( function_exists( 'apc_fetch' ) ) {
-                       $id = 'apc';
-               } elseif ( function_exists( 'xcache_get' ) && wfIniGetBool( 'xcache.var_size' ) ) {
-                       $id = 'xcache';
-               } elseif ( function_exists( 'wincache_ucache_get' ) ) {
-                       $id = 'wincache';
-               } else {
-                       if ( is_array( $fallback ) ) {
-                               $id = isset( $fallback['fallback'] ) ? $fallback['fallback'] : CACHE_NONE;
-                       } else {
-                               $id = $fallback;
-                       }
-               }
+               $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
 
-               return self::getInstance( $id );
+               return ( $cache instanceof EmptyBagOStuff )
+                       ? self::getInstance( $fallback )
+                       : $cache;
        }
 
        /**
@@ -383,11 +374,10 @@ class ObjectCache {
         *
         * @since 1.26
         * @return WANObjectCache
+        * @deprecated Since 1.28 Use MediaWikiServices::getMainWANCache()
         */
        public static function getMainWANInstance() {
-               global $wgMainWANCache;
-
-               return self::getWANInstance( $wgMainWANCache );
+               return MediaWikiServices::getInstance()->getMainWANObjectCache();
        }
 
        /**
@@ -407,11 +397,10 @@ class ObjectCache {
         *
         * @return BagOStuff
         * @since 1.26
+        * @deprecated Since 1.28 Use MediaWikiServices::getMainObjectStash
         */
        public static function getMainStashInstance() {
-               global $wgMainStash;
-
-               return self::getInstance( $wgMainStash );
+               return MediaWikiServices::getInstance()->getMainObjectStash();
        }
 
        /**
index c832237..974771f 100644 (file)
--- a/load.php
+++ b/load.php
@@ -23,6 +23,7 @@
  */
 
 use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 
 // This endpoint is supposed to be independent of request cookies and other
 // details of the session. Enforce this constraint with respect to session use.
@@ -35,6 +36,12 @@ if ( !$wgRequest->checkUrlExtension() ) {
        return;
 }
 
+// Don't initialise ChronologyProtector from object cache, and
+// don't wait for unrelated MediaWiki writes when querying ResourceLoader.
+MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->setRequestInfo( [
+       'ChronologyProtection' => 'false',
+] );
+
 // Set up ResourceLoader
 $resourceLoader = new ResourceLoader(
        ConfigFactory::getDefaultInstance()->makeConfig( 'main' ),
index 45a7ce5..e53a958 100644 (file)
@@ -336,6 +336,10 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
 
                JobQueueGroup::destroySingletons();
                ObjectCache::clear();
+               $services = MediaWikiServices::getInstance();
+               $services->resetServiceForTesting( 'MainObjectStash' );
+               $services->resetServiceForTesting( 'LocalServerObjectCache' );
+               $services->getMainWANObjectCache()->clearProcessCache();
                FileBackendGroup::destroySingleton();
 
                // TODO: move global state into MediaWikiServices
index a05e39d..4fbef6c 100644 (file)
@@ -320,8 +320,11 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                        '_MediaWikiTitleCodec' => [ '_MediaWikiTitleCodec', MediaWikiTitleCodec::class ],
                        'TitleFormatter' => [ 'TitleFormatter', TitleFormatter::class ],
                        'TitleParser' => [ 'TitleParser', TitleParser::class ],
-                       'VirtualRESTServiceClient' => [ 'VirtualRESTServiceClient', VirtualRESTServiceClient::class ],
-                       'ProxyLookup' => [ 'ProxyLookup', ProxyLookup::class ]
+                       'ProxyLookup' => [ 'ProxyLookup', ProxyLookup::class ],
+                       'MainObjectStash' => [ 'MainObjectStash', BagOStuff::class ],
+                       'MainWANObjectCache' => [ 'MainWANObjectCache', WANObjectCache::class ],
+                       'LocalServerObjectCache' => [ 'LocalServerObjectCache', BagOStuff::class ],
+                       'VirtualRESTServiceClient' => [ 'VirtualRESTServiceClient', VirtualRESTServiceClient::class ]
                ];
        }
 
index 26529e8..c915b70 100644 (file)
@@ -314,6 +314,8 @@ class SanitizerTest extends MediaWikiTestCase {
                                '/* insecure input */',
                                'background-image: -moz-image-set("asdf.png" 1x, "asdf.png" 2x);'
                        ],
+                       [ '/* insecure input */', 'foo: attr( title, url );' ],
+                       [ '/* insecure input */', 'foo: attr( title url );' ],
                ];
        }