Thiemo Mättig (WMDE) has uploaded a new change for review. https://gerrit.wikimedia.org/r/133523
Change subject: Attempt to clean-up and refactor ChangeOp and Validators code ...................................................................... Attempt to clean-up and refactor ChangeOp and Validators code This is not really fixing a bug. The code works. But it's hard to read and to maintain. Unfortunatelly the best I could do is to use clone. I tried to avoid it. It gets a mess very fast (try to reconstruct a Fingerprint object from an other Fingerprint object). This just doesn't feel right. I think we really need to discuss this. This is a direct follow up to some (but not all) of the comments in Ibb6ee8439ba3ab0252403eb811aa48d1274d1d58. Change-Id: I7434d5c40cd601976e72f104ce5699e59fef184e --- M repo/includes/ChangeOp/ChangeOpAliases.php M repo/includes/ChangeOp/ChangeOpDescription.php M repo/includes/ChangeOp/ChangeOpLabel.php M repo/includes/Validators/CompositeFingerprintValidator.php M repo/includes/Validators/FingerprintValidator.php M repo/includes/Validators/LabelDescriptionUniquenessValidator.php M repo/includes/Validators/LabelUniquenessValidator.php 7 files changed, 118 insertions(+), 105 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/23/133523/1 diff --git a/repo/includes/ChangeOp/ChangeOpAliases.php b/repo/includes/ChangeOp/ChangeOpAliases.php index 4d38a4a..e77afa1 100644 --- a/repo/includes/ChangeOp/ChangeOpAliases.php +++ b/repo/includes/ChangeOp/ChangeOpAliases.php @@ -25,86 +25,87 @@ * * @var string */ - protected $language; + private $languageCode; /** * @since 0.4 * * @var string[] */ - protected $aliases; + private $aliases; /** * @since 0.4 * * @var array */ - protected $action; + private $action; /** * @since 0.5 * * @var TermValidatorFactory */ - protected $termValidatorFactory; + private $termValidatorFactory; /** * @since 0.5 * - * @param string $language + * @param string $languageCode * @param string[] $aliases * @param string $action should be set|add|remove - * * @param TermValidatorFactory $termValidatorFactory * * @throws InvalidArgumentException */ public function __construct( - $language, + $languageCode, array $aliases, $action, TermValidatorFactory $termValidatorFactory ) { - if ( !is_string( $language ) ) { - throw new InvalidArgumentException( '$language needs to be a string' ); + if ( !is_string( $languageCode ) ) { + throw new InvalidArgumentException( 'Language code needs to be a string.' ); } if ( !is_string( $action ) ) { - throw new InvalidArgumentException( '$action needs to be a string' ); + throw new InvalidArgumentException( 'Action needs to be a string.' ); } - $this->language = $language; + $this->languageCode = $languageCode; $this->aliases = $aliases; $this->action = $action; - $this->termValidatorFactory = $termValidatorFactory; } /** - * Applies the change to the fingerprint - * * @param Fingerprint $fingerprint * * @throws ChangeOpException + * @returns Fingerprint */ - private function updateFingerprint( Fingerprint $fingerprint ) { - try { - $current = $fingerprint->getAliasGroup( $this->language )->getAliases(); - } catch ( \OutOfBoundsException $ex ) { - $current = array(); + private function getUpdatedFingerprint( Fingerprint $fingerprint ) { + if ( $fingerprint->getAliasGroups()->hasGroupForLanguage( $this->languageCode ) ) { + $oldAliases = $fingerprint->getAliasGroup( $this->languageCode )->getAliases(); + } else { + $oldAliases = array(); } - if ( $this->action === "remove" ) { - $updated = array_diff( $current, $this->aliases ); - } elseif ( $this->action === "add" ) { - $updated = array_merge( $current, $this->aliases ); - } elseif ( $this->action === "set" || $this->action === "" ) { - $updated = $this->aliases; + $fingerprint = clone $fingerprint; + + if ( $this->action === 'set' || $this->action === '' ) { + $newAliases = $this->aliases; + } elseif ( $this->action === 'add' ) { + $newAliases = array_merge( $oldAliases, $this->aliases ); + } elseif ( $this->action === 'remove' ) { + $newAliases = array_diff( $oldAliases, $this->aliases ); } else { throw new ChangeOpException( 'Bad action: ' . $this->action ); } - $fingerprint->setAliasGroup( new AliasGroup( $this->language, $updated ) ); + $fingerprint->setAliasGroup( new AliasGroup( $this->languageCode, $newAliases ) ); + + return $fingerprint; } /** @@ -113,10 +114,11 @@ public function apply( Entity $entity, Summary $summary = null ) { $fingerprint = $entity->getFingerprint(); - $this->updateFingerprint( $fingerprint ); - $this->updateSummary( $summary, $this->action, $this->language, $this->aliases ); + $this->updateSummary( $summary, $this->action, $this->languageCode, $this->aliases ); + $fingerprint = $this->getUpdatedFingerprint( $fingerprint ); $entity->setFingerprint( $fingerprint ); + return true; } @@ -129,7 +131,6 @@ * * @param Entity $entity * - * @throws ChangeOpException * @return Result */ public function validate( Entity $entity ) { @@ -137,13 +138,14 @@ $termValidator = $this->termValidatorFactory->getLabelValidator( $entity->getType() ); // check that the language is valid - $result = $languageValidator->validate( $this->language ); + $result = $languageValidator->validate( $this->languageCode ); if ( !$result->isValid() ) { return $result; } - if ( $this->action === 'set' || $this->action === '' || $this->action === 'add' ) { + // It should be possible to remove invalid aliases, but not to add/set new invalid ones + if ( $this->action !== 'remove' ) { // Check that the new aliases are valid foreach ( $this->aliases as $alias ) { $result = $termValidator->validate( $alias ); @@ -152,11 +154,10 @@ return $result; } } - } elseif ( $this->action !== 'remove' ) { - throw new ChangeOpException( 'Bad action: ' . $this->action ); } //XXX: Do we want to check the updated fingerprint, as we do for labels and descriptions? - return Result::newSuccess(); + return $result; } + } diff --git a/repo/includes/ChangeOp/ChangeOpDescription.php b/repo/includes/ChangeOp/ChangeOpDescription.php index e99d13d..1e5d57f 100644 --- a/repo/includes/ChangeOp/ChangeOpDescription.php +++ b/repo/includes/ChangeOp/ChangeOpDescription.php @@ -7,6 +7,7 @@ use Wikibase\DataModel\Entity\Entity; use Wikibase\DataModel\Term\Fingerprint; use Wikibase\DataModel\Term\Term; +use Wikibase\DataModel\Term\TermList; use Wikibase\Summary; use Wikibase\Validators\TermValidatorFactory; @@ -25,58 +26,60 @@ * * @var string */ - protected $language; + private $languageCode; /** * @since 0.4 * * @var string|null */ - protected $description; + private $description; /** * @since 0.5 * * @var TermValidatorFactory */ - protected $termValidatorFactory; + private $termValidatorFactory; /** * @since 0.4 * - * @param string $language + * @param string $languageCode * @param string|null $description - * * @param TermValidatorFactory $termValidatorFactory * * @throws InvalidArgumentException */ public function __construct( - $language, + $languageCode, $description, TermValidatorFactory $termValidatorFactory ) { - if ( !is_string( $language ) ) { - throw new InvalidArgumentException( '$language needs to be a string' ); + if ( !is_string( $languageCode ) ) { + throw new InvalidArgumentException( 'Language code needs to be a string.' ); } - $this->language = $language; + $this->languageCode = $languageCode; $this->description = $description; - $this->termValidatorFactory = $termValidatorFactory; } /** - * Applies the change to the fingerprint - * * @param Fingerprint $fingerprint + * + * @returns Fingerprint */ - private function updateFingerprint( Fingerprint $fingerprint ) { + private function getUpdatedFingerprint( Fingerprint $fingerprint ) { + $fingerprint = clone $fingerprint; + if ( $this->description === null ) { - $fingerprint->removeDescription( $this->language ); + $fingerprint->removeDescription( $this->languageCode ); } else { - $fingerprint->setDescription( new Term( $this->language, $this->description ) ); + $fingerprint->setDescription( new Term( $this->languageCode, $this->description ) ); } + + return $fingerprint; } /** @@ -84,23 +87,19 @@ */ public function apply( Entity $entity, Summary $summary = null ) { $fingerprint = $entity->getFingerprint(); - $exists = $fingerprint->getDescriptions()->hasTermForLanguage( $this->language ); - if ( $this->description === null ) { - if ( $exists ) { - $old = $fingerprint->getDescription( $this->language )->getText(); - $this->updateSummary( $summary, 'remove', $this->language, $old ); + if ( $fingerprint->getDescriptions()->hasTermForLanguage( $this->languageCode ) ) { + if ( $this->description === null ) { + $removedDescription = $fingerprint->getDescription( $this->languageCode )->getText(); + $this->updateSummary( $summary, 'remove', $this->languageCode, $removedDescription ); + } else { + $this->updateSummary( $summary, 'set', $this->languageCode, $this->description ); } } else { - if ( $exists ) { - $fingerprint->getDescription( $this->language ); - $this->updateSummary( $summary, 'set', $this->language, $this->description ); - } else { - $this->updateSummary( $summary, 'add', $this->language, $this->description ); - } + $this->updateSummary( $summary, 'add', $this->languageCode, $this->description ); } - $this->updateFingerprint( $fingerprint ); + $fingerprint = $this->getUpdatedFingerprint( $fingerprint ); $entity->setFingerprint( $fingerprint ); return true; @@ -123,7 +122,7 @@ $fingerprintValidator = $this->termValidatorFactory->getFingerprintValidator( $entity->getType() ); // check that the language is valid - $result = $languageValidator->validate( $this->language ); + $result = $languageValidator->validate( $this->languageCode ); if ( $result->isValid() && $this->description !== null ) { // Check that the new description is valid @@ -137,12 +136,12 @@ // Check if the new fingerprint of the entity is valid (e.g. if the combination // of label and description is still unique) $fingerprint = $entity->getFingerprint(); - $this->updateFingerprint( $fingerprint ); + $fingerprint = $this->getUpdatedFingerprint( $fingerprint ); $result = $fingerprintValidator->validateFingerprint( $fingerprint, $entity->getId(), - array( $this->language ) + array( $this->languageCode ) ); return $result; diff --git a/repo/includes/ChangeOp/ChangeOpLabel.php b/repo/includes/ChangeOp/ChangeOpLabel.php index e3578cc..c2870cd 100644 --- a/repo/includes/ChangeOp/ChangeOpLabel.php +++ b/repo/includes/ChangeOp/ChangeOpLabel.php @@ -3,7 +3,6 @@ namespace Wikibase\ChangeOp; use InvalidArgumentException; -use OutOfBoundsException; use ValueValidators\Result; use Wikibase\DataModel\Entity\Entity; use Wikibase\DataModel\Term\Fingerprint; @@ -26,58 +25,60 @@ * * @var string */ - protected $language; + private $languageCode; /** * @since 0.4 * * @var string|null */ - protected $label; + private $label; /** * @since 0.5 * * @var TermValidatorFactory */ - protected $termValidatorFactory; + private $termValidatorFactory; /** * @since 0.5 * - * @param string $language + * @param string $languageCode * @param string|null $label - * * @param TermValidatorFactory $termValidatorFactory * * @throws InvalidArgumentException */ public function __construct( - $language, + $languageCode, $label, TermValidatorFactory $termValidatorFactory ) { - if ( !is_string( $language ) ) { - throw new InvalidArgumentException( '$language needs to be a string' ); + if ( !is_string( $languageCode ) ) { + throw new InvalidArgumentException( 'Language code needs to be a string.' ); } - $this->language = $language; + $this->languageCode = $languageCode; $this->label = $label; - $this->termValidatorFactory = $termValidatorFactory; } /** - * Applies the change to the fingerprint - * * @param Fingerprint $fingerprint + * + * @return Fingerprint */ - private function updateFingerprint( Fingerprint $fingerprint ) { + private function getUpdatedFingerprint( Fingerprint $fingerprint ) { + $fingerprint = clone $fingerprint; + if ( $this->label === null ) { - $fingerprint->removeLabel( $this->language ); + $fingerprint->removeLabel( $this->languageCode ); } else { - $fingerprint->setLabel( new Term( $this->language, $this->label ) ); + $fingerprint->setLabel( new Term( $this->languageCode, $this->label ) ); } + + return $fingerprint; } /** @@ -86,28 +87,23 @@ * @param Entity $entity * @param Summary $summary * - * @throws ChangeOpException * @return bool */ public function apply( Entity $entity, Summary $summary = null ) { $fingerprint = $entity->getFingerprint(); - $exists = $fingerprint->getLabels()->hasTermForLanguage( $this->language ); - if ( $this->label === null ) { - if ( $exists ) { - $old = $fingerprint->getLabel( $this->language )->getText(); - $this->updateSummary( $summary, 'remove', $this->language, $old ); + if ( $fingerprint->getLabels()->hasTermForLanguage( $this->languageCode ) ) { + if ( $this->label === null ) { + $oldLabel = $fingerprint->getLabel( $this->languageCode )->getText(); + $this->updateSummary( $summary, 'remove', $this->languageCode, $oldLabel ); + } else { + $this->updateSummary( $summary, 'set', $this->languageCode, $this->label ); } } else { - if ( $exists ) { - $fingerprint->getLabel( $this->language ); - $this->updateSummary( $summary, 'set', $this->language, $this->label ); - } else { - $this->updateSummary( $summary, 'add', $this->language, $this->label ); - } + $this->updateSummary( $summary, 'add', $this->languageCode, $this->label ); } - $this->updateFingerprint( $fingerprint ); + $fingerprint = $this->getUpdatedFingerprint( $fingerprint ); $entity->setFingerprint( $fingerprint ); return true; @@ -130,7 +126,7 @@ $fingerprintValidator = $this->termValidatorFactory->getFingerprintValidator( $entity->getType() ); // check that the language is valid - $result = $languageValidator->validate( $this->language ); + $result = $languageValidator->validate( $this->languageCode ); if ( $result->isValid() && $this->label !== null ) { // Check that the new label is valid @@ -143,12 +139,12 @@ // Check if the new fingerprint of the entity is valid (e.g. if the label is unique) $fingerprint = $entity->getFingerprint(); - $this->updateFingerprint( $fingerprint ); + $fingerprint = $this->getUpdatedFingerprint( $fingerprint ); $result = $fingerprintValidator->validateFingerprint( $fingerprint, $entity->getId(), - array( $this->language ) + array( $this->languageCode ) ); return $result; diff --git a/repo/includes/Validators/CompositeFingerprintValidator.php b/repo/includes/Validators/CompositeFingerprintValidator.php index 084051f..177dd1f 100644 --- a/repo/includes/Validators/CompositeFingerprintValidator.php +++ b/repo/includes/Validators/CompositeFingerprintValidator.php @@ -41,7 +41,11 @@ * * @return Result */ - public function validateFingerprint( Fingerprint $fingerprint, EntityId $entityId = null, $languageCodes = null ) { + public function validateFingerprint( + Fingerprint $fingerprint, + EntityId $entityId = null, + array $languageCodes = null + ) { foreach ( $this->validators as $validator ) { $result = $validator->validateFingerprint( $fingerprint, $entityId, $languageCodes ); diff --git a/repo/includes/Validators/FingerprintValidator.php b/repo/includes/Validators/FingerprintValidator.php index cad460d..fd499bb 100644 --- a/repo/includes/Validators/FingerprintValidator.php +++ b/repo/includes/Validators/FingerprintValidator.php @@ -26,11 +26,16 @@ * @param Fingerprint $fingerprint * @param EntityId|null $entityId Context for uniqueness checks: conflicts with this entity * are ignored. - * @param string[]|null $languageCodes If given, the validation may be limited to the given languages; - * This is intended for optimization for the common case of only a single language changing. + * @param string[]|null $languageCodes If given, the validation may be limited to the given + * languages. This is intended for optimization for the common case of only a single + * language changing. * * @return Result */ - public function validateFingerprint( Fingerprint $fingerprint, EntityId $entityId = null, $languageCodes = null ); + public function validateFingerprint( + Fingerprint $fingerprint, + EntityId $entityId = null, + array $languageCodes = null + ); -} \ No newline at end of file +} diff --git a/repo/includes/Validators/LabelDescriptionUniquenessValidator.php b/repo/includes/Validators/LabelDescriptionUniquenessValidator.php index ec651e1..66531e4 100644 --- a/repo/includes/Validators/LabelDescriptionUniquenessValidator.php +++ b/repo/includes/Validators/LabelDescriptionUniquenessValidator.php @@ -51,11 +51,15 @@ * * @param Fingerprint $fingerprint * @param EntityId|null $entityId - * @param array|null $languageCodes + * @param string[]|null $languageCodes * * @return Result */ - public function validateFingerprint( Fingerprint $fingerprint, EntityId $entityId = null, $languageCodes = null ) { + public function validateFingerprint( + Fingerprint $fingerprint, + EntityId $entityId = null, + array $languageCodes = null + ) { $labels = array_map( function( Term $term ) { return $term->getText(); diff --git a/repo/includes/Validators/LabelUniquenessValidator.php b/repo/includes/Validators/LabelUniquenessValidator.php index db6426a..dcb8b46 100644 --- a/repo/includes/Validators/LabelUniquenessValidator.php +++ b/repo/includes/Validators/LabelUniquenessValidator.php @@ -51,11 +51,15 @@ * * @param Fingerprint $fingerprint * @param EntityId|null $entityId - * @param array|null $languageCodes + * @param string[]|null $languageCodes * * @return Result */ - public function validateFingerprint( Fingerprint $fingerprint, EntityId $entityId = null, $languageCodes = null ) { + public function validateFingerprint( + Fingerprint $fingerprint, + EntityId $entityId = null, + array $languageCodes = null + ) { $labels = array_map( function( Term $term ) { return $term->getText(); -- To view, visit https://gerrit.wikimedia.org/r/133523 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7434d5c40cd601976e72f104ce5699e59fef184e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits