Aleksey Bekh-Ivanov (WMDE) has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/376781 )

Change subject: [WIP] Diffing and Patching Lexeme forms and nextFormId
......................................................................

[WIP] Diffing and Patching Lexeme forms and nextFormId

Change-Id: Icfa5d5bfcbe7e48cab9f1d4c99eeba1bd656d39f
---
M src/DataModel/Lexeme.php
A src/DataModel/LexemePatchAccess.php
M src/DataModel/Services/Diff/LexemeDiff.php
M src/DataModel/Services/Diff/LexemeDiffer.php
M src/DataModel/Services/Diff/LexemePatcher.php
M tests/phpunit/composer/DataModel/LexemeTest.php
A tests/phpunit/composer/DataModel/Services/Diff/LexemeDifferPatcherTest.php
7 files changed, 241 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikibaseLexeme 
refs/changes/81/376781/1

diff --git a/src/DataModel/Lexeme.php b/src/DataModel/Lexeme.php
index 81aa582..b81ae22 100644
--- a/src/DataModel/Lexeme.php
+++ b/src/DataModel/Lexeme.php
@@ -296,6 +296,24 @@
        }
 
        /**
+        * @param int $number
+        */
+       public function increaseNextFormIdTo( $number ) {
+               if ( !is_int( $number ) ) {
+                       throw new \InvalidArgumentException( '$nextFormId` must 
be integer' );
+               }
+
+               if ( $number < $this->nextFormId ) {
+                       throw new \LogicException(
+                               "Cannot increase `nextFormId` because given 
number is less than counter value " .
+                               "of this Lexeme. Current=`{$this->nextFormId}`, 
given=`{$number}`"
+                       );
+               }
+
+               $this->nextFormId = $number;
+       }
+
+       /**
         * @param TermList $representations
         * @param ItemId[] $grammaticalFeatures
         *
@@ -313,6 +331,17 @@
                $this->forms->remove( $formId );
        }
 
+       public function patch( callable $patcher ) {
+               try {
+                       $lexemePatchAccess = new LexemePatchAccess();
+                       $patcher( $lexemePatchAccess );
+
+               } finally {
+                       $lexemePatchAccess->close();
+                       $this->assertCorrectNextFormIdIsGiven( 
$this->nextFormId, $this->forms );
+               }
+       }
+
        /**
         * @param mixed $nextFormId
         * @param Form[] $forms
diff --git a/src/DataModel/LexemePatchAccess.php 
b/src/DataModel/LexemePatchAccess.php
new file mode 100644
index 0000000..270ab4c
--- /dev/null
+++ b/src/DataModel/LexemePatchAccess.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Wikibase\Lexeme\DataModel;
+
+class LexemePatchAccess {
+
+       public function addForm( Form $form ) {
+       }
+
+       public function close() {
+       }
+
+}
diff --git a/src/DataModel/Services/Diff/LexemeDiff.php 
b/src/DataModel/Services/Diff/LexemeDiff.php
index ee9f4e3..7b9de37 100644
--- a/src/DataModel/Services/Diff/LexemeDiff.php
+++ b/src/DataModel/Services/Diff/LexemeDiff.php
@@ -20,6 +20,7 @@
         * @param DiffOp[] $operations
         */
        public function __construct( array $operations = [] ) {
+               //TODO Probably can be removed. Does it do anything useful?
                $this->fixSubstructureDiff( $operations, 'lemmas' );
                $this->fixSubstructureDiff( $operations, 'lexicalCategory' );
                $this->fixSubstructureDiff( $operations, 'language' );
@@ -56,13 +57,24 @@
        }
 
        /**
+        * @return Diff
+        */
+       public function getFormsDiff() {
+               return isset( $this['forms'] ) ? $this['forms'] : new Diff( [], 
true );
+       }
+
+       /**
         * Returns if there are any changes (equivalent to: any differences 
between the entities).
         *
         * @return bool
         */
        public function isEmpty() {
                return $this->getLemmasDiff()->isEmpty()
-                      && $this->getClaimsDiff()->isEmpty();
+                          && $this->getClaimsDiff()->isEmpty();
+       }
+
+       public function getNextFormIdDiff() {
+               return $this['nextFormId'];
        }
 
 }
diff --git a/src/DataModel/Services/Diff/LexemeDiffer.php 
b/src/DataModel/Services/Diff/LexemeDiffer.php
index 374c147..fb4fff2 100644
--- a/src/DataModel/Services/Diff/LexemeDiffer.php
+++ b/src/DataModel/Services/Diff/LexemeDiffer.php
@@ -3,11 +3,14 @@
 namespace Wikibase\Lexeme\DataModel\Services\Diff;
 
 use Diff\Differ\MapDiffer;
+use Diff\DiffOp\Diff\Diff;
+use Diff\DiffOp\DiffOpChange;
 use UnexpectedValueException;
 use Wikibase\DataModel\Entity\EntityDocument;
 use Wikibase\DataModel\Services\Diff\EntityDiff;
 use Wikibase\DataModel\Services\Diff\EntityDifferStrategy;
 use Wikibase\DataModel\Services\Diff\StatementListDiffer;
+use Wikibase\Lexeme\DataModel\Form;
 use Wikibase\Lexeme\DataModel\Lexeme;
 use Wikimedia\Assert\Assert;
 use InvalidArgumentException;
@@ -75,6 +78,13 @@
                        $to->getStatements()
                );
 
+               $diffOps['nextFormId'] = $this->getNextFormIdCounterDiff( 
$from, $to );
+
+               $diffOps['forms'] = $this->getFormsDiff(
+                       $from->getForms(),
+                       $to->getForms()
+               );
+
                return new LexemeDiff( $diffOps );
        }
 
@@ -132,4 +142,43 @@
                return $this->diffEntities( $entity, new Lexeme() );
        }
 
+       /**
+        * @param Form[] $from
+        * @param Form[] $to
+        *
+        * @return Diff;
+        */
+       private function getFormsDiff( array $from, array $to ) {
+               $differ = new MapDiffer();
+
+               $differ->setComparisonCallback( function ( Form $from, Form $to 
) {
+                       return $from == $to;
+               } );
+
+               $from = $this->toFormDiffArray( $from );
+               $to = $this->toFormDiffArray( $to );
+
+               return new Diff( $differ->doDiff( $from, $to ), true );
+       }
+
+       /**
+        * @param Form[] $forms
+        */
+       private function toFormDiffArray( array $forms ) {
+               $result = [];
+               foreach ( $forms as $form ) {
+                       $result[$form->getId()->getSerialization()] = $form;
+               }
+
+               return $result;
+       }
+
+       private function getNextFormIdCounterDiff( Lexeme $from, Lexeme $to ) {
+               if ( $to->getNextFormId() <= $from->getNextFormId() ) {
+                       return new Diff( [] );
+               }
+
+               return new Diff( [ new DiffOpChange( $from->getNextFormId(), 
$to->getNextFormId() ) ] );
+       }
+
 }
diff --git a/src/DataModel/Services/Diff/LexemePatcher.php 
b/src/DataModel/Services/Diff/LexemePatcher.php
index 0ec031c..8f42acd 100644
--- a/src/DataModel/Services/Diff/LexemePatcher.php
+++ b/src/DataModel/Services/Diff/LexemePatcher.php
@@ -15,6 +15,7 @@
 use Wikibase\DataModel\Services\Diff\StatementListPatcher;
 use Wikibase\DataModel\Services\Diff\TermListPatcher;
 use Wikibase\DataModel\Term\TermList;
+use Wikibase\Lexeme\DataModel\Form;
 use Wikibase\Lexeme\DataModel\Lexeme;
 use Wikimedia\Assert\Assert;
 
@@ -57,9 +58,11 @@
         */
        public function patchEntity( EntityDocument $entity, EntityDiff $patch 
) {
                Assert::parameterType( Lexeme::class, $entity, '$entity' );
-
+               Assert::parameterType( LexemeDiff::class, $patch, '$patch' );
                /** @var Lexeme $entity */
                /** @var LexemeDiff $patch */
+
+               //TODO Lemmas can't be null. Redundant check
                $lemmas = $entity->getLemmas() !== null ? $entity->getLemmas() 
: new TermList();
                $this->termListPatcher->patchTermList(
                        $lemmas,
@@ -80,6 +83,35 @@
                $itemId = $this->getPatchedItemId( $patch->getLanguageDiff() );
                if ( $itemId !== false ) {
                        $entity->setLanguage( $itemId );
+               }
+
+               $this->patchNextFormId( $entity, $patch );
+//             nextFormId
+
+               $formsDiff = $patch->getFormsDiff();
+               foreach ( $formsDiff as $formDiff ) {
+                       switch ( get_class( $formDiff ) ) {
+                               case DiffOpAdd::class:
+                                       /** @var DiffOpAdd $formDiff */
+                                       /** @var Form $form */
+                                       //TODO This is obviously wrong. Needs 
proper implementation.
+                                       $form = $formDiff->getNewValue();
+                                       $entity->addForm(
+                                               $form->getRepresentations(),
+                                               $form->getGrammaticalFeatures()
+                                       );
+                                       break;
+                               case DiffOpRemove::class:
+                                       /** @var DiffOpRemove $formDiff */
+                                       /** @var Form $form */
+                                       $form = $formDiff->getOldValue();
+                                       $entity->removeForm(
+                                               $form->getId()
+                                       );
+                                       break;
+                               default:
+                                       throw new PatcherException( 'Invalid 
forms list diff' );
+                       }
                }
        }
 
@@ -112,4 +144,21 @@
                throw new PatcherException( 'Invalid ItemId diff' );
        }
 
+       private function patchNextFormId( Lexeme $entity, LexemeDiff $patch ) {
+               $nextFormIdDiffList = $patch->getNextFormIdDiff();
+               foreach ( $nextFormIdDiffList as $nextFormIdDiff ) {
+                       switch ( get_class( $nextFormIdDiff ) ) {
+                               case DiffOpChange::class:
+                                       /** @var DiffOpChange $nextFormIdDiff */
+                                       $newNumber = 
$nextFormIdDiff->getNewValue();
+                                       if ( $newNumber > 
$entity->getNextFormId() ) {
+                                               $entity->increaseNextFormIdTo( 
$newNumber );
+                                       }
+                                       break;
+                               default:
+                                       throw new PatcherException( 'Invalid 
forms list diff' );
+                       }
+               }
+       }
+
 }
diff --git a/tests/phpunit/composer/DataModel/LexemeTest.php 
b/tests/phpunit/composer/DataModel/LexemeTest.php
index 711bd19..6346c1b 100644
--- a/tests/phpunit/composer/DataModel/LexemeTest.php
+++ b/tests/phpunit/composer/DataModel/LexemeTest.php
@@ -464,4 +464,28 @@
                $this->assertEquals( [], $lexeme->getForms() );
        }
 
+       public function 
testIncreaseNextFormIdTo_GivenLexemWithGreaterId_Increases() {
+               $lexemeWithoutForm = NewLexeme::create()->build();
+               $this->assertEquals( 1, $lexemeWithoutForm->getNextFormId() );
+
+               $lexemeWithoutForm->increaseNextFormIdTo( 2 );
+
+               $this->assertEquals( 2, $lexemeWithoutForm->getNextFormId() );
+       }
+
+       public function 
testIncreaseNextFormIdTo_GivenLexemWithSmallerId_ThrowsAnException() {
+               $lexemeWithForm = NewLexeme::havingForm( NewForm::havingId( 
'F1' ) )->build();
+               $this->assertEquals( 2, $lexemeWithForm->getNextFormId() );
+
+               $this->setExpectedException( \Exception::class );
+               $lexemeWithForm->increaseNextFormIdTo( 1 );
+       }
+
+       public function 
testIncreaseNextFormIdTo_GivenNonInteger_ThrowsAnException() {
+               $lexeme = NewLexeme::havingId( 'L1' )->build();
+
+               $this->setExpectedException( \Exception::class );
+               $lexeme->increaseNextFormIdTo( 2.0 );
+       }
+
 }
diff --git 
a/tests/phpunit/composer/DataModel/Services/Diff/LexemeDifferPatcherTest.php 
b/tests/phpunit/composer/DataModel/Services/Diff/LexemeDifferPatcherTest.php
new file mode 100644
index 0000000..69e0832
--- /dev/null
+++ b/tests/phpunit/composer/DataModel/Services/Diff/LexemeDifferPatcherTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Wikibase\Lexeme\Tests\DataModel\Services\Diff;
+
+use Wikibase\Lexeme\DataModel\FormId;
+use Wikibase\Lexeme\DataModel\Services\Diff\LexemeDiffer;
+use Wikibase\Lexeme\DataModel\Services\Diff\LexemePatcher;
+use Wikibase\Lexeme\Tests\DataModel\NewForm;
+use Wikibase\Lexeme\Tests\DataModel\NewLexeme;
+
+class LexemeDifferPatcherTest extends \PHPUnit_Framework_TestCase {
+
+       public function testAddedFormIsDiffedAndPatched() {
+               $differ = new LexemeDiffer();
+               $patcher = new LexemePatcher();
+               $initialLexeme = NewLexeme::create();
+               $lexemeWithoutForm = $initialLexeme->build();
+               $lexemeWithForm = $initialLexeme->withForm( NewForm::havingId( 
'F1' ) )->build();
+
+               $diff = $differ->diffLexemes( $lexemeWithoutForm, 
$lexemeWithForm );
+               $patcher->patchEntity( $lexemeWithoutForm, $diff );
+
+               $this->assertTrue(
+                       $lexemeWithoutForm->equals( $lexemeWithForm ),
+                       "Lexemes are not equal"
+               );
+       }
+
+       public function testRemovedFormIsDiffedAndPatched() {
+               $differ = new LexemeDiffer();
+               $patcher = new LexemePatcher();
+               $initialLexeme = NewLexeme::create();
+               $lexemeWithForm = $initialLexeme->withForm( NewForm::havingId( 
'F1' ) )->build();
+               $lexemeWithoutForm = $initialLexeme->build();
+
+               $diff = $differ->diffLexemes( $lexemeWithForm, 
$lexemeWithoutForm );
+               $patcher->patchEntity( $lexemeWithForm, $diff );
+
+               $this->assertEquals( [], $lexemeWithForm->getForms() );
+       }
+
+       public function testDiffAndPatchCanIncreaseNextFormIdCounter() {
+               $differ = new LexemeDiffer();
+               $patcher = new LexemePatcher();
+               $initialLexeme = NewLexeme::create();
+               $lexemeWithoutForm = $initialLexeme->build();
+               $lexemeThatHadForm = $initialLexeme->withForm( 
NewForm::havingId( 'F1' ) )->build();
+               $lexemeThatHadForm->removeForm( new FormId( 'F1' ) );
+
+               $diff = $differ->diffLexemes( $lexemeWithoutForm, 
$lexemeThatHadForm );
+               $patcher->patchEntity( $lexemeWithoutForm, $diff );
+
+               $this->assertEquals(
+                       $lexemeThatHadForm->getNextFormId(),
+                       $lexemeWithoutForm->getNextFormId()
+               );
+               $this->assertTrue(
+                       $lexemeWithoutForm->equals( $lexemeThatHadForm ),
+                       "Lexemes are not equal"
+               );
+       }
+
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Icfa5d5bfcbe7e48cab9f1d4c99eeba1bd656d39f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikibaseLexeme
Gerrit-Branch: master
Gerrit-Owner: Aleksey Bekh-Ivanov (WMDE) <aleksey.bekh-iva...@wikimedia.de>

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

Reply via email to