Aude has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/227632

Change subject: On page views, update usage tracking via the job queue.
......................................................................

On page views, update usage tracking via the job queue.

In some cases, we need to update the usage tracking table during normal
page views. In this case, we should not write to the database directly,
but schedule a job instead.

Bug: T103429
Change-Id: Ied1db3f2ab802ac7d7638b63844598374bd59812
(cherry picked from commit 2bdd21e427cac4f0f5a2a5cdcdd4a276633d7866)
---
M client/WikibaseClient.php
M client/includes/Hooks/DataUpdateHookHandlers.php
M client/includes/Usage/EntityUsage.php
A client/includes/store/AddUsagesForPageJob.php
M client/includes/store/ClientStore.php
M client/includes/store/sql/DirectSqlStore.php
M client/tests/phpunit/MockClientStore.php
A client/tests/phpunit/includes/AddUsagesForPageJobTest.php
M client/tests/phpunit/includes/Hooks/DataUpdateHookHandlersTest.php
M client/tests/phpunit/includes/Usage/EntityUsageTest.php
10 files changed, 449 insertions(+), 28 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/32/227632/1

diff --git a/client/WikibaseClient.php b/client/WikibaseClient.php
index 6fb840c..9a9ae33 100644
--- a/client/WikibaseClient.php
+++ b/client/WikibaseClient.php
@@ -67,6 +67,7 @@
        global $wgExtensionCredits, $wgExtensionMessagesFiles, $wgHooks;
        global $wgAPIMetaModules, $wgAPIPropModules, $wgSpecialPages, 
$wgResourceModules;
        global $wgWBClientSettings, $wgRecentChangesFlags, $wgMessagesDirs;
+       global $wgJobClasses;
 
        $wgExtensionCredits['wikibase'][] = array(
                'path' => __DIR__,
@@ -121,6 +122,9 @@
        // extension hooks
        $wgHooks['WikibaseDeleteData'][] = 
'\Wikibase\ClientHooks::onWikibaseDeleteData';
 
+       // job classes
+       $wgJobClasses['wikibase-addUsagesForPage'] = 
'Wikibase\Client\Store\AddUsagesForPageJob';
+
        // api modules
        $wgAPIMetaModules['wikibase'] = array(
                'class' => 'Wikibase\ApiClientInfo',
diff --git a/client/includes/Hooks/DataUpdateHookHandlers.php 
b/client/includes/Hooks/DataUpdateHookHandlers.php
index 8b12966..42d9d78 100644
--- a/client/includes/Hooks/DataUpdateHookHandlers.php
+++ b/client/includes/Hooks/DataUpdateHookHandlers.php
@@ -3,6 +3,8 @@
 namespace Wikibase\Client\Hooks;
 
 use Content;
+use JobQueueGroup;
+use JobSpecification;
 use LinksUpdate;
 use ManualLogEntry;
 use ParserCache;
@@ -10,7 +12,9 @@
 use ParserOutput;
 use Title;
 use User;
+use Wikibase\Client\Store\AddUsagesForPageJob;
 use Wikibase\Client\Store\UsageUpdater;
+use Wikibase\Client\Usage\EntityUsage;
 use Wikibase\Client\Usage\ParserOutputUsageAccumulator;
 use Wikibase\Client\WikibaseClient;
 use WikiPage;
@@ -34,19 +38,15 @@
         */
        private $usageUpdater;
 
+       /**
+        * @var JobQueueGroup
+        */
+       private $jobScheduler;
+
        public static function newFromGlobalState() {
-               $wikibaseClient = WikibaseClient::getDefaultInstance();
-               $settings = $wikibaseClient->getSettings();
-
-               $usageUpdater = new UsageUpdater(
-                       $settings->getSetting( 'siteGlobalID' ),
-                       $wikibaseClient->getStore()->getUsageTracker(),
-                       $wikibaseClient->getStore()->getUsageLookup(),
-                       $wikibaseClient->getStore()->getSubscriptionManager()
-               );
-
                return new DataUpdateHookHandlers(
-                       $usageUpdater
+                       
WikibaseClient::getDefaultInstance()->getStore()->getUsageUpdater(),
+                       JobQueueGroup::singleton()
                );
        }
 
@@ -113,9 +113,11 @@
        }
 
        public function __construct(
-               UsageUpdater $usageUpdater
+               UsageUpdater $usageUpdater,
+               JobQueueGroup $jobScheduler
        ) {
                $this->usageUpdater = $usageUpdater;
+               $this->jobScheduler = $jobScheduler;
        }
 
        /**
@@ -169,13 +171,22 @@
                // These timestamps should usually be the same, but asking 
$title may cause a database query.
                $touched = $parserOutput->getTimestamp() ?: 
$title->getTouched();
 
+               if ( count( $usageAcc->getUsages() ) === 0 ) {
+                       // no usages, bail out
+                       return;
+               }
+
                // Add or touch any usages present in the new rendering.
                // This allows us to track usages in each user language 
separately, for multilingual sites.
-               $this->usageUpdater->addUsagesForPage(
-                       $title->getArticleId(),
-                       $usageAcc->getUsages(),
-                       $touched
-               );
+
+               // NOTE: Since parser cache updates may be triggered by page 
views (in a new language),
+               // schedule the usage updates in the job queue, to avoid 
writing to the database
+               // during a GET request.
+
+               //TODO: Before posting a job, check slave database. If no 
changes are needed, skip update.
+
+               $addUsagesForPageJob = AddUsagesForPageJob::newSpec( $title, 
$usageAcc->getUsages(), $touched );
+               $this->jobScheduler->push( $addUsagesForPageJob );
        }
 
        /**
diff --git a/client/includes/Usage/EntityUsage.php 
b/client/includes/Usage/EntityUsage.php
index 5876d7a..ba6938e 100644
--- a/client/includes/Usage/EntityUsage.php
+++ b/client/includes/Usage/EntityUsage.php
@@ -4,6 +4,7 @@
 
 use InvalidArgumentException;
 use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\EntityIdParsingException;
 
 /**
  * Value object representing the usage of an entity. This includes information 
about
@@ -146,6 +147,17 @@
        }
 
        /**
+        * @return array array( 'entityId' => $entityId, 'aspect' => $aspect, 
'modifier' => $modifier )
+        */
+       public function asArray() {
+               return array(
+                       'entityId' => $this->entityId->getSerialization(),
+                       'aspect' => $this->aspect,
+                       'modifier' => $this->modifier
+               );
+       }
+
+       /**
         * @param string $aspectKey
         *
         * @return string One of the EntityUsage::..._USAGE constants with the 
modifier split off.
diff --git a/client/includes/store/AddUsagesForPageJob.php 
b/client/includes/store/AddUsagesForPageJob.php
new file mode 100644
index 0000000..90f2e16
--- /dev/null
+++ b/client/includes/store/AddUsagesForPageJob.php
@@ -0,0 +1,148 @@
+<?php
+
+namespace Wikibase\Client\Store;
+
+use Job;
+use JobSpecification;
+use Title;
+use Wikibase\Client\Usage\EntityUsage;
+use Wikibase\Client\WikibaseClient;
+use Wikibase\DataModel\Entity\EntityIdParser;
+use Wikimedia\Assert\Assert;
+
+/**
+ * Job for scheduled invocation of UsageUpdater::addUsagesForPage
+ *
+ * @license GPL 2+
+ * @author Daniel Kinzler
+ */
+class AddUsagesForPageJob extends Job {
+
+       /**
+        * @var integer
+        */
+       private $pageId;
+
+       /**
+        * @var EntityUsage[]
+        */
+       private $usages;
+
+       /**
+        * @var string timestamp
+        */
+       private $touched;
+
+       /**
+        * @var UsageUpdater
+        */
+       private $usageUpdater;
+
+       /**
+        * @var EntityIdParser $idParser
+        */
+       private $idParser;
+
+       /**
+        * Spec constructor, for creating JobSpecifications to be pushed to the 
job queue.
+        *
+        * @param Title $title
+        * @param EntityUsage[] $usages
+        * @param string $touched
+        *
+        * @return JobSpecification
+        */
+       public static function newSpec( Title $title, array $usages, $touched ) 
{
+               // NOTE: Map EntityUsage objects to scalar arrays, for JSON 
serialization in the job queue.
+               $usages = array_map( function ( EntityUsage $usage ) {
+                       return $usage->asArray();
+               }, $usages );
+
+               $jobParams = array(
+                       'pageId' => $title->getArticleId(),
+                       'usages' => $usages,
+                       'touched' => $touched
+               );
+
+               return new JobSpecification( 'wikibase-addUsagesForPage', 
$jobParams, array(), $title );
+       }
+
+       /**
+        * @param Title $title
+        * @param array $params
+        */
+       public function __construct( Title $title, array $params ) {
+               parent::__construct( 'wikibase-addUsagesForPage', $title, 
$params );
+
+               Assert::parameter(
+                       isset( $params['pageId'] ) && is_int( $params['pageId'] 
) && $params['pageId'] > 0,
+                       '$params["pageId"]',
+                       'must be a positive integer' );
+
+               Assert::parameter(
+                       isset( $params['usages'] ) && is_array( 
$params['usages'] ) && !empty( $params['usages'] ),
+                       '$params["usages"]',
+                       'must be a non-empty array' );
+
+               Assert::parameter(
+                       isset( $params['touched'] ) && is_string( 
$params['touched'] ) && $params['touched'] !== '',
+                       '$params["touched"]',
+                       'must be a timestamp string' );
+
+               Assert::parameterElementType(
+                       'array',
+                       $params['usages'],
+                       '$params["usages"]' );
+
+               $this->pageId = $params['pageId'];
+               $this->usages = $params['usages'];
+               $this->touched = $params['touched'];
+
+               $usageUpdater = 
WikibaseClient::getDefaultInstance()->getStore()->getUsageUpdater();
+               $idParser = 
WikibaseClient::getDefaultInstance()->getEntityIdParser();
+               $this->overrideServices( $usageUpdater, $idParser );
+       }
+
+       /**
+        * Service override for testing
+        *
+        * @param UsageUpdater $usageUpdater
+        * @param EntityIdParser $idParser
+        */
+       public function overrideServices( UsageUpdater $usageUpdater, 
EntityIdParser $idParser ) {
+               $this->usageUpdater = $usageUpdater;
+               $this->idParser = $idParser;
+       }
+
+       /**
+        * @return EntityUsage[]
+        */
+       private function getUsages() {
+               // Turn serialized usage info into EntityUsage objects
+               $idParser = $this->idParser;
+               $usages = array_map( function ( array $usageArray ) use ( 
$idParser ) {
+                       // This is the inverse of EntityUsage::asArray()
+                       return new EntityUsage(
+                               $idParser->parse( $usageArray['entityId'] ),
+                               $usageArray['aspect'],
+                               $usageArray['modifier']
+                       );
+               }, $this->usages );
+
+               return $usages;
+       }
+
+       /**
+        * Call UsageUpdater::addUsagesForPage
+        *
+        * @return bool Success
+        */
+       public function run() {
+               $this->usageUpdater->addUsagesForPage(
+                       $this->pageId,
+                       $this->getUsages(),
+                       $this->touched
+               );
+       }
+
+}
diff --git a/client/includes/store/ClientStore.php 
b/client/includes/store/ClientStore.php
index 66b381a..51d052f 100644
--- a/client/includes/store/ClientStore.php
+++ b/client/includes/store/ClientStore.php
@@ -3,6 +3,7 @@
 namespace Wikibase;
 
 use MWException;
+use Wikibase\Client\Store\UsageUpdater;
 use Wikibase\Client\Usage\SubscriptionManager;
 use Wikibase\Client\Usage\UsageLookup;
 use Wikibase\Client\Usage\UsageTracker;
@@ -125,4 +126,11 @@
         */
        public function getEntityPrefetcher();
 
+       /**
+        * @since 0.5
+        *
+        * @return UsageUpdater
+        */
+       public function getUsageUpdater();
+
 }
diff --git a/client/includes/store/sql/DirectSqlStore.php 
b/client/includes/store/sql/DirectSqlStore.php
index dc4f311..40df459 100644
--- a/client/includes/store/sql/DirectSqlStore.php
+++ b/client/includes/store/sql/DirectSqlStore.php
@@ -7,6 +7,7 @@
 use Wikibase\Client\Store\Sql\ConsistentReadConnectionManager;
 use Wikibase\Client\Store\Sql\PagePropsEntityIdLookup;
 use Wikibase\Client\Store\TitleFactory;
+use Wikibase\Client\Store\UsageUpdater;
 use Wikibase\Client\Usage\NullSubscriptionManager;
 use Wikibase\Client\Usage\NullUsageTracker;
 use Wikibase\Client\Usage\SiteLinkUsageLookup;
@@ -464,4 +465,15 @@
                return $this->entityPrefetcher;
        }
 
+       /**
+        * @return UsageUpdater
+        */
+       public function getUsageUpdater() {
+               return new UsageUpdater(
+                       $this->siteId,
+                       $this->getUsageTracker(),
+                       $this->getUsageLookup(),
+                       $this->getSubscriptionManager()
+               );
+       }
 }
diff --git a/client/tests/phpunit/MockClientStore.php 
b/client/tests/phpunit/MockClientStore.php
index 1cef882..80d015a 100644
--- a/client/tests/phpunit/MockClientStore.php
+++ b/client/tests/phpunit/MockClientStore.php
@@ -3,9 +3,13 @@
 namespace Wikibase\Test;
 
 use Wikibase\ChangesTable;
+use Wikibase\Client\Store\UsageUpdater;
 use Wikibase\Client\Usage\NullSubscriptionManager;
 use Wikibase\Client\Usage\NullUsageTracker;
 use Wikibase\ClientStore;
+use Wikibase\Lib\Store\EntityLookup;
+use Wikibase\Lib\Store\EntityPrefetcher;
+use Wikibase\Lib\Store\EntityRevisionLookup;
 use Wikibase\Lib\Store\NullEntityPrefetcher;
 use Wikibase\PropertyInfoStore;
 use Wikibase\Store\EntityIdLookup;
@@ -181,4 +185,17 @@
                return new NullEntityPrefetcher();
        }
 
+       /**
+        * @since 0.5
+        *
+        * @return UsageUpdater
+        */
+       public function getUsageUpdater() {
+               return new UsageUpdater(
+                       'mock',
+                       $this->getUsageTracker(),
+                       $this->getUsageLookup(),
+                       $this->getSubscriptionManager()
+               );
+       }
 }
diff --git a/client/tests/phpunit/includes/AddUsagesForPageJobTest.php 
b/client/tests/phpunit/includes/AddUsagesForPageJobTest.php
new file mode 100644
index 0000000..cb15661
--- /dev/null
+++ b/client/tests/phpunit/includes/AddUsagesForPageJobTest.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace Wikibase\Client\Test\Store;
+
+use Title;
+use Wikibase\Client\Store\AddUsagesForPageJob;
+use Wikibase\Client\Usage\EntityUsage;
+use Wikibase\DataModel\Entity\BasicEntityIdParser;
+use Wikibase\DataModel\Entity\ItemId;
+
+/**
+ * @covers Wikibase\Client\Store\AddUsagesForPageJob
+ *
+ * @group Wikibase
+ * @group WikibaseClient
+ * @group WikibaseUsageTracking
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class AddUsagesForPageJobTest extends \PHPUnit_Framework_TestCase {
+
+       public function provideConstructor_failure() {
+               $pageId = 17;
+               $usageQ5X = new EntityUsage( new ItemId( 'Q5' ), 'X' );
+               $usages = array( $usageQ5X->asArray() );
+               $touched = '20150101000000';
+
+               return array(
+                       'empty' => array( array() ),
+
+                       '$pageId is missing' => array( array(
+                               'usages' => $usages,
+                               'touched' => $touched,
+                       ) ),
+                       '$pageId is not an int' => array( array(
+                               'pageId' => 'foo',
+                               'usages' => $usages,
+                               'touched' => $touched,
+                       ) ),
+                       '$pageId is zero' => array( array(
+                               'pageId' => 0,
+                               'usages' => $usages,
+                               'touched' => $touched,
+                       ) ),
+
+                       '$usages is missing' => array( array(
+                               'pageId' => $pageId,
+                               'touched' => $touched,
+                       ) ),
+                       '$usages is not an array' => array( array(
+                               'pageId' => $pageId,
+                               'usages' => 'xxx',
+                               'touched' => $touched,
+                       ) ),
+                       '$usages is empty' => array( array(
+                               'pageId' => $pageId,
+                               'usages' => array(),
+                               'touched' => $touched,
+                       ) ),
+                       '$usages contains crap' => array( array(
+                               'pageId' => $pageId,
+                               'usages' => array( 1, 2, 3 ),
+                               'touched' => $touched,
+                       ) ),
+
+                       '$touched is missing' => array( array(
+                               'pageId' => $pageId,
+                               'usages' => $usages,
+                       ) ),
+                       '$touched is not a string' => array( array(
+                               'pageId' => $pageId,
+                               'usages' => $usages,
+                               'touched' => 23,
+                       ) ),
+                       '$touched is empty' => array( array(
+                               'pageId' => $pageId,
+                               'usages' => $usages,
+                               'touched' => '',
+                       ) ),
+               );
+       }
+
+       /**
+        * @dataProvider provideConstructor_failure
+        * @param array $params
+        */
+       public function testConstructor_failure( $params ) {
+               $this->setExpectedException( 'InvalidArgumentException' );
+
+               $title = Title::makeTitle( NS_MAIN, 'Foo' );
+               new AddUsagesForPageJob( $title, $params );
+       }
+
+       public function testRun() {
+               $usageQ5X = new EntityUsage( new ItemId( 'Q5' ), 'X' );
+               $params = array(
+                       'pageId' => 17,
+                       'usages' => array( $usageQ5X->asArray() ),
+                       'touched' => '20150101000000',
+               );
+
+               $usageUpdater = $this->getMockBuilder( 
'Wikibase\Client\Store\UsageUpdater' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               $usageUpdater->expects( $this->once() )
+                       ->method( 'addUsagesForPage' )
+                       ->with(
+                               $params['pageId'],
+                               array( $usageQ5X ),
+                               $params['touched']
+                       );
+
+               $title = Title::makeTitle( NS_MAIN, 'Foo' );
+               $job = new AddUsagesForPageJob( $title, $params );
+               $job->overrideServices( $usageUpdater, new 
BasicEntityIdParser() );
+
+               $job->run();
+       }
+
+       public function testNewSpec() {
+               $usageQ5X = new EntityUsage( new ItemId( 'Q5' ), 'X' );
+
+               $title = Title::makeTitle( NS_MAIN, 'Foo' );
+               $title->resetArticleID( 17 );
+
+               $touched = '20150101000000';
+               $usages = array( $usageQ5X );
+
+               $spec = AddUsagesForPageJob::newSpec( $title, $usages, $touched 
);
+
+               $params = array(
+                       'pageId' => $title->getArticleID(),
+                       'usages' => array( $usageQ5X->asArray() ),
+                       'touched' => '20150101000000',
+               );
+
+               $this->assertEquals( 'wikibase-addUsagesForPage', 
$spec->getType() );
+               $this->assertEquals( $title->getFullText(), 
$spec->getTitle()->getFullText() );
+               $this->assertEquals( $params, $spec->getParams() );
+       }
+
+}
diff --git a/client/tests/phpunit/includes/Hooks/DataUpdateHookHandlersTest.php 
b/client/tests/phpunit/includes/Hooks/DataUpdateHookHandlersTest.php
index 744489f..d0777ea 100644
--- a/client/tests/phpunit/includes/Hooks/DataUpdateHookHandlersTest.php
+++ b/client/tests/phpunit/includes/Hooks/DataUpdateHookHandlersTest.php
@@ -2,6 +2,9 @@
 
 namespace Wikibase\Client\Tests\Hooks;
 
+use Job;
+use JobQueueGroup;
+use JobSpecification;
 use ParserOutput;
 use Title;
 use Wikibase\Client\Hooks\DataUpdateHookHandlers;
@@ -26,13 +29,14 @@
 
        /**
         * @param Title $title
-        * @param EntityUsage[]|null $expectedUsages
+        * @param array $expectedUsages
         * @param string|null $touched
-        * @param bool $prune
+        * @param bool $prune whether pruneUsagesForPage() should be used
+        * @param bool $add whether addUsagesForPage() should be used
         *
         * @return UsageUpdater
         */
-       private function newUsageUpdater( Title $title, array $expectedUsages = 
null, $touched = null, $prune = true ) {
+       private function newUsageUpdater( Title $title, array $expectedUsages = 
null, $touched = null, $prune = true, $add = true ) {
                $usageUpdater = $this->getMockBuilder( 
'Wikibase\Client\Store\UsageUpdater' )
                        ->disableOriginalConstructor()
                        ->getMock();
@@ -47,7 +51,7 @@
                // greater timestamp.
                $touchedMatcher = $this->greaterThanOrEqual( $touched );
 
-               if ( $expectedUsages === null ) {
+               if ( $expectedUsages === null || !$add ) {
                        $usageUpdater->expects( $this->never() )
                                ->method( 'addUsagesForPage' );
                } else {
@@ -70,17 +74,59 @@
 
        /**
         * @param Title $title
+        * @param array|null $expectedUsages
+        * @param string|null $touched
+        * @param bool $useJobQueue whether we expect the job queue to be used
+        *
+        * @return JobQueueGroup
+        */
+       private function newJobScheduler( Title $title, array $expectedUsages = 
null, $touched = null, $useJobQueue = false ) {
+               $jobScheduler = $this->getMockBuilder( 'JobQueueGroup' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               if ( empty( $expectedUsages ) || !$useJobQueue ) {
+                       $jobScheduler->expects( $this->never() )
+                               ->method( 'push' );
+               } else {
+                       $expectedUsageArray = array_map( function ( EntityUsage 
$usage ) {
+                               return $usage->asArray();
+                       }, $expectedUsages );
+
+                       $params = array(
+                               'pageId' => $title->getArticleID(),
+                               'usages' => $expectedUsageArray,
+                               'touched' => $touched
+                       );
+
+                       $jobScheduler->expects( $this->once() )
+                               ->method( 'push' )
+                               ->with( $this->callback( function ( 
JobSpecification $job ) use ( $params ) {
+                                       
DataUpdateHookHandlersTest::assertEquals( 'wikibase-addUsagesForPage', 
$job->getType() );
+                                       
DataUpdateHookHandlersTest::assertEquals( $params, $job->getParams() );
+                                       return true;
+                               } ) );
+               }
+
+               return $jobScheduler;
+       }
+
+       /**
+        * @param Title $title
         * @param EntityUsage[]|null $expectedUsages
         * @param string|null $touched timestamp
-        * @param bool $prune
+        * @param bool $prune whether pruneUsagesForPage() should be used
+        * @param bool $asyncAdd whether addUsagesForPage() should be called 
via the job queue
         *
         * @return DataUpdateHookHandlers
         */
-       private function newDataUpdateHookHandlers( Title $title, array 
$expectedUsages = null, $touched = null, $prune = true ) {
-               $usageUpdater = $this->newUsageUpdater( $title, 
$expectedUsages, $touched, $prune );
+       private function newDataUpdateHookHandlers( Title $title, array 
$expectedUsages = null, $touched = null, $prune = true, $asyncAdd = false ) {
+               $usageUpdater = $this->newUsageUpdater( $title, 
$expectedUsages, $touched, $prune, !$asyncAdd );
+               $jobScheduler = $this->newJobScheduler( $title, 
$expectedUsages, $touched, $asyncAdd );
 
                return new DataUpdateHookHandlers(
-                       $usageUpdater
+                       $usageUpdater,
+                       $jobScheduler
                );
        }
 
@@ -164,7 +210,7 @@
                $linksUpdate = $this->newLinksUpdate( $title, $usage, 
$timestamp );
 
                // Assertions are done by the UsageUpdater mock
-               $handler = $this->newDataUpdateHookHandlers( $title, $usage, 
$timestamp, true );
+               $handler = $this->newDataUpdateHookHandlers( $title, $usage, 
$timestamp, true, false );
                $handler->doLinksUpdateComplete( $linksUpdate );
        }
 
@@ -178,7 +224,7 @@
                $parserOutput = $this->newParserOutput( $usage, $timestamp );
 
                // Assertions are done by the UsageUpdater mock
-               $handler = $this->newDataUpdateHookHandlers( $title, $usage, 
$timestamp, false );
+               $handler = $this->newDataUpdateHookHandlers( $title, $usage, 
$timestamp, false, true );
                $handler->doParserCacheSaveComplete( $parserOutput, $title );
        }
 
@@ -188,7 +234,7 @@
                $timestamp = '20150505000000';
 
                // Assertions are done by the UsageUpdater mock
-               $handler = $this->newDataUpdateHookHandlers( $title, null, 
$timestamp, true );
+               $handler = $this->newDataUpdateHookHandlers( $title, null, 
$timestamp, true, false );
                $handler->doArticleDeleteComplete( $title->getNamespace(), 
$title->getArticleID(), $timestamp );
        }
 
diff --git a/client/tests/phpunit/includes/Usage/EntityUsageTest.php 
b/client/tests/phpunit/includes/Usage/EntityUsageTest.php
index 1a20b61..48f9bc6 100644
--- a/client/tests/phpunit/includes/Usage/EntityUsageTest.php
+++ b/client/tests/phpunit/includes/Usage/EntityUsageTest.php
@@ -55,6 +55,25 @@
                $this->assertEquals( "$aspect.$modifier", 
$usage->getAspectKey() );
        }
 
+       public function testAsArray() {
+               $id = new ItemId( 'Q7' );
+               $aspect = EntityUsage::LABEL_USAGE;
+               $modifier = 'ru';
+
+               $expected = array(
+                       'entityId' => $id->getSerialization(),
+                       'aspect' => $aspect,
+                       'modifier' => null
+               );
+
+               $usage = new EntityUsage( $id, $aspect );
+               $this->assertEquals( $expected, $usage->asArray() );
+
+               $expected['modifier'] = $modifier;
+               $usage = new EntityUsage( $id, $aspect, $modifier );
+               $this->assertEquals( $expected, $usage->asArray() );
+       }
+
        public function aspectKeyProvider() {
                return array(
                        array( 'L', array( 'L', null ) ),

-- 
To view, visit https://gerrit.wikimedia.org/r/227632
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ied1db3f2ab802ac7d7638b63844598374bd59812
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: wmf/1.26wmf16
Gerrit-Owner: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to