Aude has uploaded a new change for review. https://gerrit.wikimedia.org/r/180062
Change subject: Introduce DataType for refs to Properties. ...................................................................... Introduce DataType for refs to Properties. DataType for references to Properties. Intended for use in constraints defined as statements on properties. Bug: T75302 Change-Id: I3e844f30eab145cee7a0a014a817cf306629b7a0 --- M lib/config/WikibaseLib.default.php M lib/i18n/en.json M lib/i18n/qqq.json M lib/includes/Validators/EntityExistsValidator.php M lib/includes/WikibaseDataTypeBuilders.php M lib/tests/phpunit/Validators/EntityExistsValidatorTest.php M lib/tests/phpunit/WikibaseDataTypeBuildersTest.php 7 files changed, 149 insertions(+), 50 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/62/180062/1 diff --git a/lib/config/WikibaseLib.default.php b/lib/config/WikibaseLib.default.php index 1e68026..9234333 100644 --- a/lib/config/WikibaseLib.default.php +++ b/lib/config/WikibaseLib.default.php @@ -97,6 +97,7 @@ 'time', 'url', 'wikibase-item', + 'wikibase-property', ), // URL schemes allowed for URL values. See UrlSchemeValidators for a full list. diff --git a/lib/i18n/en.json b/lib/i18n/en.json index f530ad4..11f2ad4 100644 --- a/lib/i18n/en.json +++ b/lib/i18n/en.json @@ -68,6 +68,7 @@ "wikibase-validator-unknown-unit": "Unknown unit: $1", "wikibase-validator-not-allowed": "Illegal value: $1", "datatypes-type-wikibase-item": "Item", + "datatypes-type-wikibase-property": "Property", "datatypes-type-commonsMedia": "Commons media file", "version-wikibase": "Wikibase", "wikibase-time-precision-Gannum": "$1 billion years CE", diff --git a/lib/i18n/qqq.json b/lib/i18n/qqq.json index aec72b6..c666fcf 100644 --- a/lib/i18n/qqq.json +++ b/lib/i18n/qqq.json @@ -77,6 +77,7 @@ "wikibase-validator-unknown-unit": "Input validation error when the value has an unknown unit.\n\nParameters:\n* $1 - the unknown unit\n{{Related|Wikibase-validator}}", "wikibase-validator-not-allowed": "Input validation error when the given value is not found in the known list of allowed values.\n\nParameters:\n* $1 - the illegal value\n{{Related|Wikibase-validator}}", "datatypes-type-wikibase-item": "The name of a data type for items in Wikibase.\n{{Identical|Item}}", + "datatypes-type-wikibase-property": "The name of a data type for properties in Wikibase.\n{{Identical|Property}}", "datatypes-type-commonsMedia": "The name of a data type for media files on Wikimedia Commons (proper name, capitalised in English; first letter capitalised anyway in this message and relatives).", "version-wikibase": "Name of the Wikibase extension collection, used on [[Special:Version]]", "wikibase-time-precision-Gannum": "!!DO NOT TRANSLATE!! Used to present a point in time with the precession of 1 billion of years\n{{Related|Wikibase-time-precision}}", diff --git a/lib/includes/Validators/EntityExistsValidator.php b/lib/includes/Validators/EntityExistsValidator.php index 03a9fb2..4d73766 100644 --- a/lib/includes/Validators/EntityExistsValidator.php +++ b/lib/includes/Validators/EntityExistsValidator.php @@ -18,10 +18,23 @@ */ class EntityExistsValidator implements ValueValidator { + /** + * @var EntityLookup + */ private $entityLookup; - public function __construct( EntityLookup $entityLookup ) { + /** + * @var string|null + */ + private $entityType; + + public function __construct( EntityLookup $entityLookup, $entityType = null ) { + if ( !is_string( $entityType ) && !is_null( $entityType ) ) { + throw new InvalidArgumentException( '$entityType must be a string or null' ); + } + $this->entityLookup = $entityLookup; + $this->entityType = $entityType; } /** @@ -41,14 +54,29 @@ throw new InvalidArgumentException( "Expected an EntityId object" ); } - if ( !$this->entityLookup->hasEntity( $value ) ) { - return Result::newError( array( - //XXX: we are passing an EntityId as a message parameter here - make sure to turn it into a string later! - Error::newError( "Entity not found: " . $value, null, 'no-such-entity', array( $value ) ), - ) ); + $actualType = $value->getEntityType(); + + $errors = array(); + + if ( $this->entityType !== null && $actualType !== $this->entityType ) { + $errors[] = Error::newError( + "Wrong entity type: " . $actualType, + null, + 'bad-entity-type', + array( $actualType ) + ); } - return Result::newSuccess(); + if ( !$this->entityLookup->hasEntity( $value ) ) { + $errors[] = Error::newError( + "Entity not found: " . $value, + null, + 'no-such-entity', + array( $value ) + ); + } + + return empty( $errors ) ? Result::newSuccess() : Result::newError( $errors ); } /** diff --git a/lib/includes/WikibaseDataTypeBuilders.php b/lib/includes/WikibaseDataTypeBuilders.php index 3e84ccc..b3414f1 100644 --- a/lib/includes/WikibaseDataTypeBuilders.php +++ b/lib/includes/WikibaseDataTypeBuilders.php @@ -6,6 +6,8 @@ use DataValues\TimeValue; use ValueValidators\ValueValidator; use Wikibase\DataModel\Entity\EntityIdParser; +use Wikibase\DataModel\Entity\Item; +use Wikibase\DataModel\Entity\Property; use Wikibase\Lib\Store\EntityLookup; use Wikibase\Utils; use Wikibase\Validators\CompositeValidator; @@ -73,26 +75,28 @@ /** * Data types to data value types mapping: - * commonsMedia => string (camel case, FIXME maybe?) - * globe-coordinate => globecoordinate (FIXME!) - * monolingualtext => monolingualtext - * multilingualtext => multilingualtext - * quantity => quantity - * string => string - * time => time - * url => string - * wikibase-item => wikibase-entityid + * commonsMedia => string (camel case, FIXME maybe?) + * globe-coordinate => globecoordinate (FIXME!) + * monolingualtext => monolingualtext + * multilingualtext => multilingualtext + * quantity => quantity + * string => string + * time => time + * url => string + * wikibase-item => wikibase-entityid + * wikibase-property => wikibase-entityid */ $types = array( - 'commonsMedia' => array( $this, 'buildMediaType' ), - 'globe-coordinate' => array( $this, 'buildCoordinateType' ), - 'quantity' => array( $this, 'buildQuantityType' ), - 'string' => array( $this, 'buildStringType' ), - 'time' => array( $this, 'buildTimeType' ), - 'url' => array( $this, 'buildUrlType' ), - 'wikibase-item' => array( $this, 'buildItemType' ), - 'monolingualtext' => array( $this, 'buildMonolingualTextType' ), + 'commonsMedia' => array( $this, 'buildMediaType' ), + 'globe-coordinate' => array( $this, 'buildCoordinateType' ), + 'quantity' => array( $this, 'buildQuantityType' ), + 'string' => array( $this, 'buildStringType' ), + 'time' => array( $this, 'buildTimeType' ), + 'url' => array( $this, 'buildUrlType' ), + 'wikibase-item' => array( $this, 'buildItemType' ), + 'wikibase-property' => array( $this, 'buildPropertyType' ), + 'monolingualtext' => array( $this, 'buildMonolingualTextType' ), ); $experimental = array( @@ -116,7 +120,22 @@ //NOTE: The DataValue in question is going to be an instance of EntityId! $validators[] = new TypeValidator( 'Wikibase\DataModel\Entity\EntityIdValue' ); - $validators[] = new EntityExistsValidator( $this->entityLookup ); + $validators[] = new EntityExistsValidator( $this->entityLookup, Item::ENTITY_TYPE ); + + return new DataType( $id, 'wikibase-entityid', $validators ); + } + + /** + * @param string $id Data type ID, typically 'wikibase-property' + * + * @return DataType + */ + public function buildPropertyType( $id ) { + $validators = array(); + + //NOTE: The DataValue in question is going to be an instance of EntityId! + $validators[] = new TypeValidator( 'Wikibase\DataModel\Entity\EntityIdValue' ); + $validators[] = new EntityExistsValidator( $this->entityLookup, Property::ENTITY_TYPE ); return new DataType( $id, 'wikibase-entityid', $validators ); } diff --git a/lib/tests/phpunit/Validators/EntityExistsValidatorTest.php b/lib/tests/phpunit/Validators/EntityExistsValidatorTest.php index aa7f042..ff352a3 100644 --- a/lib/tests/phpunit/Validators/EntityExistsValidatorTest.php +++ b/lib/tests/phpunit/Validators/EntityExistsValidatorTest.php @@ -4,6 +4,8 @@ use Wikibase\DataModel\Entity\Item; use Wikibase\DataModel\Entity\ItemId; +use Wikibase\DataModel\Entity\Property; +use Wikibase\DataModel\Entity\PropertyId; use Wikibase\Test\MockRepository; use Wikibase\Validators\EntityExistsValidator; use Wikibase\Validators\ValidatorErrorLocalizer; @@ -21,42 +23,79 @@ */ class EntityExistsValidatorTest extends \PHPUnit_Framework_TestCase { + private function getEntityLookup() { + $q8 = Item::newEmpty(); + $q8->setId( 8 ); + + $p8 = Property::newFromType( 'string' ); + $p8->setId( 8 ); + + $entityLookup = new MockRepository(); + $entityLookup->putEntity( $q8 ); + $entityLookup->putEntity( $p8 ); + + return $entityLookup; + } + public static function provideValidate() { return array( - array( 'q3', false, 'InvalidArgumentException', "Expect an EntityId" ), - array( new ItemId( 'q3' ), false, null, "missing entity" ), - array( new ItemId( 'q8' ), true, null, "existing entity" ), + "existing entity" => array( new ItemId( 'Q8' ), null ), + "is an item" => array( new ItemId( 'Q8' ), Item::ENTITY_TYPE ), + "is a property" => array( new PropertyId( 'P8' ), Property::ENTITY_TYPE ), ); } /** * @dataProvider provideValidate() */ - public function testValidate( $value, $expected, $exception, $message ) { - if ( $exception !== null ) { - $this->setExpectedException( $exception ); - } - - $q8 = Item::newEmpty(); - $q8->setId( 8 ); - - $entityLookup = new MockRepository(); - $entityLookup->putEntity( $q8 ); - - $validator = new EntityExistsValidator( $entityLookup ); + public function testValidate( $value, $type ) { + $validator = new EntityExistsValidator( $this->getEntityLookup(), $type ); $result = $validator->validate( $value ); - $this->assertEquals( $expected, $result->isValid(), $message ); + $this->assertTrue( $result->isValid() ); + } - if ( !$expected ) { - $errors = $result->getErrors(); - $this->assertCount( 1, $errors, $message ); - $this->assertEquals( 'no-such-entity', $errors[0]->getCode(), $message ); + public static function provideValidate_failure() { + return array( + "missing entity" => array( new ItemId( 'Q3' ), null, 'no-such-entity' ), + "not an item" => array( new PropertyId( 'P8' ), Item::ENTITY_TYPE, 'bad-entity-type' ), + "not a property" => array( new ItemId( 'Q8' ), Property::ENTITY_TYPE, 'bad-entity-type' ), + ); + } - $localizer = new ValidatorErrorLocalizer( ); - $msg = $localizer->getErrorMessage( $errors[0] ); - $this->assertTrue( $msg->exists(), $msg ); - } + /** + * @dataProvider provideValidate_failure() + */ + public function testValidate_failure( $value, $type, $errorCode ) { + $validator = new EntityExistsValidator( $this->getEntityLookup(), $type ); + $result = $validator->validate( $value ); + + $this->assertFalse( $result->isValid() ); + + $errors = $result->getErrors(); + $this->assertCount( 1, $errors ); + $this->assertEquals( $errorCode, $errors[0]->getCode() ); + + $localizer = new ValidatorErrorLocalizer( ); + $msg = $localizer->getErrorMessage( $errors[0] ); + $this->assertTrue( $msg->exists(), $msg ); + } + + public static function provideValidate_exception() { + return array( + "Not an EntityId" => array( 'Q3', null ), + "Type is not a string" => array( new ItemId( 'Q8' ), array( 'foo' ) ), + ); + } + + /** + * @dataProvider provideValidate_exception() + */ + public function testValidate_exception( $value, $type ) { + $this->setExpectedException( 'InvalidArgumentException' ); + + $validator = new EntityExistsValidator( $this->getEntityLookup(), $type ); + $validator->validate( $value ); } } diff --git a/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php b/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php index 3f2818a..cf2dd33 100644 --- a/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php +++ b/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php @@ -16,6 +16,8 @@ use Wikibase\DataModel\Entity\EntityIdValue; use Wikibase\DataModel\Entity\Item; use Wikibase\DataModel\Entity\ItemId; +use Wikibase\DataModel\Entity\Property; +use Wikibase\DataModel\Entity\PropertyId; use Wikibase\Lib\WikibaseDataTypeBuilders; /** @@ -34,10 +36,14 @@ $entityIdParser = new BasicEntityIdParser(); $q8 = Item::newEmpty(); - $q8->setId( new ItemId( 'q8' ) ); + $q8->setId( new ItemId( 'Q8' ) ); + + $p8 = Property::newFromType( 'string' ); + $p8->setId( new PropertyId( 'P8' ) ); $entityLookup = new MockRepository(); $entityLookup->putEntity( $q8 ); + $entityLookup->putEntity( $p8 ); $urlSchemes = array( 'http', 'https', 'ftp', 'mailto' ); @@ -56,6 +62,10 @@ array( 'wikibase-item', new StringValue( 'q8' ), false, 'Expected EntityId, StringValue supplied' ), array( 'wikibase-item', new EntityIdValue( new ItemId( 'q8' ) ), true, 'existing entity' ), array( 'wikibase-item', new EntityIdValue( new ItemId( 'q3' ) ), false, 'missing entity' ), + array( 'wikibase-item', new EntityIdValue( new PropertyId( 'p8' ) ), false, 'not an item' ), + + array( 'wikibase-property', new EntityIdValue( new PropertyId( 'p8' ) ), true, 'existing entity' ), + array( 'wikibase-property', new EntityIdValue( new ItemId( 'q8' ) ), false, 'not a property' ), //commonsMedia array( 'commonsMedia', 'Foo.jpg', false, 'StringValue expected, string supplied' ), -- To view, visit https://gerrit.wikimedia.org/r/180062 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3e844f30eab145cee7a0a014a817cf306629b7a0 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: wmf/1.25wmf12c Gerrit-Owner: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits