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

Change subject: Check for conflicts in ChangeOpsMerge preSave
......................................................................


Check for conflicts in ChangeOpsMerge preSave

Now now make sure that after applying the resulting
items make sense given the constraints that should
be in place

We also refactor the LabelDescriptionDuplicateDetector
slightly in this change

Bug: 55960
Change-Id: I07667e8a2c60b113586a01312eb513482fb04c11
---
M repo/includes/ChangeOp/ChangeOpsMerge.php
M repo/includes/LabelDescriptionDuplicateDetector.php
M repo/includes/PreSaveChecks.php
M repo/includes/api/MergeItems.php
M repo/includes/specials/SpecialMergeItems.php
M repo/tests/phpunit/includes/ChangeOp/ChangeOpsMergeTest.php
M repo/tests/phpunit/includes/LabelDescriptionDuplicateDetectorTest.php
A repo/tests/phpunit/includes/MockTermCache.php
8 files changed, 377 insertions(+), 108 deletions(-)

Approvals:
  Tobias Gritschacher: Looks good to me, approved
  WikidataJenkins: Verified
  jenkins-bot: Verified



diff --git a/repo/includes/ChangeOp/ChangeOpsMerge.php 
b/repo/includes/ChangeOp/ChangeOpsMerge.php
index e106012..75132c4 100644
--- a/repo/includes/ChangeOp/ChangeOpsMerge.php
+++ b/repo/includes/ChangeOp/ChangeOpsMerge.php
@@ -5,9 +5,14 @@
 use InvalidArgumentException;
 use Wikibase\DataModel\Claim\Claim;
 use Wikibase\DataModel\Claim\Statement;
+use Wikibase\DataModel\Entity\ItemId;
 use Wikibase\DataModel\Reference;
 use Wikibase\ItemContent;
+use Wikibase\LabelDescriptionDuplicateDetector;
 use Wikibase\Lib\ClaimGuidGenerator;
+use Wikibase\SiteLinkCache;
+use Wikibase\StoreFactory;
+use Wikibase\Term;
 
 /**
  * @since 0.5
@@ -23,16 +28,24 @@
        private $toChangeOps;
        /** @var array */
        private $ignoreConflicts;
+       /** @var LabelDescriptionDuplicateDetector */
+       private $labelDescriptionDuplicateDetector;
+       /** @var SitelinkCache */
+       private $sitelinkCache;
 
        /**
         * @param ItemContent $fromItemContent
         * @param ItemContent $toItemContent
+        * @param LabelDescriptionDuplicateDetector 
$labelDescriptionDuplicateDetector
+        * @param SitelinkCache $sitelinkCache
         * @param array $ignoreConflicts list of elements to ignore conflicts 
for
         *   can only contain 'label' and or 'description' and or 'sitelink'
         */
        public function __construct(
                ItemContent $fromItemContent,
                ItemContent $toItemContent,
+               LabelDescriptionDuplicateDetector 
$labelDescriptionDuplicateDetector,
+               SitelinkCache $sitelinkCache,
                $ignoreConflicts = array()
        ) {
                $this->fromItemContent = $fromItemContent;
@@ -41,6 +54,8 @@
                $this->toChangeOps = new ChangeOps();
                $this->assertValidIgnoreConflictValues( $ignoreConflicts );
                $this->ignoreConflicts = $ignoreConflicts;
+               $this->labelDescriptionDuplicateDetector = 
$labelDescriptionDuplicateDetector;
+               $this->sitelinkCache = $sitelinkCache;
        }
 
        /**
@@ -63,6 +78,7 @@
                $this->generateChangeOps();
                $this->fromChangeOps->apply( $this->fromItemContent->getItem() 
);
                $this->toChangeOps->apply( $this->toItemContent->getItem() );
+               $this->applyConstraintChecks();
        }
 
        private function generateChangeOps() {
@@ -188,4 +204,91 @@
                }
        }
 
+       /**
+        * Throws an exception if it would not be possible to save the second 
item
+        * @throws ChangeOpException
+        */
+       private function applyConstraintChecks() {
+               $conflictingTerms = 
$this->labelDescriptionDuplicateDetector->getConflictingTerms(
+                       $this->toItemContent->getItem()
+               );
+               $conflictingSitelinks = 
$this->sitelinkCache->getConflictsForItem( $this->toItemContent->getItem() );
+
+               $conflictString = '';
+               if( $conflictingTerms !== array() ) {
+                       $conflictString .= $this->getConflictStringForTerms( 
$conflictingTerms );
+               }
+               if( $conflictingSitelinks !== array() ) {
+                       $conflictString .= 
$this->getConflictStringForSitelinks( $conflictingSitelinks );
+               }
+
+               if( $conflictString !== '' ) {
+                       throw new ChangeOpException( 'Item being merged to has 
conflicting terms: ' . $conflictString );
+               }
+       }
+
+       /**
+        * @param Term[] $conflictingTerms
+        *
+        * @return string
+        */
+       private function getConflictStringForTerms( $conflictingTerms ) {
+               $conflictString = '';
+               foreach( $conflictingTerms as $term ) {
+                       $conflictString .= $this->getConflictStringForTerm( 
$term );
+               }
+               return $conflictString;
+       }
+
+       /**
+        * @param Term $term
+        *
+        * @return string
+        */
+       private function getConflictStringForTerm( $term ) {
+               $itemId = ItemId::newFromNumber( $term->getEntityId() );
+               if( !$itemId->equals( 
$this->fromItemContent->getItem()->getId() ) ) {
+                       return '(' .
+                               $itemId->getSerialization() . ' => ' .
+                               $term->getLanguage() . ' => ' .
+                               $term->getType() . ' => ' .
+                               $term->getText() . ') ';
+               }
+               return '';
+       }
+
+       /**
+        * @param array $conflictingSitelinks array of arrays each with the 
keys:
+        *     - itemId => integer
+        *     - siteId => string
+        *     - sitePage => string
+        * @return string
+        */
+       private function getConflictStringForSitelinks( $conflictingSitelinks ) 
{
+               $conflictString = '';
+               foreach( $conflictingSitelinks as $sitelink ) {
+                       $conflictString .= $this->getConflictStringForSitelink( 
$sitelink );
+               }
+               return $conflictString;
+       }
+
+       /**
+        * @param array $sitelink array with the keys:
+        *     - itemId => integer
+        *     - siteId => string
+        *     - sitePage => string
+        *
+        * @return string
+        */
+       private function getConflictStringForSitelink( $sitelink ) {
+               $itemId = ItemId::newFromNumber( $sitelink['itemId'] );
+               if( !$itemId->equals( 
$this->fromItemContent->getItem()->getId() ) ) {
+                       return '(' .
+                               $itemId->getSerialization() . ' => ' .
+                               $sitelink['siteId'] . ' => ' .
+                               $sitelink['sitePage'] . ') ';
+               }
+               return '';
+       }
+
 }
\ No newline at end of file
diff --git a/repo/includes/LabelDescriptionDuplicateDetector.php 
b/repo/includes/LabelDescriptionDuplicateDetector.php
index 021b838..eb06fc8 100644
--- a/repo/includes/LabelDescriptionDuplicateDetector.php
+++ b/repo/includes/LabelDescriptionDuplicateDetector.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace Wikibase;
+
 use Status;
 use Diff\Diff;
 
@@ -11,8 +12,23 @@
  *
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < jeroended...@gmail.com >
+ * @author Adam Shorland
  */
 class LabelDescriptionDuplicateDetector {
+
+       /**
+        * @var TermCombinationMatchFinder
+        */
+       private $termCache;
+
+       /**
+        * @param TermCombinationMatchFinder $termCache
+        *
+        * @since 0.5
+        */
+       public function __construct( TermCombinationMatchFinder $termCache ) {
+               $this->termCache = $termCache;
+       }
 
        /**
         * Looks for label+description violations in the provided Entity using
@@ -23,11 +39,10 @@
         * @since 0.4
         *
         * @param Entity $entity
-        * @param TermCombinationMatchFinder $termCache
         *
         * @return Term[]
         */
-       public function getConflictingTerms( Entity $entity, 
TermCombinationMatchFinder $termCache ) {
+       public function getConflictingTerms( Entity $entity ) {
                $terms = array();
 
                foreach ( $entity->getLabels() as $langCode => $labelText ) {
@@ -54,7 +69,7 @@
                        return array();
                }
 
-               $foundTerms = $termCache->getMatchingTermCombination(
+               $foundTerms = $this->termCache->getMatchingTermCombination(
                        $terms,
                        null,
                        $entity->getType(),
@@ -74,14 +89,16 @@
         *
         * @param Entity $entity The Entity for which to check if it has any 
non-unique label+description pairs
         * @param Status $status The status to which to add an error if there 
is a violation
-        * @param TermCombinationMatchFinder $termCache The TermIndex to use 
for conflict detection
         * @param Diff|null $labelsDiff
         * @param Diff|null $descriptionDiff
         */
-       public function addLabelDescriptionConflicts( Entity $entity, Status 
$status, TermCombinationMatchFinder $termCache,
-                                                                               
                  Diff $labelsDiff = null, Diff $descriptionDiff = null ) {
-
-               $foundTerms = $this->getConflictingTerms( $entity, $termCache );
+       public function addLabelDescriptionConflicts(
+               Entity $entity,
+               Status $status,
+               Diff $labelsDiff = null,
+               Diff $descriptionDiff = null
+       ) {
+               $foundTerms = $this->getConflictingTerms( $entity );
 
                if ( !empty( $foundTerms ) ) {
                        /**
diff --git a/repo/includes/PreSaveChecks.php b/repo/includes/PreSaveChecks.php
index daa3477..7718129 100644
--- a/repo/includes/PreSaveChecks.php
+++ b/repo/includes/PreSaveChecks.php
@@ -58,12 +58,13 @@
                        // caused by the edit. This can be improved by only 
looking for
                        // those conflicts that can be caused by the edit.
 
-                       $termViolationDetector = new 
LabelDescriptionDuplicateDetector();
+                       $termViolationDetector = new 
LabelDescriptionDuplicateDetector(
+                               $this->termIndex
+                       );
 
                        $termViolationDetector->addLabelDescriptionConflicts(
                                $entity,
                                $status,
-                               $this->termIndex,
                                $entityDiff === null ? null : 
$entityDiff->getLabelsDiff(),
                                $entityDiff === null ? null : 
$entityDiff->getDescriptionsDiff()
                        );
diff --git a/repo/includes/api/MergeItems.php b/repo/includes/api/MergeItems.php
index 35efe21..cac5e55 100644
--- a/repo/includes/api/MergeItems.php
+++ b/repo/includes/api/MergeItems.php
@@ -11,7 +11,9 @@
 use Wikibase\DataModel\Entity\ItemId;
 use Wikibase\EntityContent;
 use Wikibase\ItemContent;
+use Wikibase\LabelDescriptionDuplicateDetector;
 use Wikibase\Repo\WikibaseRepo;
+use Wikibase\StoreFactory;
 use Wikibase\Summary;
 
 /**
@@ -55,6 +57,8 @@
                }
 
                $ignoreConflicts = $this->getIgnoreConflicts( $params );
+               $sitelinkCache = 
WikibaseRepo::getDefaultInstance()->getStore()->newSiteLinkCache();
+               $termIndex = 
WikibaseRepo::getDefaultInstance()->getStore()->getTermIndex();
 
                /**
                 * @var ItemContent $fromEntityContent
@@ -64,6 +68,10 @@
                        $changeOps = new ChangeOpsMerge(
                                $fromEntityContent,
                                $toEntityContent,
+                               new LabelDescriptionDuplicateDetector(
+                                       $termIndex
+                               ),
+                               $sitelinkCache,
                                $ignoreConflicts
                        );
                        $changeOps->apply();
diff --git a/repo/includes/specials/SpecialMergeItems.php 
b/repo/includes/specials/SpecialMergeItems.php
index 8860e70..cafee36 100644
--- a/repo/includes/specials/SpecialMergeItems.php
+++ b/repo/includes/specials/SpecialMergeItems.php
@@ -10,6 +10,9 @@
 use Wikibase\ChangeOp\ChangeOpException;
 use Wikibase\EntityContent;
 use Wikibase\ItemContent;
+use Wikibase\LabelDescriptionDuplicateDetector;
+use Wikibase\Repo\WikibaseRepo;
+use Wikibase\StoreFactory;
 use Wikibase\Summary;
 use Wikibase\DataModel\Entity\EntityId;
 use Status;
@@ -140,10 +143,16 @@
                if ( $this->fromItemContent === null || $this->toItemContent 
=== null ) {
                        return false;
                }
+               $sitelinkCache = 
WikibaseRepo::getDefaultInstance()->getStore()->newSiteLinkCache();
+               $termIndex = 
WikibaseRepo::getDefaultInstance()->getStore()->getTermIndex();
                try {
                        $changeOps = new ChangeOpsMerge(
                                $this->fromItemContent,
                                $this->toItemContent,
+                               new LabelDescriptionDuplicateDetector(
+                                       $termIndex
+                               ),
+                               $sitelinkCache,
                                $this->ignoreConflicts
                        );
                        $changeOps->apply();
@@ -324,4 +333,4 @@
                . Html::element( 'br' );
                // TODO: Here should be a way to easily ignore conflicts
        }
-}
\ No newline at end of file
+}
diff --git a/repo/tests/phpunit/includes/ChangeOp/ChangeOpsMergeTest.php 
b/repo/tests/phpunit/includes/ChangeOp/ChangeOpsMergeTest.php
index b4bb1ef..6005c61 100644
--- a/repo/tests/phpunit/includes/ChangeOp/ChangeOpsMergeTest.php
+++ b/repo/tests/phpunit/includes/ChangeOp/ChangeOpsMergeTest.php
@@ -20,11 +20,35 @@
  */
 class ChangeOpsMergeTest extends \PHPUnit_Framework_TestCase {
 
+       private function getMockLabelDescriptionDuplicateDetector( $callTimes, 
$returnValue = array() ) {
+               $mock = $this->getMockBuilder( 
'\Wikibase\LabelDescriptionDuplicateDetector' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $mock->expects( $this->exactly( $callTimes ) )
+                       ->method( 'getConflictingTerms' )
+                       ->will( $this->returnValue( $returnValue ) );
+               return $mock;
+       }
+
+       private function getMockSitelinkCache( $callTimes, $returnValue = 
array() ) {
+               $mock = $this->getMock( '\Wikibase\SiteLinkCache' );
+               $mock->expects( $this->exactly( $callTimes ) )
+                       ->method( 'getConflictsForItem' )
+                       ->will( $this->returnValue( $returnValue ) );
+               return $mock;
+       }
+
        /**
         * @dataProvider provideValidConstruction
         */
        public function testCanConstruct( $from, $to, $ignoreConflicts ) {
-               $changeOps = new ChangeOpsMerge( $from, $to, $ignoreConflicts );
+               $changeOps = new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 0 ),
+                       $this->getMockSitelinkCache( 0 ),
+                       $ignoreConflicts
+               );
                $this->assertInstanceOf( '\Wikibase\ChangeOp\ChangeOpsMerge', 
$changeOps );
        }
 
@@ -45,7 +69,13 @@
         */
        public function testInvalidIgnoreConflicts( $from, $to, 
$ignoreConflicts ) {
                $this->setExpectedException( 'InvalidArgumentException' );
-               new ChangeOpsMerge( $from, $to, $ignoreConflicts );
+               new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 0 ),
+                       $this->getMockSitelinkCache( 0 ),
+                       $ignoreConflicts
+               );
        }
 
        public static function provideInvalidConstruction(){
@@ -72,7 +102,13 @@
        public function testCanApply( $fromData, $toData, $expectedFromData, 
$expectedToData, $ignoreConflicts = array() ) {
                $from = self::getItemContent( 'Q111', $fromData );
                $to = self::getItemContent( 'Q222', $toData );
-               $changeOps = new ChangeOpsMerge( $from, $to, $ignoreConflicts );
+               $changeOps = new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 1 ),
+                       $this->getMockSitelinkCache( 1 ),
+                       $ignoreConflicts
+               );
 
                $this->assertTrue( $from->getEntity()->equals( new Item( 
$fromData ) ), 'FromItem was not filled correctly' );
                $this->assertTrue( $to->getEntity()->equals( new Item( $toData 
) ), 'ToItem was not filled correctly' );
@@ -281,4 +317,91 @@
                return $testCases;
        }
 
+       private function getMockTerm( $entityId, $language, $type, $text ) {
+               $mock = $this->getMock( '\Wikibase\Term' );
+               $mock->expects( $this->once() )
+                       ->method( 'getEntityId' )
+                       ->will( $this->returnValue( $entityId ) );
+               $mock->expects( $this->any() )
+                       ->method( 'getLanguage' )
+                       ->will( $this->returnValue( $language ) );
+               $mock->expects( $this->any() )
+                       ->method( 'getType' )
+                       ->will( $this->returnValue( $type ) );
+               $mock->expects( $this->any() )
+                       ->method( 'getText' )
+                       ->will( $this->returnValue( $text ) );
+               return $mock;
+       }
+
+       public function 
testExceptionThrownWhenLabelDescriptionDuplicatesDetected() {
+               $conflicts = array( $this->getMockTerm( 999, 'imalang', 
'imatype', 'foog text' ) );
+               $from = self::getItemContent( 'Q111', array() );
+               $to = self::getItemContent( 'Q222', array() );
+               $changeOps = new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 1, 
$conflicts ),
+                       $this->getMockSitelinkCache( 1 ),
+                       array()
+               );
+
+               $this->setExpectedException(
+                       '\Wikibase\ChangeOp\ChangeOpException',
+                       'Item being merged to has conflicting terms: (Q999 => 
imalang => imatype => foog text)'
+               );
+               $changeOps->apply();
+       }
+
+       public function 
testExceptionNotThrownWhenLabelDescriptionDuplicatesDetectedOnFromItem() {
+               $conflicts = array( $this->getMockTerm( 111, 'imalang', 
'imatype', 'foog text' ) );
+               $from = self::getItemContent( 'Q111', array() );
+               $to = self::getItemContent( 'Q222', array() );
+               $changeOps = new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 1, 
$conflicts ),
+                       $this->getMockSitelinkCache( 1 ),
+                       array()
+               );
+
+               $changeOps->apply();
+               $this->assertTrue( true ); // no exception thrown
+       }
+
+       public function testExceptionThrownWhenSitelinkDuplicatesDetected() {
+               $conflicts = array( array( 'itemId' => 8888, 'siteId' => 
'eewiki', 'sitePage' => 'imapage' ) );
+               $from = self::getItemContent( 'Q111', array() );
+               $to = self::getItemContent( 'Q222', array() );
+               $changeOps = new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 1 ),
+                       $this->getMockSitelinkCache( 1, $conflicts ),
+                       array()
+               );
+
+               $this->setExpectedException(
+                       '\Wikibase\ChangeOp\ChangeOpException',
+                       'Item being merged to has conflicting terms: (Q8888 => 
eewiki => imapage)'
+               );
+               $changeOps->apply();
+       }
+
+       public function 
testExceptionNotThrownWhenSitelinkDuplicatesDetectedOnFromItem() {
+               $conflicts = array( array( 'itemId' => 111, 'siteId' => 
'eewiki', 'sitePage' => 'imapage' ) );
+               $from = self::getItemContent( 'Q111', array() );
+               $to = self::getItemContent( 'Q222', array() );
+               $changeOps = new ChangeOpsMerge(
+                       $from,
+                       $to,
+                       $this->getMockLabelDescriptionDuplicateDetector( 1 ),
+                       $this->getMockSitelinkCache( 1, $conflicts ),
+                       array()
+               );
+
+               $changeOps->apply();
+               $this->assertTrue( true ); // no exception thrown
+       }
+
 }
\ No newline at end of file
diff --git 
a/repo/tests/phpunit/includes/LabelDescriptionDuplicateDetectorTest.php 
b/repo/tests/phpunit/includes/LabelDescriptionDuplicateDetectorTest.php
index adf8713..5f3a181 100644
--- a/repo/tests/phpunit/includes/LabelDescriptionDuplicateDetectorTest.php
+++ b/repo/tests/phpunit/includes/LabelDescriptionDuplicateDetectorTest.php
@@ -8,7 +8,6 @@
 use Wikibase\EntityId;
 use Wikibase\Item;
 use Wikibase\LabelDescriptionDuplicateDetector;
-use Wikibase\Term;
 
 /**
  * @covers Wikibase\LabelDescriptionDuplicateDetector
@@ -70,9 +69,7 @@
         * @param $shouldConflict
         */
        public function testGetConflictingTerms( $langCode, $label, 
$description, $shouldConflict ) {
-               $termCache = new MockTermCache();
-
-               $detector = new LabelDescriptionDuplicateDetector();
+               $detector = new LabelDescriptionDuplicateDetector( new 
MockTermCache() );
 
                $entity = Item::newEmpty();
                $entity->setId( new EntityId( Item::ENTITY_TYPE, 1 ) );
@@ -80,7 +77,7 @@
                $entity->setDescription( $langCode, $description );
                $entity->setLabel( $langCode, $label );
 
-               $conflicts = $detector->getConflictingTerms( $entity, 
$termCache );
+               $conflicts = $detector->getConflictingTerms( $entity );
 
                if ( $shouldConflict ) {
                        $this->assertEquals( 2, count( $conflicts ) );
@@ -113,105 +110,19 @@
        ) {
                $termCache = new MockTermCache();
 
-               $detector = new LabelDescriptionDuplicateDetector();
+               $detector = new LabelDescriptionDuplicateDetector( $termCache );
 
                $entity = Item::newEmpty();
-               $entity->setId( new EntityId( \Wikibase\Item::ENTITY_TYPE, 1 ) 
);
+               $entity->setId( new EntityId( Item::ENTITY_TYPE, 1 ) );
 
                $entity->setDescription( $langCode, $description );
                $entity->setLabel( $langCode, $label );
 
                $status = new Status();
 
-               $detector->addLabelDescriptionConflicts( $entity, $status, 
$termCache, $labelsDiff, $descriptionDiff );
+               $detector->addLabelDescriptionConflicts( $entity, $status, 
$labelsDiff, $descriptionDiff );
 
                $this->assertEquals( $shouldConflict, !$status->isOK() );
-       }
-
-}
-
-class MockTermCache implements \Wikibase\TermCombinationMatchFinder {
-
-       /**
-        * @var Term[]
-        */
-       protected $terms;
-
-       public function __construct() {
-               $terms = array();
-
-               $terms[] = new \Wikibase\Term( array(
-                       'termType' => Term::TYPE_LABEL,
-                       'termLanguage' => 'en',
-                       'entityId' => 42,
-                       'entityType' => \Wikibase\Item::ENTITY_TYPE,
-                       'termText' => 'label-en',
-               ) );
-
-               $terms[] = new \Wikibase\Term( array(
-                       'termType' => Term::TYPE_LABEL,
-                       'termLanguage' => 'de',
-                       'entityId' => 42,
-                       'entityType' => \Wikibase\Item::ENTITY_TYPE,
-                       'termText' => 'label-de',
-               ) );
-
-               $terms[] = new \Wikibase\Term( array(
-                       'termType' => Term::TYPE_DESCRIPTION,
-                       'termLanguage' => 'en',
-                       'entityId' => 42,
-                       'entityType' => \Wikibase\Item::ENTITY_TYPE,
-                       'termText' => 'description-en',
-               ) );
-
-               $this->terms = $terms;
-       }
-
-       /**
-        * @see \Wikibase\TermCombinationMatchFinder::getMatchingTermCombination
-        *
-        * @param array $terms
-        * @param string|null $termType
-        * @param string|null $entityType
-        * @param EntityId|null $excludeId
-        *
-        * @return array
-        */
-       public function getMatchingTermCombination( array $terms, $termType = 
null, $entityType = null, EntityId $excludeId = null ) {
-               /**
-                * @var Term[] $termPair
-                * @var Term[] $matchingTerms
-                */
-               foreach ( $terms as $termPair ) {
-                       $matchingTerms = array();
-
-                       $id = null;
-                       $type = null;
-
-                       foreach ( $termPair as $term ) {
-                               foreach ( $this->terms as $storedTerm ) {
-                                       if ( $term->getText() === 
$storedTerm->getText()
-                                               && $term->getLanguage() === 
$storedTerm->getLanguage()
-                                               && $term->getType() === 
$storedTerm->getType() ) {
-
-                                               if ( $id === null ) {
-                                                       $id = 
$term->getEntityId();
-                                                       $type = 
$term->getEntityType();
-                                                       $matchingTerms[] = 
$term;
-                                               }
-                                               elseif ( $id === 
$term->getEntityId() && $type === $term->getEntityType() ) {
-                                                       $matchingTerms[] = 
$term;
-                                               }
-                                       }
-                               }
-                       }
-
-                       if ( count( $matchingTerms ) === count( $termPair ) ) {
-                               return $matchingTerms;
-                       }
-               }
-
-               return array();
        }
 
 }
diff --git a/repo/tests/phpunit/includes/MockTermCache.php 
b/repo/tests/phpunit/includes/MockTermCache.php
new file mode 100644
index 0000000..1489f2d
--- /dev/null
+++ b/repo/tests/phpunit/includes/MockTermCache.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace Wikibase\Test;
+
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\Item;
+use Wikibase\Term;
+
+/**
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroended...@gmail.com >
+ */
+class MockTermCache implements \Wikibase\TermCombinationMatchFinder {
+
+       /**
+        * @var Term[]
+        */
+       protected $terms;
+
+       public function __construct() {
+               $terms = array();
+
+               $terms[] = new Term( array(
+                       'termType' => Term::TYPE_LABEL,
+                       'termLanguage' => 'en',
+                       'entityId' => 42,
+                       'entityType' => Item::ENTITY_TYPE,
+                       'termText' => 'label-en',
+               ) );
+
+               $terms[] = new Term( array(
+                       'termType' => Term::TYPE_LABEL,
+                       'termLanguage' => 'de',
+                       'entityId' => 42,
+                       'entityType' => Item::ENTITY_TYPE,
+                       'termText' => 'label-de',
+               ) );
+
+               $terms[] = new Term( array(
+                       'termType' => Term::TYPE_DESCRIPTION,
+                       'termLanguage' => 'en',
+                       'entityId' => 42,
+                       'entityType' => Item::ENTITY_TYPE,
+                       'termText' => 'description-en',
+               ) );
+
+               $this->terms = $terms;
+       }
+
+       /**
+        * @see \Wikibase\TermCombinationMatchFinder::getMatchingTermCombination
+        *
+        * @param array $terms
+        * @param string|null $termType
+        * @param string|null $entityType
+        * @param EntityId|null $excludeId
+        *
+        * @return array
+        */
+       public function getMatchingTermCombination( array $terms, $termType = 
null, $entityType = null, EntityId $excludeId = null ) {
+               /**
+                * @var Term[] $termPair
+                * @var Term[] $matchingTerms
+                */
+               foreach ( $terms as $termPair ) {
+                       $matchingTerms = array();
+
+                       $id = null;
+                       $type = null;
+
+                       foreach ( $termPair as $term ) {
+                               foreach ( $this->terms as $storedTerm ) {
+                                       if ( $term->getText() === 
$storedTerm->getText()
+                                               && $term->getLanguage() === 
$storedTerm->getLanguage()
+                                               && $term->getType() === 
$storedTerm->getType() ) {
+
+                                               if ( $id === null ) {
+                                                       $id = 
$term->getEntityId();
+                                                       $type = 
$term->getEntityType();
+                                                       $matchingTerms[] = 
$term;
+                                               }
+                                               elseif ( $id === 
$term->getEntityId() && $type === $term->getEntityType() ) {
+                                                       $matchingTerms[] = 
$term;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if ( count( $matchingTerms ) === count( $termPair ) ) {
+                               return $matchingTerms;
+                       }
+               }
+
+               return array();
+       }
+
+}
\ No newline at end of file

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I07667e8a2c60b113586a01312eb513482fb04c11
Gerrit-PatchSet: 14
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Adrian Lang <adrian.l...@wikimedia.de>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Hoo man <h...@online.de>
Gerrit-Reviewer: Jeroen De Dauw <jeroended...@gmail.com>
Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de>
Gerrit-Reviewer: WikidataJenkins <wikidata-servi...@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