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