Daniel Kinzler has uploaded a new change for review. https://gerrit.wikimedia.org/r/68369
Change subject: (bug 49498) Handle errors from invalid snak values. ...................................................................... (bug 49498) Handle errors from invalid snak values. When providing invalid snak values to the API, we should respond with a meaningful error message, not a fatal error. Note that this needs I4d6b27a to be applied to the DataValues project in order to work correctly. Change-Id: I09e54dca33a3d143b1fa0d2f6ccf331ba8241a36 --- M DataModel/DataModel/Entity/EntityId.php M DataModel/DataModel/Snak/SnakFactory.php M repo/includes/api/CreateClaim.php M repo/includes/api/SetClaim.php M repo/includes/api/SetClaimValue.php M repo/includes/api/SetQualifier.php M repo/includes/api/SetReference.php M repo/tests/phpunit/includes/api/CreateClaimTest.php 8 files changed, 91 insertions(+), 39 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/69/68369/1 diff --git a/DataModel/DataModel/Entity/EntityId.php b/DataModel/DataModel/Entity/EntityId.php index d093be7..dc238f7 100644 --- a/DataModel/DataModel/Entity/EntityId.php +++ b/DataModel/DataModel/Entity/EntityId.php @@ -2,6 +2,7 @@ namespace Wikibase; +use DataValues\IllegalValueException; use InvalidArgumentException; use ValueParsers\ParseException; @@ -273,15 +274,18 @@ /** * Constructs a new instance of the DataValue from the provided data. - * This can round-trip with @see getArrayValue + * This can round-trip with + * @see getArrayValue * * @since 0.4 * * @param mixed $data * + * @throws \DataValues\IllegalValueException * @return \DataValues\DataValue */ public static function newFromArray( $data ) { + self::requireArrayFields( $data, array( 'entity-type', 'numeric-id' ) ); return new static( $data['entity-type'], $data['numeric-id'] ); } diff --git a/DataModel/DataModel/Snak/SnakFactory.php b/DataModel/DataModel/Snak/SnakFactory.php index ebdc0ef..c938232 100644 --- a/DataModel/DataModel/Snak/SnakFactory.php +++ b/DataModel/DataModel/Snak/SnakFactory.php @@ -2,6 +2,8 @@ namespace Wikibase; +use DataValues\IllegalValueException; +use InvalidArgumentException; use MWException; /** @@ -36,16 +38,17 @@ * * @since 0.3 * - * @param EntityId $propertyId - * @param string $snakType + * @param EntityId $propertyId + * @param string $snakType * @param string|null $snakValue * + * @throws IllegalValueException + * @throws InvalidArgumentException * @return Snak - * @throws MWException */ public function newSnak( EntityId $propertyId, $snakType, $snakValue = null ) { if ( $propertyId->getEntityType() !== Property::ENTITY_TYPE ) { - throw new MWException( 'Expected an EntityId of a property' ); + throw new InvalidArgumentException( 'Expected an EntityId of a property' ); } switch ( $snakType ) { @@ -60,9 +63,7 @@ break; } - if ( !isset( $snak ) ) { - throw new MWException( '$snak was not set to an instance of Snak' ); - } + assert( isset( $snak ) ); return $snak; } diff --git a/repo/includes/api/CreateClaim.php b/repo/includes/api/CreateClaim.php index 0d79e5a..53469b1 100644 --- a/repo/includes/api/CreateClaim.php +++ b/repo/includes/api/CreateClaim.php @@ -4,6 +4,9 @@ use ApiBase, MWException; +use DataValues\IllegalValueException; +use InvalidArgumentException; +use UsageException; use ValueParsers\ParseException; use Wikibase\EntityId; use Wikibase\Entity; @@ -66,9 +69,18 @@ try { $snak = $this->getSnakInstance(); } - catch ( \Exception $ex ) { + catch ( IllegalValueException $ex ) { wfProfileOut( __METHOD__ ); - $this->dieUsageMsg( $ex->getMessage() ); + $this->dieUsage( $ex->getMessage(), 'claim-invalid-snak' ); + } + catch ( InvalidArgumentException $ex ) { + // shouldn't happen, but might. + wfProfileOut( __METHOD__ ); + $this->dieUsage( $ex->getMessage(), 'claim-invalid-snak' ); + } + catch ( ParseException $parseException ) { + wfProfileOut( __METHOD__ ); + $this->dieUsage( $parseException->getMessage(), 'claim-invalid-guid' ); } $claim = $this->addClaim( $entityContent->getEntity(), $snak ); @@ -168,7 +180,8 @@ * @since 0.2 * * @return Snak - * @throws MWException + * @throws ParseException + * @throws IllegalValueException */ protected function getSnakInstance() { $params = $this->extractRequestParams(); @@ -176,12 +189,7 @@ $factory = new SnakFactory(); $entityIdParser = WikibaseRepo::getDefaultInstance()->getEntityIdParser(); - try { - $entityId = $entityIdParser->parse( $params['property'] ); - } - catch ( ParseException $parseException ) { - throw new MWException( $parseException->getMessage(), 'setclaim-invalid-guid' ); - } + $entityId = $entityIdParser->parse( $params['property'] ); return $factory->newSnak( $entityId, diff --git a/repo/includes/api/SetClaim.php b/repo/includes/api/SetClaim.php index 70a94db..23b34be 100644 --- a/repo/includes/api/SetClaim.php +++ b/repo/includes/api/SetClaim.php @@ -2,6 +2,7 @@ namespace Wikibase\Api; +use DataValues\IllegalValueException; use Diff\CallbackListDiffer; use MWException; use ApiBase; @@ -105,11 +106,15 @@ $unserializer = $serializerFactory->newUnserializerForClass( 'Wikibase\Claim' ); $params = $this->extractRequestParams(); - $claim = $unserializer->newFromSerialization( \FormatJson::decode( $params['claim'], true ) ); - assert( $claim instanceof Claim ); + try { + $claim = $unserializer->newFromSerialization( \FormatJson::decode( $params['claim'], true ) ); - return $claim; + assert( $claim instanceof Claim ); + return $claim; + } catch ( IllegalValueException $ex ) { + $this->dieUsage( $ex->getMessage(), 'setclaim-invalid-claim' ); + } } /** diff --git a/repo/includes/api/SetClaimValue.php b/repo/includes/api/SetClaimValue.php index d8aba33..2774f42 100644 --- a/repo/includes/api/SetClaimValue.php +++ b/repo/includes/api/SetClaimValue.php @@ -4,6 +4,7 @@ use ApiBase, MWException; +use DataValues\IllegalValueException; use Wikibase\Autocomment; use Wikibase\EntityId; use Wikibase\Entity; @@ -143,11 +144,16 @@ $constructorArguments[] = $content->getProperty()->newDataValue( $value ); } - $claim->setMainSnak( SnakObject::newFromType( $snakType, $constructorArguments ) ); + try { + $snak = SnakObject::newFromType( $snakType, $constructorArguments ); + $claim->setMainSnak( $snak ); - $entity->setClaims( $claims ); + $entity->setClaims( $claims ); - return $claim; + return $claim; + } catch ( IllegalValueException $ex ) { + $this->dieUsage( $ex->getMessage(), 'setclaim-invalid-snak' ); + } } /** diff --git a/repo/includes/api/SetQualifier.php b/repo/includes/api/SetQualifier.php index 301eecd..31891bd 100644 --- a/repo/includes/api/SetQualifier.php +++ b/repo/includes/api/SetQualifier.php @@ -3,6 +3,7 @@ namespace Wikibase\Api; use ApiBase; +use DataValues\IllegalValueException; use MWException; use ValueParsers\ParseException; @@ -220,10 +221,16 @@ $snakValue = null; } - $factory = new SnakFactory(); - $newQualifier = $factory->newSnak( $propertyId, $snakType, $snakValue ); + try { + $factory = new SnakFactory(); + $newQualifier = $factory->newSnak( $propertyId, $snakType, $snakValue ); - return $qualifiers->addSnak( $newQualifier ); + return $qualifiers->addSnak( $newQualifier ); + } catch ( IllegalValueException $ex ) { + $this->dieUsage( $ex->getMessage(), 'setclaim-invalid-snak' ); + } + + return false; // we should never get here. } protected function getParsedEntityId( $prefixedId, $errorCode ) { @@ -255,13 +262,19 @@ $propertyId = $this->getParsedEntityId( $params['property'], 'invalid-property-id' ); - $newQualifier = $factory->newSnak( - $propertyId, - $params['snaktype'], - isset( $params['value'] ) ? \FormatJson::decode( $params['value'], true ) : null - ); + try { + $newQualifier = $factory->newSnak( + $propertyId, + $params['snaktype'], + isset( $params['value'] ) ? \FormatJson::decode( $params['value'], true ) : null + ); - return $qualifiers->addSnak( $newQualifier ); + return $qualifiers->addSnak( $newQualifier ); + } catch ( IllegalValueException $ex ) { + $this->dieUsage( $ex->getMessage(), 'setclaim-invalid-snak' ); + } + + return false; // we should never get here. } /** diff --git a/repo/includes/api/SetReference.php b/repo/includes/api/SetReference.php index f6b0bef..da5abff 100644 --- a/repo/includes/api/SetReference.php +++ b/repo/includes/api/SetReference.php @@ -4,6 +4,7 @@ use ApiBase, MWException; +use DataValues\IllegalValueException; use Wikibase\EntityId; use Wikibase\Entity; use Wikibase\EntityContent; @@ -128,13 +129,17 @@ $serializerFactory = new \Wikibase\Lib\Serializers\SerializerFactory(); $snakUnserializer = $serializerFactory->newUnserializerForClass( 'Wikibase\Snak' ); - foreach ( $rawSnaks as $byPropertySnaks ) { - if ( !is_array( $byPropertySnaks ) ) { - $this->dieUsage( 'Invalid snak JSON given', 'setreference-invalid-snaks' ); + try { + foreach ( $rawSnaks as $byPropertySnaks ) { + if ( !is_array( $byPropertySnaks ) ) { + $this->dieUsage( 'Invalid snak JSON given', 'setreference-invalid-snaks' ); + } + foreach ( $byPropertySnaks as $rawSnak ) { + $snaks[] = $snakUnserializer->newFromSerialization( $rawSnak ); + } } - foreach ( $byPropertySnaks as $rawSnak ) { - $snaks[] = $snakUnserializer->newFromSerialization( $rawSnak ); - } + } catch ( IllegalValueException $ex ) { + $this->dieUsage( $ex->getMessage(), 'setreference-invalid-snaks' ); } return $snaks; diff --git a/repo/tests/phpunit/includes/api/CreateClaimTest.php b/repo/tests/phpunit/includes/api/CreateClaimTest.php index b2d7ac0..1cf4e17 100644 --- a/repo/tests/phpunit/includes/api/CreateClaimTest.php +++ b/repo/tests/phpunit/includes/api/CreateClaimTest.php @@ -123,7 +123,7 @@ 'value' => '"foo"', ); - $argLists[] = array( 'unknownerror', $params ); + $argLists[] = array( 'claim-invalid-snak', $params ); $params = array( 'action' => 'wbcreateclaim', @@ -167,6 +167,16 @@ $argLists[] = array( 'claim-value-missing', $params ); + $params = array( + 'action' => 'wbcreateclaim', + 'entity' => '-', + 'snaktype' => 'value', + 'property' => '-', + 'value' => '{"x":"foo", "y":"bar"}', + ); + + $argLists[] = array( 'claim-invalid-snak', $params ); + return $argLists; } -- To view, visit https://gerrit.wikimedia.org/r/68369 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I09e54dca33a3d143b1fa0d2f6ccf331ba8241a36 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Daniel Kinzler <daniel.kinz...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits