Skip to content

Commit

Permalink
Streamline FingerprintPatcher (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
thiemowmde authored and adrianheine committed Apr 20, 2016
1 parent 31dda19 commit f337392
Showing 1 changed file with 154 additions and 24 deletions.
178 changes: 154 additions & 24 deletions src/Diff/Internal/FingerprintPatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

namespace Wikibase\DataModel\Services\Diff\Internal;

use Diff\DiffOp\AtomicDiffOp;
use Diff\DiffOp\Diff\Diff;
use Diff\DiffOp\DiffOp;
use Diff\DiffOp\DiffOpAdd;
use Diff\DiffOp\DiffOpChange;
use Diff\DiffOp\DiffOpRemove;
use Diff\Patcher\MapPatcher;
use InvalidArgumentException;
use Diff\Patcher\PatcherException;
use Wikibase\DataModel\Services\Diff\EntityDiff;
use Wikibase\DataModel\Term\AliasGroupList;
use Wikibase\DataModel\Term\Fingerprint;
Expand All @@ -19,20 +24,11 @@
*/
class FingerprintPatcher {

/**
* @var MapPatcher
*/
private $patcher;

public function __construct() {
$this->patcher = new MapPatcher();
}

/**
* @param Fingerprint $fingerprint
* @param EntityDiff $patch
*
* @throws InvalidArgumentException
* @throws PatcherException
*/
public function patchFingerprint( Fingerprint $fingerprint, EntityDiff $patch ) {
$this->patchTermList( $fingerprint->getLabels(), $patch->getLabelsDiff() );
Expand All @@ -41,30 +37,164 @@ public function patchFingerprint( Fingerprint $fingerprint, EntityDiff $patch )
$this->patchAliasGroupList( $fingerprint->getAliasGroups(), $patch->getAliasesDiff() );
}

/**
* @param TermList $terms
* @param Diff $patch
*
* @throws PatcherException
*/
private function patchTermList( TermList $terms, Diff $patch ) {
$original = $terms->toTextArray();
$patched = $this->patcher->patch( $original, $patch );

foreach ( $patched as $languageCode => $text ) {
$terms->setTextForLanguage( $languageCode, $text );
foreach ( $patch as $lang => $diffOp ) {
$this->patchTerm( $terms, $lang, $diffOp );
}
}

foreach ( array_diff_key( $original, $patched ) as $languageCode => $text ) {
$terms->removeByLanguage( $languageCode );
/**
* @see MapPatcher
*
* @param TermList $terms
* @param string $lang
* @param AtomicDiffOp $diffOp
*
* @throws PatcherException
*/
private function patchTerm( TermList $terms, $lang, AtomicDiffOp $diffOp ) {
$hasLang = $terms->hasTermForLanguage( $lang );

if ( $diffOp instanceof DiffOpAdd ) {
if ( !$hasLang ) {
$terms->setTextForLanguage( $lang, $diffOp->getNewValue() );
}
} elseif ( $diffOp instanceof DiffOpChange ) {
if ( $hasLang
&& $terms->getByLanguage( $lang )->getText() === $diffOp->getOldValue()
) {
$terms->setTextForLanguage( $lang, $diffOp->getNewValue() );
}
} elseif ( $diffOp instanceof DiffOpRemove ) {
if ( $hasLang
&& $terms->getByLanguage( $lang )->getText() === $diffOp->getOldValue()
) {
$terms->removeByLanguage( $lang );
}
} else {
throw new PatcherException( 'Invalid terms diff' );
}
}

/**
* @param AliasGroupList $groups
* @param Diff $patch
*
* @throws PatcherException
*/
private function patchAliasGroupList( AliasGroupList $groups, Diff $patch ) {
$original = $groups->toTextArray();
$patched = $this->patcher->patch( $original, $patch );
foreach ( $patch as $lang => $diffOp ) {
$this->patchAliasGroup( $groups, $lang, $diffOp );
}
}

/**
* @see MapPatcher
*
* @param AliasGroupList $groups
* @param string $lang
* @param DiffOp $diffOp
*
* @throws PatcherException
*/
private function patchAliasGroup( AliasGroupList $groups, $lang, DiffOp $diffOp ) {
$hasLang = $groups->hasGroupForLanguage( $lang );

foreach ( $patched as $languageCode => $aliases ) {
$groups->setAliasesForLanguage( $languageCode, $aliases );
if ( $diffOp instanceof DiffOpAdd ) {
if ( !$hasLang ) {
$groups->setAliasesForLanguage( $lang, $diffOp->getNewValue() );
}
} elseif ( $diffOp instanceof DiffOpChange ) {
$this->applyAliasGroupChange( $groups, $lang, $diffOp );
} elseif ( $diffOp instanceof DiffOpRemove ) {
if ( $hasLang
&& $groups->getByLanguage( $lang )->getAliases() === $diffOp->getOldValue()
) {
$groups->removeByLanguage( $lang );
}
} elseif ( $diffOp instanceof Diff ) {
$this->applyAliasGroupDiff( $groups, $lang, $diffOp );
} else {
throw new PatcherException( 'Invalid aliases diff' );
}
}

/**
* @param AliasGroupList $groups
* @param string $lang
* @param DiffOpChange $patch
*/
private function applyAliasGroupChange( AliasGroupList $groups, $lang, DiffOpChange $patch ) {
if ( $groups->hasGroupForLanguage( $lang )
&& $groups->getByLanguage( $lang )->getAliases() === $patch->getOldValue()
) {
$groups->setAliasesForLanguage( $lang, $patch->getNewValue() );
}
}

/**
* @param AliasGroupList $groups
* @param string $lang
* @param Diff $patch
*/
private function applyAliasGroupDiff( AliasGroupList $groups, $lang, Diff $patch ) {
$hasLang = $groups->hasGroupForLanguage( $lang );

if ( $hasLang || !$this->containsOperationsOnOldValues( $patch ) ) {
$aliases = $hasLang ? $groups->getByLanguage( $lang )->getAliases() : array();
$aliases = $this->getPatchedAliases( $aliases, $patch );
$groups->setAliasesForLanguage( $lang, $aliases );
}
}

foreach ( array_diff_key( $original, $patched ) as $languageCode => $aliases ) {
$groups->removeByLanguage( $languageCode );
/**
* @param Diff $diff
*
* @return bool
*/
private function containsOperationsOnOldValues( Diff $diff ) {
return $diff->getChanges() !== array()
|| $diff->getRemovals() !== array();
}

/**
* @see ListPatcher
*
* @param string[] $aliases
* @param Diff $patch
*
* @throws PatcherException
* @return string[]
*/
private function getPatchedAliases( array $aliases, Diff $patch ) {
foreach ( $patch as $diffOp ) {
if ( $diffOp instanceof DiffOpAdd ) {
$aliases[] = $diffOp->getNewValue();
} elseif ( $diffOp instanceof DiffOpChange ) {
$key = array_search( $diffOp->getOldValue(), $aliases, true );

if ( $key !== false ) {
unset( $aliases[$key] );
$aliases[] = $diffOp->getNewValue();
}
} elseif ( $diffOp instanceof DiffOpRemove ) {
$key = array_search( $diffOp->getOldValue(), $aliases, true );

if ( $key !== false ) {
unset( $aliases[$key] );
}
} else {
throw new PatcherException( 'Invalid aliases diff' );
}
}

return $aliases;
}

}

0 comments on commit f337392

Please sign in to comment.