jenkins-bot has submitted this change and it was merged.

Change subject: Split ChangeHandler::getPagesToUpdate into new class with tests
......................................................................


Split ChangeHandler::getPagesToUpdate into new class with tests

Change-Id: I86a78a1a275c7deb7a822e1188a1a04c9c37bcf5
---
M client/WikibaseClient.classes.php
M client/includes/ChangeHandler.php
A client/includes/ReferencedPagesFinder.php
A client/tests/phpunit/includes/ReferencedPagesFinderTest.php
4 files changed, 416 insertions(+), 84 deletions(-)

Approvals:
  Daniel Kinzler: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/client/WikibaseClient.classes.php 
b/client/WikibaseClient.classes.php
index ad29c64..e554ee4 100644
--- a/client/WikibaseClient.classes.php
+++ b/client/WikibaseClient.classes.php
@@ -17,6 +17,7 @@
                'Wikibase\LangLinkHandler' => 'includes/LangLinkHandler.php',
                'Wikibase\ChangeHandler' => 'includes/ChangeHandler.php',
                'Wikibase\NamespaceChecker' => 'includes/NamespaceChecker.php',
+               'Wikibase\ReferencedPagesFinder' => 
'includes/ReferencedPagesFinder.php',
                'Wikibase\RepoItemLinkGenerator' => 
'includes/RepoItemLinkGenerator.php',
                'Wikibase\RepoLinker' => 'includes/RepoLinker.php',
                'Wikibase\Client\WikibaseClient' => 
'includes/WikibaseClient.php',
diff --git a/client/includes/ChangeHandler.php 
b/client/includes/ChangeHandler.php
index e840f2f..287a31f 100644
--- a/client/includes/ChangeHandler.php
+++ b/client/includes/ChangeHandler.php
@@ -1,4 +1,5 @@
 <?php
+
 namespace Wikibase;
 
 use Diff\Diff;
@@ -17,25 +18,7 @@
  * it should be fed to this service which then takes care handling
  * it.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
  * @since 0.1
- *
- * @file
- * @ingroup WikibaseLib
  *
  * @licence GNU GPL v2+
  * @author Daniel Kinzler
@@ -100,9 +83,14 @@
        protected $entityLookup;
 
        /**
-        * @var \Site $site
+        * @var Site $site
         */
        protected $site;
+
+       /**
+        * @var string
+        */
+       protected $siteId;
 
        /**
         * @var NamespaceChecker $namespaceChecker
@@ -151,6 +139,8 @@
                }
 
                $this->site = $localSite;
+               $this->siteId = $localSite->getGlobalId();
+
                $this->updater = $updater;
                $this->entityLookup = $entityLookup;
                $this->entityUsageIndex = $entityUsageIndex;
@@ -549,8 +539,6 @@
        /**
         * Returns the pages that need some kind of updating given the change.
         *
-        * @todo: determine actions for each page!
-        *
         * @param Change $change
         *
         * @return Title[] the titles of the pages to update
@@ -558,72 +546,19 @@
        public function getPagesToUpdate( Change $change ) {
                wfProfileIn( __METHOD__ );
 
-               $pagesToUpdate = array();
+               // todo inject!
+               $referencedPagesFinder = new ReferencedPagesFinder(
+                       $this->entityUsageIndex,
+                       $this->namespaceChecker,
+                       $this->siteId,
+                       $this->checkPageExistence
+               );
 
-               if ( $change instanceof ItemChange ) {
-                       // update local pages connected to a relevant data item.
-
-                       $itemId = $change->getEntityId();
-
-                       $siteGlobalId = $this->site->getGlobalId();
-
-                       $usedOnPages = $this->entityUsageIndex->getEntityUsage( 
array( $itemId ) );
-                       $pagesToUpdate = array_merge( $pagesToUpdate, 
$usedOnPages );
-
-                       // if an item's sitelinks change, update the old and 
the new target
-                       $siteLinkDiff = $change->getSiteLinkDiff();
-
-                       if ( isset( $siteLinkDiff[$siteGlobalId] ) ) {
-
-                               // $siteLinkDiff changed from containing atomic 
diffs to
-                               // containing map diffs. For B/C, handle both 
cases.
-                               $siteLinkDiffOp = $siteLinkDiff[$siteGlobalId];
-
-                               if ( $siteLinkDiffOp instanceof Diff ) {
-                                       if ( array_key_exists( 'name', 
$siteLinkDiffOp ) ) {
-                                               $siteLinkDiffOp = 
$siteLinkDiffOp['name'];
-                                       } else {
-                                               // change to badges only
-                                               $siteLinkDiffOp = null;
-                                       }
-                               }
-
-                               if ( $siteLinkDiffOp === null ) {
-                                       // do nothing, only badges were  changed
-                               }elseif ( $siteLinkDiffOp instanceof DiffOpAdd 
) {
-                                       $pagesToUpdate[] = 
$siteLinkDiffOp->getNewValue();
-                               } elseif ( $siteLinkDiffOp instanceof 
DiffOpRemove ) {
-                                       $pagesToUpdate[] = 
$siteLinkDiffOp->getOldValue();
-                               } elseif ( $siteLinkDiffOp instanceof 
DiffOpChange ) {
-                                       $pagesToUpdate[] = 
$siteLinkDiffOp->getNewValue();
-                                       $pagesToUpdate[] = 
$siteLinkDiffOp->getOldValue();
-                               } else {
-                                       wfWarn( "Unknown change operation: " . 
get_class( $siteLinkDiffOp ) . ")" );
-                               }
-                       }
-               }
-
-               $pagesToUpdate = array_unique( $pagesToUpdate );
-               $titlesToUpdate = array();
-
-               foreach ( $pagesToUpdate as $page ) {
-                       $title = Title::newFromText( $page );
-
-                       if ( !$title->exists() && $this->checkPageExistence ) {
-                               continue;
-                       }
-
-                       $ns = $title->getNamespace();
-
-                       if ( !is_int( $ns ) || 
!$this->namespaceChecker->isWikibaseEnabled( $ns ) ) {
-                               continue;
-                       }
-
-                       $titlesToUpdate[] = $title;
-               }
+               $pagesToUpdate = $referencedPagesFinder->getPages( $change );
 
                wfProfileOut( __METHOD__ );
-               return $titlesToUpdate;
+
+               return $pagesToUpdate;
        }
 
        /**
diff --git a/client/includes/ReferencedPagesFinder.php 
b/client/includes/ReferencedPagesFinder.php
new file mode 100644
index 0000000..0c7017c
--- /dev/null
+++ b/client/includes/ReferencedPagesFinder.php
@@ -0,0 +1,189 @@
+<?php
+
+namespace Wikibase;
+
+use Diff\Diff;
+use Diff\DiffOpAdd;
+use Diff\DiffOpChange;
+use Diff\DiffOpRemove;
+use Title;
+use Wikibase\DataModel\Entity\ItemId;
+
+/**
+ * Interface for change handling. Whenever a change is detected,
+ * it should be fed to this service which then takes care handling
+ * it.
+ *
+ * @since 0.1
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ * @author Katie Filbert < aude.w...@gmail.com >
+ */
+class ReferencedPagesFinder {
+
+       /**
+        * @var ItemUsageIndex
+        */
+       private $itemUsageIndex;
+
+       /**
+        * @var NamespaceChecker
+        */
+       private $namespaceChecker;
+
+       /**
+        * @var string
+        */
+       private $siteId;
+
+       /**
+        * @var boolean
+        */
+       private $checkPageExistence;
+
+       /**
+        * @param ItemUsageIndex $itemUsageIndex
+        * @param NamespaceChecker $namespaceChecker
+        * @param string $siteId
+        * @param boolean $checkPageExistence
+        */
+       public function __construct( ItemUsageIndex $itemUsageIndex, 
NamespaceChecker $namespaceChecker,
+               $siteId, $checkPageExistence = true ) {
+               $this->itemUsageIndex = $itemUsageIndex;
+               $this->namespaceChecker = $namespaceChecker;
+               $this->siteId = $siteId;
+               $this->checkPageExistence = $checkPageExistence;
+       }
+
+       /**
+        * @since 0.5
+        *
+        * @param Change $change
+        *
+        * @return Title[]
+        */
+       public function getPages( Change $change ) {
+               if ( ! ( $change instanceof ItemChange ) ) {
+                       return array();
+               }
+
+               $pages = $this->getReferencedPages( $change );
+
+               return $this->getTitlesToUpdate( $pages );
+       }
+
+       /**
+        * Returns the pages that need some kind of updating given the change.
+        *
+        * @param Change $change
+        *
+        * @return Title[] the titles of the pages to update
+        */
+       private function getReferencedPages( Change $change ) {
+               $itemId = $change->getEntityId();
+
+               $pages = $this->itemUsageIndex->getEntityUsage( array( $itemId 
) );
+
+               $siteLinkDiff = $change->getSiteLinkDiff();
+
+               if ( $this->isRelevantSiteLinkChange( $siteLinkDiff ) ) {
+                       $pages = $this->addSiteLinkDiffPages( $siteLinkDiff, 
$pages );
+               }
+
+               return array_unique( $pages );
+       }
+
+       /**
+        * @param Diff $siteLinkDiff
+        *
+        * @return boolean
+        */
+       private function isRelevantSiteLinkChange( Diff $siteLinkDiff ) {
+               return isset( $siteLinkDiff[$this->siteId] ) && 
!$this->isBadgesOnlyChange( $siteLinkDiff );
+       }
+
+       /**
+        * @param Diff $siteLinkDiff
+        * @param string[] $pages
+        *
+        * @return string[]
+        */
+       private function addSiteLinkDiffPages( Diff $siteLinkDiff, array $pages 
) {
+               return array_merge(
+                       $pages,
+                       $this->getPagesReferencedInDiff( $siteLinkDiff )
+               );
+       }
+
+       /**
+        * @param Diff $siteLinkDiff
+        *
+        * @return array
+        */
+       private function getPagesReferencedInDiff( Diff $siteLinkDiff ) {
+               $pagesToUpdate = array();
+
+               // $siteLinkDiff changed from containing atomic diffs to
+               // containing map diffs. For B/C, handle both cases.
+               $siteLinkDiffOp = $siteLinkDiff[$this->siteId];
+
+               if ( ( $siteLinkDiffOp instanceof Diff ) && ( array_key_exists( 
'name', $siteLinkDiffOp ) ) ) {
+                       $siteLinkDiffOp = $siteLinkDiffOp['name'];
+               }
+
+               if ( $siteLinkDiffOp instanceof DiffOpAdd ) {
+                       $pagesToUpdate[] = $siteLinkDiffOp->getNewValue();
+               } elseif ( $siteLinkDiffOp instanceof DiffOpRemove ) {
+                       $pagesToUpdate[] = $siteLinkDiffOp->getOldValue();
+               } elseif ( $siteLinkDiffOp instanceof DiffOpChange ) {
+                       $pagesToUpdate[] = $siteLinkDiffOp->getNewValue();
+                       $pagesToUpdate[] = $siteLinkDiffOp->getOldValue();
+               } else {
+                       throw new UnexpectedValueException(
+                               "Unknown change operation: " . get_class( 
$siteLinkDiffOp ) . ")"
+                       );
+               }
+
+               return $pagesToUpdate;
+       }
+
+       /**
+        * @param Diff $siteLinkDiff
+        *
+        * @return boolean
+        */
+       private function isBadgesOnlyChange( Diff $siteLinkDiff ) {
+               $siteLinkDiffOp = $siteLinkDiff[$this->siteId];
+
+               return ( $siteLinkDiffOp instanceof Diff && !array_key_exists( 
'name', $siteLinkDiffOp ) );
+       }
+
+       /**
+        * @param array $pagesToUpdate
+        *
+        * @return Title[]
+        */
+       private function getTitlesToUpdate( array $pagesToUpdate ) {
+               $titlesToUpdate = array();
+
+               foreach ( $pagesToUpdate as $page ) {
+                       $title = Title::newFromText( $page );
+
+                       if ( !$title->exists() && $this->checkPageExistence ) {
+                               continue;
+                       }
+
+                       $ns = $title->getNamespace();
+
+                       if ( !is_int( $ns ) || 
!$this->namespaceChecker->isWikibaseEnabled( $ns ) ) {
+                               continue;
+                       }
+
+                       $titlesToUpdate[] = $title;
+               }
+
+               return $titlesToUpdate;
+       }
+
+}
diff --git a/client/tests/phpunit/includes/ReferencedPagesFinderTest.php 
b/client/tests/phpunit/includes/ReferencedPagesFinderTest.php
new file mode 100644
index 0000000..c0d7a65
--- /dev/null
+++ b/client/tests/phpunit/includes/ReferencedPagesFinderTest.php
@@ -0,0 +1,207 @@
+<?php
+
+namespace Wikibase\Test;
+
+use ContentHandler;
+use Title;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\SimpleSiteLink;
+use Wikibase\Item;
+use Wikibase\ItemChange;
+use Wikibase\ReferencedPagesFinder;
+use WikiPage;
+
+/**
+ * @covers Wikibase\ReferencedPagesFinder
+ *
+ * @since 0.5
+ *
+ * @group WikibaseClient
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.w...@gmail.com >
+ */
+class ReferencedPagesFinderTest extends \PHPUnit_Framework_TestCase {
+
+       static protected $titles;
+
+       public function setUp() {
+               parent::setUp();
+
+               if ( !self::$titles ) {
+                       self::$titles = array(
+                               Title::newFromText( 'Berlin' ),
+                               Title::newFromText( 'Rome' )
+                       );
+
+                       foreach( self::$titles as $title ) {
+                               $content = ContentHandler::makeContent( 'edit 
page', $title );
+                               $page = WikiPage::factory( $title );
+                               $page->doEditContent( $content, 'edit page' );
+                       }
+               }
+       }
+
+       /**
+        * @dataProvider getPagesProvider
+        */
+       public function testGetPages( $expected, $usage, $change, $message ) {
+               $itemUsageIndex = $this->getMockBuilder( 
'\Wikibase\ItemUsageIndex' )
+                                                       
->disableOriginalConstructor()->getMock();
+
+               $itemUsageIndex->expects( $this->any() )
+                       ->method( 'getEntityUsage' )
+                       ->will( $this->returnValue( $usage ) );
+
+               $namespaceChecker = $this->getMockBuilder( 
'\Wikibase\NamespaceChecker' )
+                                                       
->disableOriginalConstructor()->getMock();
+
+               $namespaceChecker->expects( $this->any() )
+                       ->method( 'isWikibaseEnabled' )
+                       ->will( $this->returnValue( true ) );
+
+               $referencedPagesFinder = new ReferencedPagesFinder( 
$itemUsageIndex, $namespaceChecker, 'enwiki' );
+
+               $this->assertEquals( $expected, 
$referencedPagesFinder->getPages( $change ), $message );
+       }
+
+       public function getPagesProvider() {
+               $berlin = Title::newFromText( 'Berlin' );
+               $rome = Title::newFromText( 'Rome' );
+
+               $cases = array();
+
+               $cases[] = array(
+                       array( $berlin ),
+                       array(),
+                       ItemChange::newFromUpdate(
+                               ItemChange::ADD,
+                               null,
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Berlin' ) )
+                       ),
+                       'created item with site link to client'
+               );
+
+               $cases[] = array(
+                       array( $berlin ),
+                       array(),
+                       ItemChange::newFromUpdate(
+                               ItemChange::UPDATE,
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Berlin' ) ),
+                               $this->getEmptyItem()
+                       ),
+                       'removed site link to client'
+               );
+
+               $cases[] = array(
+                       array( $rome ),
+                       array(),
+                       ItemChange::newFromUpdate(
+                               ItemChange::UPDATE,
+                               $this->getEmptyItem(),
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Rome' ) )
+                       ),
+                       'added site link to client'
+               );
+
+               $cases[] = array(
+                       array( $berlin, $rome ),
+                       array(),
+                       ItemChange::newFromUpdate(
+                               ItemChange::UPDATE,
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Rome' ) ),
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Berlin' ) )
+                       ),
+                       'changed client site link'
+               );
+
+               $cases[] = array(
+                       array( $rome ),
+                       array(),
+                       ItemChange::newFromUpdate(
+                               ItemChange::REMOVE,
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Rome' ) ),
+                               null
+                       ),
+                       'item connected to client was deleted'
+               );
+
+               $cases[] = array(
+                       array( $rome ),
+                       array( 'Rome' ),
+                       ItemChange::newFromUpdate(
+                               ItemChange::UPDATE,
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Rome' ) ),
+                               $this->getItemWithSiteLinks( array(
+                                       'enwiki' => 'Rome',
+                                       'itwiki' => 'Roma'
+                               ) )
+                       ),
+                       'added site link on connected item'
+               );
+
+               $cases[] = array(
+                       array(),
+                       array(),
+                       ItemChange::newFromUpdate(
+                               ItemChange::UPDATE,
+                               $this->getEmptyItem(),
+                               $this->getItemWithLabel( 'de', 'Berlin' )
+                       ),
+                       'unrelated label change'
+               );
+
+               $connectedItem = $this->getItemWithSiteLinks( array( 'enwiki' 
=> 'Berlin' ) );
+               $connectedItemWithLabel = $this->getItemWithSiteLinks( array( 
'enwiki' => 'Berlin' ) );
+               $connectedItemWithLabel->setLabel( 'enwiki', 'Berlin' );
+
+               $cases[] = array(
+                       array( $berlin ),
+                       array( 'Berlin' ),
+                       ItemChange::newFromUpdate( ItemChange::UPDATE, 
$connectedItem, $connectedItemWithLabel ),
+                       'connected item label change'
+               );
+
+               $itemWithBadge = $this->getEmptyItem();
+               $badges = array( new ItemId( 'Q34' ) );
+               $itemWithBadge->addSimpleSiteLink( new SimpleSiteLink( 
'enwiki', 'Rome', $badges  ) );
+
+               $cases[] = array(
+                       array(),
+                       array(),
+                       ItemChange::newFromUpdate( ItemChange::UPDATE,
+                               $this->getItemWithSiteLinks( array( 'enwiki' => 
'Rome' ) ),
+                               $itemWithBadge ),
+                       'badge change'
+               );
+
+               return $cases;
+       }
+
+       private function getEmptyItem() {
+               $item = Item::newEmpty();
+               $item->setId( 2 );
+
+               return $item->copy();
+       }
+
+       private function getItemWithSiteLinks( $links ) {
+               $item = $this->getEmptyItem();
+
+               foreach( $links as $siteId => $page ) {
+                       $item->addSimpleSiteLink(
+                               new SimpleSiteLink( $siteId, $page )
+                       );
+               }
+
+               return $item->copy();
+       }
+
+       private function getItemWithLabel( $lang, $label ) {
+               $item = $this->getEmptyItem();
+               $item->setLabel( $lang, $label );
+
+               return $item;
+       }
+
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I86a78a1a275c7deb7a822e1188a1a04c9c37bcf5
Gerrit-PatchSet: 9
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to