Adrian Lang has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/189731

Change subject: Move Validator builders out of WikibaseDataTypeBuilders
......................................................................

Move Validator builders out of WikibaseDataTypeBuilders

Change-Id: I6fb14c135315c7c064ccf49c019670dfab68c857
---
M lib/includes/WikibaseDataTypeBuilders.php
A repo/includes/DataTypeValidatorFactory.php
A repo/includes/ValidatorBuilders.php
M repo/includes/Validators/SnakValidator.php
M repo/includes/WikibaseRepo.php
5 files changed, 402 insertions(+), 243 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/31/189731/1

diff --git a/lib/includes/WikibaseDataTypeBuilders.php 
b/lib/includes/WikibaseDataTypeBuilders.php
index 90f7ee4..c6e09c4 100644
--- a/lib/includes/WikibaseDataTypeBuilders.php
+++ b/lib/includes/WikibaseDataTypeBuilders.php
@@ -3,26 +3,6 @@
 namespace Wikibase\Lib;
 
 use DataTypes\DataType;
-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\AlternativeValidator;
-use Wikibase\Validators\CompositeValidator;
-use Wikibase\Validators\DataFieldValidator;
-use Wikibase\Validators\DataValueValidator;
-use Wikibase\Validators\EntityExistsValidator;
-use Wikibase\Validators\MembershipValidator;
-use Wikibase\Validators\NumberRangeValidator;
-use Wikibase\Validators\NumberValidator;
-use Wikibase\Validators\RegexValidator;
-use Wikibase\Validators\StringLengthValidator;
-use Wikibase\Validators\TypeValidator;
-use Wikibase\Validators\UrlSchemeValidators;
-use Wikibase\Validators\UrlValidator;
 
 /**
  * Defines the data types supported by Wikibase.
@@ -33,36 +13,6 @@
  * @author Daniel Kinzler
  */
 class WikibaseDataTypeBuilders {
-
-       /**
-        * @var EntityIdParser
-        */
-       private $entityIdParser;
-
-       /**
-        * @var EntityLookup
-        */
-       private $entityLookup;
-
-       /**
-        * @var string[]
-        */
-       private $urlSchemes;
-
-       /**
-        * @param EntityLookup $lookup
-        * @param EntityIdParser $idParser
-        * @param string[] $urlSchemes
-        */
-       public function __construct(
-               EntityLookup $lookup,
-               EntityIdParser $idParser,
-               array $urlSchemes
-       ) {
-               $this->entityIdParser = $idParser;
-               $this->entityLookup = $lookup;
-               $this->urlSchemes = $urlSchemes;
-       }
 
        /**
         * @return array DataType builder specs
@@ -88,6 +38,7 @@
                 * wikibase-property => wikibase-entityid
                 */
 
+               // Update ValidatorBuilders in repo if you change this
                $types = array(
                        'commonsMedia'      => array( $this, 'buildMediaType' ),
                        'globe-coordinate'  => array( $this, 
'buildCoordinateType' ),
@@ -117,13 +68,7 @@
         * @return DataType
         */
        public function buildItemType( $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, 
Item::ENTITY_TYPE );
-
-               return new DataType( $id, 'wikibase-entityid', $validators );
+               return new DataType( $id, 'wikibase-entityid', array() );
        }
 
        /**
@@ -132,30 +77,7 @@
         * @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 );
-       }
-
-       /**
-        * @param int $maxLength Defaults to 400 characters. This was an 
arbitrary decision when it
-        * turned out that 255 was to short for descriptions.
-        *
-        * @return ValueValidator[]
-        */
-       private function getCommonStringValidators( $maxLength = 400  ) {
-               $validators = array();
-
-               $validators[] = new TypeValidator( 'string' );
-               //TODO: validate UTF8 (here and elsewhere)
-               $validators[] = new StringLengthValidator( 1, $maxLength, 
'mb_strlen' );
-               $validators[] = new RegexValidator( '/^\s|[\r\n\t]|\s$/', true 
); // no leading/trailing whitespace, no line breaks.
-
-               return $validators;
+               return new DataType( $id, 'wikibase-entityid', array() );
        }
 
        /**
@@ -164,22 +86,8 @@
         * @return DataType
         */
        public function buildMediaType( $id ) {
-               // oi_archive_name is max 255 bytes, which include a timestamp 
and an exclamation mark,
-               // so restrict file name to 240 bytes (see 
UploadBase::getTitle).
-               $validators = $this->getCommonStringValidators( 240 );
 
-               $validators[] = new RegexValidator( '@[#/:\\\\]@u', true ); // 
no nasty chars
-               // Must contain a non-empty file name and a non-empty, 
character-only file extension.
-               $validators[] = new RegexValidator( '/.\.\w+$/u' );
-               //TODO: add a validator that checks the rules that MediaWiki 
imposes on filenames for uploads.
-               //      $wgLegalTitleChars and $wgIllegalFileChars define this, 
but we need these for the *target* wiki.
-               //TODO: add a validator that uses a foreign DB query to check 
whether the file actually exists on commons.
-
-               $topValidator = new DataValueValidator(
-                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
-               );
-
-               return new DataType( $id, 'string', array( new TypeValidator( 
'DataValues\DataValue' ), $topValidator ) );
+               return new DataType( $id, 'string', array() );
        }
 
        /**
@@ -188,13 +96,7 @@
         * @return DataType
         */
        public function buildStringType( $id ) {
-               $validators = $this->getCommonStringValidators();
-
-               $topValidator = new DataValueValidator(
-                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
-               );
-
-               return new DataType( $id, 'string', array( new TypeValidator( 
'DataValues\DataValue' ), $topValidator ) );
+               return new DataType( $id, 'string', array() );
        }
 
        /**
@@ -203,23 +105,7 @@
         * @return DataType
         */
        public function buildMonolingualTextType( $id ) {
-               $validators = array();
-
-               $validators[] = new DataFieldValidator(
-                       'text',
-                       new CompositeValidator( 
$this->getCommonStringValidators() ) //Note: each validator is fatal
-               );
-
-               $validators[] = new DataFieldValidator(
-                       'language',
-                       new MembershipValidator( Utils::getLanguageCodes() )
-               );
-
-               $topValidator = new DataValueValidator(
-                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
-               );
-
-               return new DataType( $id, 'monolingualtext', array( new 
TypeValidator( 'DataValues\DataValue' ), $topValidator ) );
+               return new DataType( $id, 'monolingualtext', array() );
        }
 
        /**
@@ -228,48 +114,7 @@
         * @return DataType
         */
        public function buildTimeType( $id ) {
-               $validators = array();
-               $validators[] = new TypeValidator( 'array' );
-
-               // Expected to be a short IRI, see TimeFormatter and TimeParser.
-               $urlValidator = $this->buildUrlValidator( array( 'http', 
'https' ), 255 );
-               //TODO: enforce well known calendar models from config
-
-               $validators[] = new DataFieldValidator( 'calendarmodel', 
$urlValidator );
-
-               // time string field
-               $timeStringValidators = array();
-               $timeStringValidators[] = new TypeValidator( 'string' );
-
-               // down to the second
-               //$maxPrecision = TimeValue::PRECISION_SECOND;
-               //$isoDataPattern = 
'!^[-+]\d{1,16}-(0\d|1[012])-([012]\d|3[01])T([01]\d|2[0123]):[0-5]\d:([0-5]\d|6[012])Z$!';
-
-               // down to the day
-               $maxPrecision = TimeValue::PRECISION_DAY;
-               $isoDataPattern = 
'!^[-+]\d{1,16}-(0\d|1[012])-([012]\d|3[01])T00:00:00Z$!';
-
-               $timeStringValidators[] = new RegexValidator( $isoDataPattern );
-
-               $validators[] = new DataFieldValidator(
-                       'time',
-                       new CompositeValidator( $timeStringValidators ) //Note: 
each validator is fatal
-               );
-
-               $precisionValidators = array();
-               $precisionValidators[] = new TypeValidator( 'integer' );
-               $precisionValidators[] = new NumberRangeValidator( 
TimeValue::PRECISION_Ga, $maxPrecision );
-
-               $validators[] = new DataFieldValidator(
-                       'precision',
-                       new CompositeValidator( $precisionValidators ) //Note: 
each validator is fatal
-               );
-
-               $topValidator = new DataValueValidator(
-                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
-               );
-
-               return new DataType( $id, 'time', array( new TypeValidator( 
'DataValues\DataValue' ), $topValidator ) );
+               return new DataType( $id, 'time', array() );
        }
 
        /**
@@ -278,42 +123,7 @@
         * @return DataType
         */
        public function buildCoordinateType( $id ) {
-               $validators = array();
-               $validators[] = new TypeValidator( 'array' );
-
-               // Expected to be a short IRI, see GlobeCoordinateValue and 
GlobeCoordinateParser.
-               $urlValidator = $this->buildUrlValidator( array( 'http', 
'https' ), 255 );
-               //TODO: enforce well known reference globes from config
-
-               $validators[] = new DataFieldValidator( 'precision', new 
NumberValidator() );
-
-               $validators[] = new DataFieldValidator( 'globe', $urlValidator 
);
-
-               $topValidator = new DataValueValidator(
-                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
-               );
-
-               return new DataType( $id, 'globecoordinate', array( new 
TypeValidator( 'DataValues\DataValue' ), $topValidator ) );
-       }
-
-       /**
-        * @param string[] $urlSchemes List of URL schemes, e.g. 'http'
-        * @param int $maxLength Defaults to 500 characters. Even if URLs are 
unlimited in theory they
-        * should be limited to about 2000. About 500 is a reasonable 
compromise.
-        * @see http://stackoverflow.com/a/417184
-        *
-        * @return CompositeValidator
-        */
-       public function buildUrlValidator( $urlSchemes, $maxLength = 500 ) {
-               $validators = array();
-               $validators[] = new TypeValidator( 'string' );
-               $validators[] = new StringLengthValidator( 2, $maxLength );
-
-               $urlValidators = new UrlSchemeValidators();
-               $urlSchemeValidators = $urlValidators->getValidators( 
$urlSchemes );
-               $validators[] = new UrlValidator( $urlSchemeValidators );
-
-               return new CompositeValidator( $validators ); //Note: each 
validator is fatal
+               return new DataType( $id, 'globecoordinate', array() );
        }
 
        /**
@@ -322,13 +132,7 @@
         * @return DataType
         */
        public function buildUrlType( $id ) {
-               $urlValidator = $this->buildUrlValidator( $this->urlSchemes );
-
-               $topValidator = new DataValueValidator(
-                       $urlValidator
-               );
-
-               return new DataType( $id, 'string', array( new TypeValidator( 
'DataValues\DataValue' ), $topValidator ) );
+               return new DataType( $id, 'string', array() );
        }
 
        /**
@@ -337,26 +141,7 @@
         * @return DataType
         */
        public function buildQuantityType( $id ) {
-               $validators = array();
-               $validators[] = new TypeValidator( 'array' );
-
-               // the 'amount' field is already validated by QuantityValue's 
constructor
-               // the 'digits' field is already validated by QuantityValue's 
constructor
-
-               $unitValidators = new AlternativeValidator( array(
-                       // NOTE: "1" is always considered legal for historical 
reasons,
-                       // since we use it to represent "unitless" quantities. 
We could also use
-                       // http://qudt.org/vocab/unit#Unitless or 
https://www.wikidata.org/entity/Q199
-                       new MembershipValidator( array( '1' ) ),
-                       $this->buildUrlValidator( array( 'http', 'https' ), 255 
),
-               ) );
-               $validators[] = new DataFieldValidator( 'unit', $unitValidators 
);
-
-               $topValidator = new DataValueValidator(
-                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
-               );
-
-               return new DataType( $id, 'quantity', array( new TypeValidator( 
'DataValues\QuantityValue' ), $topValidator ) );
+               return new DataType( $id, 'quantity', array() );
        }
 
 }
diff --git a/repo/includes/DataTypeValidatorFactory.php 
b/repo/includes/DataTypeValidatorFactory.php
new file mode 100644
index 0000000..0d492f4
--- /dev/null
+++ b/repo/includes/DataTypeValidatorFactory.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Wikibase\Repo;
+
+/**
+ * Description of DataTypeValidatorFactory
+ *
+ * @author Adrian Heine < [email protected] >
+ */
+class DataTypeValidatorFactory {
+
+       /**
+        * @var callable[]
+        */
+       private $validatorBuilders;
+
+       //put your code here
+
+       public function __construct( ValidatorBuilders $validatorBuilders ) {
+               $this->validatorBuilders = 
$validatorBuilders->getDataTypeValidators();
+       }
+
+       /**
+        * 
+        * @param string $dataValueType
+        * 
+        * @return ValueValidator[]
+        */
+       public function getValidators( $dataValueType ) {
+               return call_user_func(
+                       $this->validatorBuilders[ $dataValueType ]
+               );
+       }
+
+}
diff --git a/repo/includes/ValidatorBuilders.php 
b/repo/includes/ValidatorBuilders.php
new file mode 100644
index 0000000..0f799f3
--- /dev/null
+++ b/repo/includes/ValidatorBuilders.php
@@ -0,0 +1,324 @@
+<?php
+
+namespace Wikibase\Repo;
+
+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\AlternativeValidator;
+use Wikibase\Validators\CompositeValidator;
+use Wikibase\Validators\DataFieldValidator;
+use Wikibase\Validators\DataValueValidator;
+use Wikibase\Validators\EntityExistsValidator;
+use Wikibase\Validators\MembershipValidator;
+use Wikibase\Validators\NumberRangeValidator;
+use Wikibase\Validators\NumberValidator;
+use Wikibase\Validators\RegexValidator;
+use Wikibase\Validators\StringLengthValidator;
+use Wikibase\Validators\TypeValidator;
+use Wikibase\Validators\UrlSchemeValidators;
+use Wikibase\Validators\UrlValidator;
+
+/**
+ * Defines validators for the data types supported by Wikibase.
+ *
+ * @since 0.4
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class ValidatorBuilders {
+
+       /**
+        * @var EntityIdParser
+        */
+       private $entityIdParser;
+
+       /**
+        * @var EntityLookup
+        */
+       private $entityLookup;
+
+       /**
+        * @var string[]
+        */
+       private $urlSchemes;
+
+       /**
+        * @param EntityLookup $lookup
+        * @param EntityIdParser $idParser
+        * @param string[] $urlSchemes
+        */
+       public function __construct(
+               EntityLookup $lookup,
+               EntityIdParser $idParser,
+               array $urlSchemes
+       ) {
+               $this->entityIdParser = $idParser;
+               $this->entityLookup = $lookup;
+               $this->urlSchemes = $urlSchemes;
+       }
+
+       /**
+        * @return callable[] ValueValidator for DataTypes build spec
+        */
+       public function getDataTypeValidators() {
+
+               $types = array(
+                       'commonsMedia'      => array( $this, 
'buildMediaValidators' ),
+                       'globe-coordinate'  => array( $this, 
'buildCoordinateValidators' ),
+                       'quantity'          => array( $this, 
'buildQuantityValidators' ),
+                       'string'            => array( $this, 
'buildStringValidators' ),
+                       'time'              => array( $this, 
'buildTimeValidators' ),
+                       'url'               => array( $this, 
'buildUrlValidators' ),
+                       'wikibase-item'     => array( $this, 
'buildItemValidators' ),
+                       'wikibase-property' => array( $this, 
'buildPropertyValidators' ),
+                       'monolingualtext'   => array( $this, 
'buildMonolingualTextValidators' ),
+               );
+
+               $experimental = array(
+                       // 'multilingualtext' => array( $this, 
'buildMultilingualTextValidators' ),
+               );
+
+               if ( defined( 'WB_EXPERIMENTAL_FEATURES' ) && 
WB_EXPERIMENTAL_FEATURES ) {
+                       $types = array_merge( $types, $experimental );
+               }
+
+               return $types;
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildItemValidators() {
+               $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, 
Item::ENTITY_TYPE );
+
+               return $validators;
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildPropertyValidators( ) {
+               $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 $validators;
+       }
+
+       /**
+        * @param int $maxLength Defaults to 400 characters. This was an 
arbitrary decision when it
+        * turned out that 255 was to short for descriptions.
+        *
+        * @return ValueValidator[]
+        */
+       private function getCommonStringValidators( $maxLength = 400  ) {
+               $validators = array();
+
+               $validators[] = new TypeValidator( 'string' );
+               //TODO: validate UTF8 (here and elsewhere)
+               $validators[] = new StringLengthValidator( 1, $maxLength, 
'mb_strlen' );
+               $validators[] = new RegexValidator( '/^\s|[\r\n\t]|\s$/', true 
); // no leading/trailing whitespace, no line breaks.
+
+               return $validators;
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildMediaValidators() {
+               // oi_archive_name is max 255 bytes, which include a timestamp 
and an exclamation mark,
+               // so restrict file name to 240 bytes (see 
UploadBase::getTitle).
+               $validators = $this->getCommonStringValidators( 240 );
+
+               $validators[] = new RegexValidator( '@[#/:\\\\]@u', true ); // 
no nasty chars
+               // Must contain a non-empty file name and a non-empty, 
character-only file extension.
+               $validators[] = new RegexValidator( '/.\.\w+$/u' );
+               //TODO: add a validator that checks the rules that MediaWiki 
imposes on filenames for uploads.
+               //      $wgLegalTitleChars and $wgIllegalFileChars define this, 
but we need these for the *target* wiki.
+               //TODO: add a validator that uses a foreign DB query to check 
whether the file actually exists on commons.
+
+               $topValidator = new DataValueValidator(
+                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
+               );
+
+               return array( new TypeValidator( 'DataValues\DataValue' ), 
$topValidator );
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildStringValidators() {
+               $validators = $this->getCommonStringValidators();
+
+               $topValidator = new DataValueValidator(
+                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
+               );
+
+               return array( new TypeValidator( 'DataValues\DataValue' ), 
$topValidator );
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildMonolingualTextValidators() {
+               $validators = array();
+
+               $validators[] = new DataFieldValidator(
+                       'text',
+                       new CompositeValidator( 
$this->getCommonStringValidators() ) //Note: each validator is fatal
+               );
+
+               $validators[] = new DataFieldValidator(
+                       'language',
+                       new MembershipValidator( Utils::getLanguageCodes() )
+               );
+
+               $topValidator = new DataValueValidator(
+                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
+               );
+
+               return array( new TypeValidator( 'DataValues\DataValue' ), 
$topValidator );
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildTimeValidators() {
+               $validators = array();
+               $validators[] = new TypeValidator( 'array' );
+
+               // Expected to be a short IRI, see TimeFormatter and TimeParser.
+               $urlValidator = $this->getUrlValidator( array( 'http', 'https' 
), 255 );
+               //TODO: enforce well known calendar models from config
+
+               $validators[] = new DataFieldValidator( 'calendarmodel', 
$urlValidator );
+
+               // time string field
+               $timeStringValidators = array();
+               $timeStringValidators[] = new TypeValidator( 'string' );
+
+               // down to the second
+               //$maxPrecision = TimeValue::PRECISION_SECOND;
+               //$isoDataPattern = 
'!^[-+]\d{1,16}-(0\d|1[012])-([012]\d|3[01])T([01]\d|2[0123]):[0-5]\d:([0-5]\d|6[012])Z$!';
+
+               // down to the day
+               $maxPrecision = TimeValue::PRECISION_DAY;
+               $isoDataPattern = 
'!^[-+]\d{1,16}-(0\d|1[012])-([012]\d|3[01])T00:00:00Z$!';
+
+               $timeStringValidators[] = new RegexValidator( $isoDataPattern );
+
+               $validators[] = new DataFieldValidator(
+                       'time',
+                       new CompositeValidator( $timeStringValidators ) //Note: 
each validator is fatal
+               );
+
+               $precisionValidators = array();
+               $precisionValidators[] = new TypeValidator( 'integer' );
+               $precisionValidators[] = new NumberRangeValidator( 
TimeValue::PRECISION_Ga, $maxPrecision );
+
+               $validators[] = new DataFieldValidator(
+                       'precision',
+                       new CompositeValidator( $precisionValidators ) //Note: 
each validator is fatal
+               );
+
+               $topValidator = new DataValueValidator(
+                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
+               );
+
+               return array( new TypeValidator( 'DataValues\DataValue' ), 
$topValidator );
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildCoordinateValidators() {
+               $validators = array();
+               $validators[] = new TypeValidator( 'array' );
+
+               // Expected to be a short IRI, see GlobeCoordinateValue and 
GlobeCoordinateParser.
+               $urlValidator = $this->getUrlValidator( array( 'http', 'https' 
), 255 );
+               //TODO: enforce well known reference globes from config
+
+               $validators[] = new DataFieldValidator( 'precision', new 
NumberValidator() );
+
+               $validators[] = new DataFieldValidator( 'globe', $urlValidator 
);
+
+               $topValidator = new DataValueValidator(
+                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
+               );
+
+               return array( new TypeValidator( 'DataValues\DataValue' ), 
$topValidator );
+       }
+
+       /**
+        * @param string[] $urlSchemes List of URL schemes, e.g. 'http'
+        * @param int $maxLength Defaults to 500 characters. Even if URLs are 
unlimited in theory they
+        * should be limited to about 2000. About 500 is a reasonable 
compromise.
+        * @see http://stackoverflow.com/a/417184
+        *
+        * @return CompositeValidator
+        */
+       private function getUrlValidator( $urlSchemes, $maxLength = 500 ) {
+               $validators = array();
+               $validators[] = new TypeValidator( 'string' );
+               $validators[] = new StringLengthValidator( 2, $maxLength );
+
+               $urlValidators = new UrlSchemeValidators();
+               $urlSchemeValidators = $urlValidators->getValidator( 
$urlSchemes );
+               $validators[] = new UrlValidator( $urlSchemeValidators );
+
+               return new CompositeValidator( $validators ); //Note: each 
validator is fatal
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildUrlValidators( ) {
+               $urlValidator = $this->getUrlValidator( $this->urlSchemes );
+
+               $topValidator = new DataValueValidator(
+                       $urlValidator
+               );
+
+               return array( new TypeValidator( 'DataValues\DataValue' ), 
$topValidator );
+       }
+
+       /**
+        * @return ValueValidator[]
+        */
+       public function buildQuantityValidators( ) {
+               $validators = array();
+               $validators[] = new TypeValidator( 'array' );
+
+               // the 'amount' field is already validated by QuantityValue's 
constructor
+               // the 'digits' field is already validated by QuantityValue's 
constructor
+
+               $unitValidators = new AlternativeValidator( array(
+                       // NOTE: "1" is always considered legal for historical 
reasons,
+                       // since we use it to represent "unitless" quantities. 
We could also use
+                       // http://qudt.org/vocab/unit#Unitless or 
https://www.wikidata.org/entity/Q199
+                       new MembershipValidator( array( '1' ) ),
+                       $this->getUrlValidator( array( 'http', 'https' ), 255 ),
+               ) );
+               $validators[] = new DataFieldValidator( 'unit', $unitValidators 
);
+
+               $topValidator = new DataValueValidator(
+                       new CompositeValidator( $validators ) //Note: each 
validator is fatal
+               );
+
+               return array( new TypeValidator( 'DataValues\QuantityValue' ), 
$topValidator );
+       }
+
+}
diff --git a/repo/includes/Validators/SnakValidator.php 
b/repo/includes/Validators/SnakValidator.php
index 14aa045..d1bbbd1 100644
--- a/repo/includes/Validators/SnakValidator.php
+++ b/repo/includes/Validators/SnakValidator.php
@@ -17,6 +17,7 @@
 use Wikibase\DataModel\Snak\PropertyValueSnak;
 use Wikibase\DataModel\Snak\Snak;
 use Wikibase\DataModel\Statement\Statement;
+use Wikibase\Repo\DataTypeValidatorFactory;
 
 /**
  * Class SnakValidator for validating Snaks.
@@ -29,21 +30,28 @@
 class SnakValidator implements ValueValidator {
 
        /**
+        * @var DataTypeFactory
+        */
+       private $dataTypeFactory;
+
+       /**
         * @var PropertyDataTypeLookup
         */
        private $propertyDataTypeLookup;
 
        /**
-        * @var DataTypeFactory
+        * @var DataTypeValidatorFactory
         */
-       private $dataTypeFactory;
+       private $validatorFactory;
 
        public function __construct(
                PropertyDataTypeLookup $propertyDataTypeLookup,
-               DataTypeFactory $dataTypeFactory
+               DataTypeFactory $dataTypeFactory,
+               DataTypeValidatorFactory $validatorFactory
        ) {
-               $this->propertyDataTypeLookup = $propertyDataTypeLookup;
                $this->dataTypeFactory = $dataTypeFactory;
+               $this->propertyDataTypeLookup = $propertyDataTypeLookup;
+               $this->validatorFactory = $validatorFactory;
        }
 
        /**
@@ -174,7 +182,7 @@
         * @return Result
         */
        public function validateDataValue( DataValue $dataValue, $dataTypeId ) {
-               $dataType = $this->dataTypeFactory->getType( $dataTypeId );
+               $dataValueType = $this->dataTypeFactory->getType( $dataTypeId 
)->getDataValueType();
 
                if ( $dataValue instanceof UnDeserializableValue ) {
                        $result = Result::newError( array(
@@ -185,22 +193,21 @@
                                        array( $dataValue->getReason() )
                                ),
                        ) );
-               } elseif ( $dataType->getDataValueType() != 
$dataValue->getType() ) {
+               } elseif ( $dataValueType != $dataValue->getType() ) {
                        $result = Result::newError( array(
                                Error::newError(
-                                       'Bad value type: ' . 
$dataValue->getType() . ', expected ' . $dataType->getDataValueType(),
+                                       'Bad value type: ' . 
$dataValue->getType() . ', expected ' . $dataValueType,
                                        null,
                                        'bad-value-type',
-                                       array( $dataValue->getType(), 
$dataType->getDataValueType() )
+                                       array( $dataValue->getType(), 
$dataValueType )
                                ),
                        ) );
                } else {
                        $result = Result::newSuccess();
                }
 
-               //XXX: Perhaps DataType should have a validate() method (even 
implement ValueValidator)
-               //     At least, DataType should expose only one validator, 
which would be a CompositeValidator
-               foreach ( $dataType->getValidators() as $validator ) {
+               //XXX: DataTypeValidatorFactory should expose only one 
validator, which would be a CompositeValidator
+               foreach ( $this->validatorFactory->getValidators( 
$dataValueType ) as $validator ) {
                        $subResult = $validator->validate( $dataValue );
 
                        //XXX: Some validators should be fatal and cause us to 
abort the loop.
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index fbfbe04..c48d125 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -211,12 +211,7 @@
         */
        public function getDataTypeFactory() {
                if ( $this->dataTypeFactory === null ) {
-                       $urlSchemes = $this->settings->getSetting( 'urlSchemes' 
);
-                       $builders = new WikibaseDataTypeBuilders(
-                               $this->getEntityLookup(),
-                               $this->getEntityIdParser(),
-                               $urlSchemes
-                       );
+                       $builders = new WikibaseDataTypeBuilders();
 
                        $typeBuilderSpecs = array_intersect_key(
                                $builders->getDataTypeBuilders(),
@@ -424,7 +419,8 @@
        public function getSnakValidator() {
                return new SnakValidator(
                        $this->getPropertyDataTypeLookup(),
-                       $this->getDataTypeFactory()
+                       $this->getDataTypeFactory(),
+                       $this->getDataTypeValidatorFactory()
                );
        }
 
@@ -1030,4 +1026,16 @@
                );
        }
 
+       private function getDataTypeValidatorFactory() {
+               $urlSchemes = $this->settings->getSetting( 'urlSchemes' );
+
+               return new DataTypeValidatorFactory(
+                       new ValidatorBuilders(
+                               $this->getEntityLookup(),
+                               $this->getEntityIdParser(),
+                               $urlSchemes
+                       )
+               );
+       }
+
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6fb14c135315c7c064ccf49c019670dfab68c857
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Adrian Lang <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to