Daniel Kinzler has uploaded a new change for review.

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


Change subject: (bug 49263) Validate all Snaks passed to the API.
......................................................................

(bug 49263) Validate all Snaks passed to the API.

This enforces constraints on the Snak's data types.

This should prevent invalid Snaks to be created
and stored in the database.

Change-Id: I67b9ae480c4a667043486b45027796c0c69c5ffa
---
M repo/Wikibase.classes.php
M repo/Wikibase.hooks.php
M repo/includes/WikibaseRepo.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
A repo/includes/api/SnakValidationHelper.php
M repo/tests/phpunit/includes/Validators/SnakValidatorTest.php
A repo/tests/phpunit/includes/Validators/TestValidator.php
M repo/tests/phpunit/includes/api/SetClaimTest.php
M repo/tests/phpunit/includes/api/SetQualifierTest.php
M repo/tests/phpunit/includes/api/SetReferenceTest.php
A repo/tests/phpunit/includes/api/SnakValidationHelperTest.php
M repo/tests/phpunit/includes/store/sql/EntityPerPageBuilderTest.php
15 files changed, 671 insertions(+), 73 deletions(-)


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

diff --git a/repo/Wikibase.classes.php b/repo/Wikibase.classes.php
index 57694e9..2010eac 100644
--- a/repo/Wikibase.classes.php
+++ b/repo/Wikibase.classes.php
@@ -95,6 +95,7 @@
                'Wikibase\Api\SetClaim' => 'includes/api/SetClaim.php',
                'Wikibase\Api\RemoveQualifiers' => 
'includes/api/RemoveQualifiers.php',
                'Wikibase\Api\SetQualifier' => 'includes/api/SetQualifier.php',
+               'Wikibase\Api\SnakValidationHelper' => 
'includes/api/SnakValidationHelper.php',
 
                // includes/content
                'Wikibase\EntityContent' => 
'includes/content/EntityContent.php',
@@ -171,6 +172,7 @@
                'Wikibase\Test\EntityDataSerializationServiceTest' => 
'tests/phpunit/includes/specials/EntityDataSerializationServiceTest.php',
                'Wikibase\Test\EntityDataRequestHandlerTest' => 
'tests/phpunit/includes/specials/EntityDataRequestHandlerTest.php',
                'Wikibase\Test\EntityDataTestProvider' => 
'tests/phpunit/includes/specials/EntityDataTestProvider.php',
+               'Wikibase\Test\TestValidator' => 
'tests/phpunit/includes/Validators/TestValidator.php',
        );
 
 
diff --git a/repo/Wikibase.hooks.php b/repo/Wikibase.hooks.php
index c97f9a3..567380d 100644
--- a/repo/Wikibase.hooks.php
+++ b/repo/Wikibase.hooks.php
@@ -186,6 +186,7 @@
                        'api/SetClaim',
                        'api/RemoveQualifiers',
                        'api/SetQualifier',
+                       'api/SnakValidationHelper',
 
                        'changeop/ChangeOps',
                        'changeop/ChangeOpLabel',
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 8da42ba..b52a26f 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -6,12 +6,17 @@
 use ValueFormatters\FormatterOptions;
 use ValueParsers\ParserOptions;
 use Wikibase\EntityContentFactory;
+use Wikibase\EntityLookup;
 use Wikibase\Lib\EntityIdFormatter;
 use Wikibase\Lib\EntityIdLabelFormatter;
 use Wikibase\Lib\EntityIdParser;
 use Wikibase\Lib\WikibaseDataTypeBuilders;
+use Wikibase\Lib\EntityRetrievingDataTypeLookup;
+use Wikibase\Lib\PropertyDataTypeLookup;
 use Wikibase\Settings;
 use Wikibase\SettingsArray;
+use Wikibase\Store;
+use Wikibase\StoreFactory;
 
 /**
  * Top level factory for the WikibaseRepo extension.
@@ -55,12 +60,24 @@
        private $idFormatter = null;
 
        /**
+        * @var Store
+        */
+       private $store;
+
+       /**
+        * @var PropertyDataTypeLookup
+        */
+       private $propertyDataTypeLookup;
+
+       /**
         * @since 0.4
         *
-        * @param SettingsArray $settings
+        * @param SettingsArray   $settings
+        * @param Store           $store
         */
-       public function __construct( SettingsArray $settings ) {
+       public function __construct( SettingsArray $settings, Store $store ) {
                $this->settings = $settings;
+               $this->store = $store;
        }
 
        /**
@@ -122,6 +139,28 @@
        }
 
        /**
+        * @since 0.4
+        *
+        * @return PropertyDataTypeLookup
+        */
+       public function getPropertyDataTypeLookup() {
+               if ( $this->propertyDataTypeLookup === null ) {
+                       $this->propertyDataTypeLookup = new 
EntityRetrievingDataTypeLookup( $this->getEntityLookup() );
+               }
+
+               return $this->propertyDataTypeLookup;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @return EntityLookup
+        */
+       public function getEntityLookup() {
+               return $this->store->getEntityLookup();
+       }
+
+       /**
         * Returns the base to use when generating URIs for use in RDF output.
         *
         * @return string
@@ -166,7 +205,10 @@
         * @return WikibaseRepo
         */
        public static function newInstance() {
-               return new self( Settings::singleton() );
+               return new self(
+                       Settings::singleton(),
+                       StoreFactory::getStore()
+               );
        }
 
        /**
diff --git a/repo/includes/api/SetClaim.php b/repo/includes/api/SetClaim.php
index 23b34be..63edd50 100644
--- a/repo/includes/api/SetClaim.php
+++ b/repo/includes/api/SetClaim.php
@@ -3,6 +3,7 @@
 namespace Wikibase\Api;
 
 use DataValues\IllegalValueException;
+use ApiMain;
 use Diff\CallbackListDiffer;
 use MWException;
 use ApiBase;
@@ -15,6 +16,7 @@
 use Wikibase\ClaimSummaryBuilder;
 use Wikibase\Repo\WikibaseRepo;
 use Wikibase\Summary;
+use Wikibase\validators\SnakValidator;
 
 /**
  * API module for creating or updating an entire Claim.
@@ -48,12 +50,36 @@
        // TODO: rights
 
        /**
+        * @var SnakValidationHelper
+        */
+       protected $snakValidation;
+
+       /**
+        * see ApiBase::__construct()
+        *
+        * @param ApiMain $mainModule
+        * @param string  $moduleName
+        * @param string  $modulePrefix
+        */
+       public function __construct( ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
+               parent::__construct( $mainModule, $moduleName, $modulePrefix );
+
+               $this->snakValidation = new SnakValidationHelper(
+                       $this,
+                       
WikibaseRepo::getDefaultInstance()->getPropertyDataTypeLookup(),
+                       WikibaseRepo::getDefaultInstance()->getDataTypeFactory()
+               );
+       }
+
+       /**
         * @see ApiBase::execute
         *
         * @since 0.4
         */
        public function execute() {
                $claim = $this->getClaimFromRequest();
+
+               $this->snakValidation->validateClaimSnaks( $claim );
 
                $comparer = function( \Comparable $old, \Comparable $new ) {
                        return $old->equals( $new );
@@ -197,5 +223,4 @@
                        // 'ex' => 'desc'
                );
        }
-
 }
diff --git a/repo/includes/api/SetClaimValue.php 
b/repo/includes/api/SetClaimValue.php
index cbf00d0..8afeb20 100644
--- a/repo/includes/api/SetClaimValue.php
+++ b/repo/includes/api/SetClaimValue.php
@@ -5,6 +5,7 @@
 use ApiBase, MWException;
 
 use DataValues\IllegalValueException;
+use ApiMain;
 use Wikibase\Autocomment;
 use Wikibase\EntityId;
 use Wikibase\Entity;
@@ -15,6 +16,7 @@
 use Wikibase\Claims;
 use Wikibase\Lib\ClaimGuidValidator;
 use Wikibase\Repo\WikibaseRepo;
+use Wikibase\validators\SnakValidator;
 
 /**
  * API module for setting the DataValue contained by the main snak of a claim.
@@ -48,6 +50,28 @@
        // TODO: rights
        // TODO: conflict detection
        // TODO: claim uniqueness
+
+       /**
+        * @var SnakValidationHelper
+        */
+       protected $snakValidation;
+
+       /**
+        * see ApiBase::__construct()
+        *
+        * @param ApiMain $mainModule
+        * @param string  $moduleName
+        * @param string  $modulePrefix
+        */
+       public function __construct( ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
+               parent::__construct( $mainModule, $moduleName, $modulePrefix );
+
+               $this->snakValidation = new SnakValidationHelper(
+                       $this,
+                       
WikibaseRepo::getDefaultInstance()->getPropertyDataTypeLookup(),
+                       WikibaseRepo::getDefaultInstance()->getDataTypeFactory()
+               );
+       }
 
        /**
         * @see \ApiBase::execute
@@ -148,9 +172,10 @@
                }
 
                try {
-                       $snak = SnakObject::newFromType( $snakType, 
$constructorArguments );
-                       $claim->setMainSnak( $snak );
+                       $snak = SnakObject::newFromType( $snakType, 
$constructorArguments ); //TODO: use SnakFactory
+                       $this->snakValidation->validateSnak( $snak );
 
+                       $claim->setMainSnak( $snak );
                        $entity->setClaims( $claims );
 
                        return $claim;
diff --git a/repo/includes/api/SetQualifier.php 
b/repo/includes/api/SetQualifier.php
index 31891bd..87fd2d1 100644
--- a/repo/includes/api/SetQualifier.php
+++ b/repo/includes/api/SetQualifier.php
@@ -4,6 +4,7 @@
 
 use ApiBase;
 use DataValues\IllegalValueException;
+use ApiMain;
 use MWException;
 
 use ValueParsers\ParseException;
@@ -13,12 +14,14 @@
 use Wikibase\EntityContentFactory;
 use Wikibase\Claim;
 use Wikibase\Repo\WikibaseRepo;
+use Wikibase\Snak;
 use Wikibase\Snaks;
 use Wikibase\SnakFactory;
 use Wikibase\PropertyValueSnak;
 use Wikibase\LibRegistry;
 use Wikibase\Settings;
 use Wikibase\Lib\ClaimGuidValidator;
+use Wikibase\validators\SnakValidator;
 
 /**
  * API module for creating a qualifier or setting the value of an existing one.
@@ -54,6 +57,28 @@
        // TODO: conflict detection
        // TODO: more explicit support for snak merging?
        // TODO: claim uniqueness
+
+       /**
+        * @var SnakValidationHelper
+        */
+       protected $snakValidation;
+
+       /**
+        * see ApiBase::__construct()
+        *
+        * @param ApiMain $mainModule
+        * @param string  $moduleName
+        * @param string  $modulePrefix
+        */
+       public function __construct( ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
+               parent::__construct( $mainModule, $moduleName, $modulePrefix );
+
+               $this->snakValidation = new SnakValidationHelper(
+                       $this,
+                       
WikibaseRepo::getDefaultInstance()->getPropertyDataTypeLookup(),
+                       WikibaseRepo::getDefaultInstance()->getDataTypeFactory()
+               );
+       }
 
        /**
         * @see ApiBase::execute
@@ -222,11 +247,15 @@
                }
 
                try {
-                       $factory = new SnakFactory();
+                       $factory = new SnakFactory(); //TODO: should be 
injected!
                        $newQualifier = $factory->newSnak( $propertyId, 
$snakType, $snakValue );
+
+                       $this->snakValidation->validateSnak( $newQualifier );
 
                        return $qualifiers->addSnak( $newQualifier );
                } catch ( IllegalValueException $ex ) {
+                       //Note: This handles failures during snak 
instantiation, not validation.
+                       //      Validation errors are handled by the validation 
helper.
                        $this->dieUsage( $ex->getMessage(), 
'setclaim-invalid-snak' );
                }
 
@@ -269,6 +298,8 @@
                                isset( $params['value'] ) ? 
\FormatJson::decode( $params['value'], true ) : null
                        );
 
+               $this->snakValidation->validateSnak( $newQualifier );
+
                        return $qualifiers->addSnak( $newQualifier );
                } catch ( IllegalValueException $ex ) {
                        $this->dieUsage( $ex->getMessage(), 
'setclaim-invalid-snak' );
diff --git a/repo/includes/api/SetReference.php 
b/repo/includes/api/SetReference.php
index da5abff..b61783c 100644
--- a/repo/includes/api/SetReference.php
+++ b/repo/includes/api/SetReference.php
@@ -5,6 +5,7 @@
 use ApiBase, MWException;
 
 use DataValues\IllegalValueException;
+use ApiMain;
 use Wikibase\EntityId;
 use Wikibase\Entity;
 use Wikibase\EntityContent;
@@ -14,7 +15,6 @@
 use Wikibase\Snaks;
 use Wikibase\SnakList;
 use Wikibase\Claims;
-use Wikibase\Settings;
 use Wikibase\Lib\ClaimGuidValidator;
 use Wikibase\Repo\WikibaseRepo;
 
@@ -50,6 +50,28 @@
        // TODO: example
        // TODO: rights
        // TODO: conflict detection
+
+       /**
+        * @var SnakValidationHelper
+        */
+       protected $snakValidation;
+
+       /**
+        * see ApiBase::__construct()
+        *
+        * @param ApiMain $mainModule
+        * @param string  $moduleName
+        * @param string  $modulePrefix
+        */
+       public function __construct( ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
+               parent::__construct( $mainModule, $moduleName, $modulePrefix );
+
+               $this->snakValidation = new SnakValidationHelper(
+                       $this,
+                       
WikibaseRepo::getDefaultInstance()->getPropertyDataTypeLookup(),
+                       WikibaseRepo::getDefaultInstance()->getDataTypeFactory()
+               );
+       }
 
        /**
         * @see ApiBase::execute
@@ -135,10 +157,13 @@
                                        $this->dieUsage( 'Invalid snak JSON 
given', 'setreference-invalid-snaks' );
                                }
                                foreach ( $byPropertySnaks as $rawSnak ) {
-                                       $snaks[] = 
$snakUnserializer->newFromSerialization( $rawSnak );
+                                       $snak = 
$snakUnserializer->newFromSerialization( $rawSnak );
+                                       $this->snakValidation->validateSnak( 
$snak );
+                                       $snaks[] = $snak;
                                }
                        }
                } catch ( IllegalValueException $ex ) {
+                       // Handle Snak instantiation failures
                        $this->dieUsage( $ex->getMessage(), 
'setreference-invalid-snaks' );
                }
 
diff --git a/repo/includes/api/SnakValidationHelper.php 
b/repo/includes/api/SnakValidationHelper.php
new file mode 100644
index 0000000..5dc4d9c
--- /dev/null
+++ b/repo/includes/api/SnakValidationHelper.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.2
+ *
+ * @file
+ * @ingroup WikibaseRepo
+ *
+ * @licence GNU GPL v2+
+ * @author John Erling Blad < [email protected] >
+ *
+ * @deprecated use the Summary class to build summaries instead
+ */
+
+namespace Wikibase\Api;
+
+
+use ApiBase;
+use DataTypes\DataTypeFactory;
+use Wikibase\Claim;
+use Wikibase\Lib\PropertyDataTypeLookup;
+use Wikibase\Snak;
+use Wikibase\Validators\SnakValidator;
+
+/**
+ * SnakValidationHelper is a component for API modules that performs validation
+ * of Snaks and Claims.
+ *
+ * @package Wikibase\Api
+ */
+class SnakValidationHelper {
+
+       /**
+        * @var ApiBase
+        */
+       protected $apiModule;
+
+       /**
+        * @var SnakValidator
+        */
+       protected $snakValidator;
+
+       /**
+        * @param ApiBase                $apiModule the API module for 
collaboration
+        * @param PropertyDataTypeLookup $propertyDataTypeLookup
+        * @param DataTypeFactory        $dataTypeFactory
+        *
+        * @todo: instead of taking an ApiBase instance, use an interface that 
provides dieUsage().
+        */
+       public function __construct(
+               ApiBase $apiModule,
+               PropertyDataTypeLookup $propertyDataTypeLookup,
+               DataTypeFactory $dataTypeFactory
+       ) {
+               $this->apiModule = $apiModule;
+               $this->snakValidator = new SnakValidator(
+                       $propertyDataTypeLookup,
+                       $dataTypeFactory
+               );
+       }
+
+       /**
+        * @see SnakValidator::validate()
+        * @param Snak $snak
+        */
+       public function validateSnak( Snak $snak ) {
+               $result = $this->snakValidator->validate( $snak );
+
+               if ( !$result->isValid() ) {
+                       $this->apiDieWithErrors( $result->getErrors() );
+               }
+       }
+
+       /**
+        * @see SnakValidator::validateClaimSnaks()
+        * @param Claim $claim
+        */
+       public function validateClaimSnaks( Claim $claim ) {
+               $result = $this->snakValidator->validateClaimSnaks( $claim );
+
+
+               if ( !$result->isValid() ) {
+                       $this->apiDieWithErrors( $result->getErrors() );
+               }
+       }
+
+
+       /**
+        * Returns a text representing the given errors.
+        * This can be used for reporting validation failures.
+        *
+        * @param \ValueValidators\Error[] $errors
+        * @return string
+        */
+       public function getValidatorErrorText( array $errors ) {
+               $messages = array();
+
+               foreach ( $errors as $error ) {
+                       //TODO: apply localization... how?!
+                       $messages[] = $error->getText();
+               }
+
+               $text = implode( '; ', $messages );
+               return $text;
+       }
+
+       /**
+        * Calls the API module's dieUsage() method with the appropriate
+        * error message derived from the given validator Errors.
+        *
+        * @param \ValueValidators\Error[] $errors
+        */
+       public function apiDieWithErrors( array $errors ) {
+               $errorText = $this->getValidatorErrorText( $errors );
+               $this->apiModule->dieUsage( $errorText, 'invalid-snak-value' );
+       }
+}
diff --git a/repo/tests/phpunit/includes/Validators/SnakValidatorTest.php 
b/repo/tests/phpunit/includes/Validators/SnakValidatorTest.php
index fe3e95c..27250fb 100644
--- a/repo/tests/phpunit/includes/Validators/SnakValidatorTest.php
+++ b/repo/tests/phpunit/includes/Validators/SnakValidatorTest.php
@@ -72,9 +72,9 @@
        public function setUp() {
                parent::setUp();
 
-               $numericValidator = new SnakValidatorTestValidator( 
'/^[0-9]+$/' );
-               $alphabeticValidator = new SnakValidatorTestValidator( 
'/^[a-zA-Z]+$/' );
-               $lengthValidator = new SnakValidatorTestValidator( 
'/^.{1,10}$/' );
+               $numericValidator = new TestValidator( '/^[0-9]+$/' );
+               $alphabeticValidator = new TestValidator( '/^[a-zA-Z]+$/' );
+               $lengthValidator = new TestValidator( '/^.{1,10}$/' );
 
                $this->dataTypeFactory = new DataTypeFactory();
                $this->dataTypeFactory->registerDataType( new DataType( 
'numeric', 'string', array(), array(), array( $numericValidator, 
$lengthValidator ) ) );
@@ -286,42 +286,4 @@
                $this->assertEquals( $expectedValid, $result->isValid(), 
$description );
        }
 
-}
-
-/**
- * Simple validator for testing.
- * Checks the string representation of a DataValue against a regular 
expression.
- *
- * @package Wikibase\Test
- */
-class SnakValidatorTestValidator implements ValueValidator {
-       protected $regex;
-
-       public function __construct( $regex ) {
-               $this->regex = $regex;
-       }
-
-       /**
-        * @return Result
-        */
-       public function validate( $value ) {
-               /* @var DataValue $value */
-
-               $value = $value->getArrayValue();
-
-               if ( preg_match( $this->regex, $value ) ) {
-                       return Result::newSuccess();
-               } else {
-                       return Result::newError( array(
-                               Error::newError( "doesn't match " . 
$this->regex )
-                       ) );
-               }
-       }
-
-       /**
-        * @param array $options
-        */
-       public function setOptions( array $options ) {
-               // noop
-       }
-}
+}
\ No newline at end of file
diff --git a/repo/tests/phpunit/includes/Validators/TestValidator.php 
b/repo/tests/phpunit/includes/Validators/TestValidator.php
new file mode 100644
index 0000000..761275f
--- /dev/null
+++ b/repo/tests/phpunit/includes/Validators/TestValidator.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace Wikibase\Test;
+
+use DataTypes\DataType;
+use DataTypes\DataTypeFactory;
+use DataValues\DataValue;
+use DataValues\StringValue;
+use ValueValidators\Error;
+use ValueValidators\Result;
+use ValueValidators\StringValidator;
+use ValueValidators\ValueValidator;
+use Wikibase\Claim;
+use Wikibase\EntityId;
+use Wikibase\Lib\InMemoryDataTypeLookup;
+use Wikibase\Lib\PropertyDataTypeLookup;
+use Wikibase\Property;
+use Wikibase\PropertyNoValueSnak;
+use Wikibase\PropertySomeValueSnak;
+use Wikibase\PropertyValueSnak;
+use Wikibase\Reference;
+use Wikibase\ReferenceList;
+use Wikibase\References;
+use Wikibase\Snak;
+use Wikibase\SnakList;
+use Wikibase\Statement;
+use Wikibase\Validators\DataValueValidator;
+use Wikibase\Validators\SnakValidator;
+
+/**
+ * A simple validator for use in unit tests.
+ * Checks a string value against a regular expression.
+ * If the value is a DataValue object, it's native representation
+ * ("array value") will be checked.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 0.4
+ *
+ * @ingroup WikibaseRepoTest
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class TestValidator implements ValueValidator {
+       protected $regex;
+
+       public function __construct( $regex ) {
+               $this->regex = $regex;
+       }
+
+       /**
+        * @return Result
+        */
+       public function validate( $value ) {
+               if ( $value instanceof DataValue ) {
+                       $value = $value->getArrayValue();
+               }
+
+               if ( preg_match( $this->regex, $value ) ) {
+                       return Result::newSuccess();
+               } else {
+                       return Result::newError( array(
+                               Error::newError( "doesn't match " . 
$this->regex )
+                       ) );
+               }
+       }
+
+       /**
+        * @param array $options
+        */
+       public function setOptions( array $options ) {
+               // noop
+       }
+}
diff --git a/repo/tests/phpunit/includes/api/SetClaimTest.php 
b/repo/tests/phpunit/includes/api/SetClaimTest.php
index 242cbe3..1bd2a4d 100644
--- a/repo/tests/phpunit/includes/api/SetClaimTest.php
+++ b/repo/tests/phpunit/includes/api/SetClaimTest.php
@@ -2,6 +2,9 @@
 
 namespace Wikibase\Test\Api;
 use Wikibase\Claim;
+use Wikibase\EntityId;
+use Wikibase\Property;
+use Wikibase\PropertyContent;
 
 /**
  * Unit tests for the Wikibase\Repo\Api\ApSetClaim class.
@@ -37,6 +40,7 @@
  *
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
+ * @author Daniel Kinzler
  */
 class SetClaimTest extends \ApiTestCase {
 
@@ -44,11 +48,36 @@
         * @return \Wikibase\Snak[]
         */
        protected function snakProvider() {
+               static $hasProperties = false;
+
+               $prop42 = new EntityId( Property::ENTITY_TYPE, 42 );
+               $prop9001 = new EntityId( Property::ENTITY_TYPE, 9001 );
+               $prop7201010 = new EntityId( Property::ENTITY_TYPE, 7201010 );
+
+               if ( !$hasProperties ) {
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( $prop42 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( $prop9001 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( $prop7201010 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $hasProperties = true;
+               }
+
                $snaks = array();
 
-               $snaks[] = new \Wikibase\PropertyNoValueSnak( 42 );
-               $snaks[] = new \Wikibase\PropertySomeValueSnak( 9001 );
-               $snaks[] = new \Wikibase\PropertyValueSnak( 7201010, new 
\DataValues\StringValue( 'o_O' ) );
+               $snaks[] = new \Wikibase\PropertyNoValueSnak( $prop42 );
+               $snaks[] = new \Wikibase\PropertySomeValueSnak( $prop9001 );
+               $snaks[] = new \Wikibase\PropertyValueSnak( $prop7201010, new 
\DataValues\StringValue( 'o_O' ) );
 
                return $snaks;
        }
@@ -59,11 +88,12 @@
        protected function claimProvider() {
                $statements = array();
 
-               $mainSnak = new \Wikibase\PropertyNoValueSnak( 42 );
+               $snaks = $this->snakProvider();
+               $mainSnak = $snaks[0];
                $statement = new \Wikibase\Statement( $mainSnak );
                $statements[] = $statement;
 
-               foreach ( $this->snakProvider() as $snak ) {
+               foreach ( $snaks as $snak ) {
                        $statement = clone $statement;
                        $snaks = new \Wikibase\SnakList( array( $snak ) );
                        $statement->getReferences()->addReference( new 
\Wikibase\Reference( $snaks ) );
@@ -105,7 +135,7 @@
                        // Addition request
                        $this->makeRequest( $claim, $item->getId(), 1 );
 
-                       $claim = new \Wikibase\Statement( new 
\Wikibase\PropertyNoValueSnak( 1234 ) );
+                       $claim = new \Wikibase\Statement( new 
\Wikibase\PropertyNoValueSnak( 9001 ) );
                        $claim->setGuid( $guid );
 
                        // Update request
diff --git a/repo/tests/phpunit/includes/api/SetQualifierTest.php 
b/repo/tests/phpunit/includes/api/SetQualifierTest.php
index 78a0e38..630316e 100644
--- a/repo/tests/phpunit/includes/api/SetQualifierTest.php
+++ b/repo/tests/phpunit/includes/api/SetQualifierTest.php
@@ -2,6 +2,8 @@
 
 namespace Wikibase\Test\Api;
 use Wikibase\Item;
+use Wikibase\Property;
+use Wikibase\PropertyContent;
 use Wikibase\Snak;
 use Wikibase\Statement;
 use Wikibase\Claim;
@@ -42,6 +44,7 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
  * @author Katie Filbert < [email protected] >
+ * @author Daniel Kinzler
  */
 class SetQualifierTest extends ModifyItemBase {
 
@@ -49,11 +52,36 @@
         * @return Snak[]
         */
        protected function snakProvider() {
+               static $hasProperties = false;
+
+               $prop42 = new EntityId( Property::ENTITY_TYPE, 42 );
+               $prop9001 = new EntityId( Property::ENTITY_TYPE, 9001 );
+               $prop7201010 = new EntityId( Property::ENTITY_TYPE, 7201010 );
+
+               if ( !$hasProperties ) {
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( $prop42 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( $prop9001 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( $prop7201010 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $hasProperties = true;
+               }
+
                $snaks = array();
 
-               $snaks[] = new \Wikibase\PropertyNoValueSnak( 42 );
-               $snaks[] = new \Wikibase\PropertySomeValueSnak( 9001 );
-               $snaks[] = new \Wikibase\PropertyValueSnak( 7201010, new 
\DataValues\StringValue( 'o_O' ) );
+               $snaks[] = new \Wikibase\PropertyNoValueSnak( $prop42 );
+               $snaks[] = new \Wikibase\PropertySomeValueSnak( $prop9001 );
+               $snaks[] = new \Wikibase\PropertyValueSnak( $prop7201010, new 
\DataValues\StringValue( 'o_O' ) );
 
                return $snaks;
        }
@@ -116,8 +144,8 @@
                }
 
                return array(
-                       new \Wikibase\PropertySomeValueSnak( 1 ),
-                       new \Wikibase\PropertyNoValueSnak( 1 ),
+                       new \Wikibase\PropertySomeValueSnak( 9001 ),
+                       new \Wikibase\PropertyNoValueSnak( 9001 ),
                        new \Wikibase\PropertyValueSnak( $property1->getId(), 
new \DataValues\StringValue( 'new qualifier' ) ),
                        new \Wikibase\PropertyValueSnak( $property2->getId(), 
new EntityId( Item::ENTITY_TYPE, 802 ) ),
                );
diff --git a/repo/tests/phpunit/includes/api/SetReferenceTest.php 
b/repo/tests/phpunit/includes/api/SetReferenceTest.php
index 1bf812a..c627bb2 100644
--- a/repo/tests/phpunit/includes/api/SetReferenceTest.php
+++ b/repo/tests/phpunit/includes/api/SetReferenceTest.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace Wikibase\Test\Api;
+use Wikibase\PropertyContent;
 use Wikibase\Reference;
 
 /**
@@ -38,8 +39,23 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
  * @author Katie Filbert < [email protected] >
+ * @author Daniel Kinzler
  */
 class SetReferenceTest extends \ApiTestCase {
+
+       public function setUp() {
+               static $hasProperties = false;
+               if ( !$hasProperties ) {
+                       $prop = PropertyContent::newEmpty();
+                       $prop->getEntity()->setId( 42 );
+                       $prop->getEntity()->setDataTypeId( 'string' );
+                       $prop->save( 'testing' );
+
+                       $hasProperties = true;
+               }
+
+               parent::setUp();
+       }
 
        // TODO: clean this up so more of the input space can easily be tested
        // semi-blocked by cleanup of GUID handling in claims
@@ -133,7 +149,7 @@
        /**
         * @dataProvider invalidClaimProvider
         */
-       public function testInvalidClaimGuid( $claimGuid, $snakHash, $refHash ) 
{
+       public function testInvalidClaimGuid( $claimGuid, $snakHash, $refHash, 
$expectedError ) {
                $caughtException = false;
 
                $params = array(
@@ -146,24 +162,22 @@
 
                try {
                        $this->doApiRequest( $params );
+                       $this->fail( "Exception with code $expectedError 
expected" );
                } catch ( \UsageException $e ) {
-                       $this->assertEquals( $e->getCodeString(), 
'setreference-invalid-guid', 'Invalid claim guid raised correct error' );
-                       $caughtException = true;
+                       $this->assertEquals( $e->getCodeString(), 
$expectedError, 'Error code' );
                }
-
-               $this->assertTrue( $caughtException, 'Exception was caught' );
        }
 
        public function invalidClaimProvider() {
-               $snak = new \Wikibase\PropertyValueSnak( 722, new 
\DataValues\StringValue( 'abc') );
+               $snak = new \Wikibase\PropertyValueSnak( 42, new 
\DataValues\StringValue( 'abc') );
                $snakHash = $snak->getHash();
 
-               $reference = new \Wikibase\PropertyValueSnak( 723, new 
\DataValues\StringValue( 'def' ) );
+               $reference = new \Wikibase\PropertyValueSnak( 42, new 
\DataValues\StringValue( 'def' ) );
                $refHash = $reference->getHash();
 
                return array(
-                       array( 'xyz', $snakHash, $refHash ),
-                       array( 'x$y$z', $snakHash, $refHash )
+                       array( 'xyz', $snakHash, $refHash, 
'setreference-invalid-guid' ),
+                       array( 'x$y$z', $snakHash, $refHash, 
'setreference-invalid-guid' )
                );
        }
 
diff --git a/repo/tests/phpunit/includes/api/SnakValidationHelperTest.php 
b/repo/tests/phpunit/includes/api/SnakValidationHelperTest.php
new file mode 100644
index 0000000..2052eb1
--- /dev/null
+++ b/repo/tests/phpunit/includes/api/SnakValidationHelperTest.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace Wikibase\Test;
+
+use DataTypes\DataType;
+use DataTypes\DataTypeFactory;
+use DataValues\DataValue;
+use DataValues\StringValue;
+use ValueValidators\StringValidator;
+use Wikibase\Claim;
+use Wikibase\EntityId;
+use Wikibase\Lib\InMemoryDataTypeLookup;
+use Wikibase\Lib\PropertyDataTypeLookup;
+use Wikibase\Property;
+use Wikibase\PropertyNoValueSnak;
+use Wikibase\PropertySomeValueSnak;
+use Wikibase\PropertyValueSnak;
+use Wikibase\Reference;
+use Wikibase\ReferenceList;
+use Wikibase\References;
+use Wikibase\Snak;
+use Wikibase\SnakList;
+use Wikibase\Statement;
+use Wikibase\Validators\DataValueValidator;
+use Wikibase\Validators\SnakValidator;
+
+/**
+ * @covers Wikibase\Api\SnakValidationHelper
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 0.4
+ *
+ * @ingroup WikibaseRepoTest
+ * @ingroup Test
+ *
+ * @group Wikibase
+ * @group WikibaseValidators
+ * @group WikibaseApi
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class SnakValidationHelperTest extends \MediaWikiTestCase {
+
+       /**
+        * @var DataTypeFactory
+        */
+       protected $dataTypeFactory;
+
+       /**
+        * @var PropertyDataTypeLookup
+        */
+       protected $propertyDataTypeLookup;
+
+       public function setUp() {
+               parent::setUp();
+
+               $numericValidator = new TestValidator( '/^[0-9]+$/' );
+               $alphabeticValidator = new TestValidator( '/^[a-zA-Z]+$/' );
+               $lengthValidator = new TestValidator( '/^.{1,10}$/' );
+
+               $this->dataTypeFactory = new DataTypeFactory();
+               $this->dataTypeFactory->registerDataType( new DataType( 
'numeric', 'string', array(), array(), array( $numericValidator, 
$lengthValidator ) ) );
+               $this->dataTypeFactory->registerDataType( new DataType( 
'alphabetic', 'string', array(), array(), array( $alphabeticValidator, 
$lengthValidator ) ) );
+
+               $p1 = new EntityId( Property::ENTITY_TYPE, 1 );
+               $p2 = new EntityId( Property::ENTITY_TYPE, 2 );
+
+               $this->propertyDataTypeLookup = new InMemoryDataTypeLookup();
+               $this->propertyDataTypeLookup->setDataTypeForProperty( $p1, 
'numeric' );
+               $this->propertyDataTypeLookup->setDataTypeForProperty( $p2, 
'alphabetic' );
+       }
+
+
+       public static function provideValidateClaimSnaks() {
+               $p1 = new EntityId( Property::ENTITY_TYPE, 1 ); // numeric
+               $p2 = new EntityId( Property::ENTITY_TYPE, 2 ); // alphabetic
+
+               $cases = array();
+
+               $claim = new Statement( new PropertyNoValueSnak( $p1 ) );
+               $cases[] = array( $claim, 'empty claim', true );
+
+               $claim = new Statement(
+                       new PropertyValueSnak( $p1, new StringValue( '12' ) )
+               );
+               $claim->setQualifiers( new SnakList( array(
+                       new PropertyValueSnak( $p2, new StringValue( 'abc' ) )
+               ) ) );
+               $claim->setReferences( new ReferenceList( array (
+                       new Reference( new SnakList( array(
+                               new PropertyValueSnak( $p2, new StringValue( 
'xyz' ) )
+                       ) ) )
+               ) ) );
+               $cases[] = array( $claim, 'conforming claim', true );
+
+               $brokenClaim = clone $claim;
+               $brokenClaim->setMainSnak(
+                       new PropertyValueSnak( $p1, new StringValue( 'kittens' 
) )
+               );
+               $cases[] = array( $brokenClaim, 'error in main snak', false );
+
+               $brokenClaim = clone $claim;
+               $brokenClaim->setQualifiers( new SnakList( array(
+                       new PropertyValueSnak( $p2, new StringValue( '333' ) )
+               ) ) );
+               $cases[] = array( $brokenClaim, 'error in qualifier', false );
+
+               $brokenClaim = clone $claim;
+               $brokenClaim->setReferences( new ReferenceList( array (
+                       new Reference( new SnakList( array(
+                               new PropertyValueSnak( $p1, new StringValue( 
'xyz' ) )
+                       ) ) )
+               ) ) );
+               $cases[] = array( $brokenClaim, 'error in reference', false );
+
+               return $cases;
+       }
+
+       /**
+        * @dataProvider provideValidateClaimSnaks
+        */
+       public function testValidateClaimSnaks( Claim $claim, $description, 
$expectedValid = true ) {
+               $validator = new SnakValidator( $this->propertyDataTypeLookup, 
$this->dataTypeFactory );
+
+               $result = $validator->validateClaimSnaks( $claim );
+
+               $this->assertEquals( $expectedValid, $result->isValid(), 
$description );
+       }
+
+       public static function provideValidateSnak() {
+               //TODO: share code with SnakValidatorTest
+
+               $p1 = new EntityId( Property::ENTITY_TYPE, 1 ); // numeric
+               $p2 = new EntityId( Property::ENTITY_TYPE, 2 ); // alphabetic
+
+               $cases = array();
+
+               $snak = new PropertyNoValueSnak( $p1 );
+               $cases[] = array( $snak, 'PropertyNoValueSnak', true );
+
+               $snak = new PropertySomeValueSnak( $p2 );
+               $cases[] = array( $snak, 'PropertySomeValueSnak', true );
+
+               $snak = new PropertyValueSnak( $p1, new StringValue( '123' ) );
+               $cases[] = array( $snak, 'valid numeric value', true );
+
+               $snak = new PropertyValueSnak( $p2, new StringValue( '123' ) );
+               $cases[] = array( $snak, 'invalid alphabetic value', false );
+
+               $snak = new PropertyValueSnak( $p2, new StringValue( 'abc' ) );
+               $cases[] = array( $snak, 'valid alphabetic value', true );
+
+               $snak = new PropertyValueSnak( $p1, new StringValue( 'abc' ) );
+               $cases[] = array( $snak, 'invalid numeric value', false );
+
+               return $cases;
+       }
+
+       /**
+        * @dataProvider provideValidateSnak
+        */
+       public function testValidateSnak( Snak $snak, $description, 
$expectedValid = true ) {
+               $validator = new SnakValidator( $this->propertyDataTypeLookup, 
$this->dataTypeFactory );
+
+               $result = $validator->validate( $snak );
+
+               $this->assertEquals( $expectedValid, $result->isValid(), 
$description );
+       }
+
+}
+
diff --git a/repo/tests/phpunit/includes/store/sql/EntityPerPageBuilderTest.php 
b/repo/tests/phpunit/includes/store/sql/EntityPerPageBuilderTest.php
index e900ac7..b9119d8 100644
--- a/repo/tests/phpunit/includes/store/sql/EntityPerPageBuilderTest.php
+++ b/repo/tests/phpunit/includes/store/sql/EntityPerPageBuilderTest.php
@@ -53,9 +53,14 @@
                parent::setUp();
 
                $settings = $this->getTestSettings();
-               $this->wikibaseRepo = new WikibaseRepo( $settings );
+               $store = StoreFactory::getStore( 'sqlstore' );
 
-               $this->entityPerPageTable = StoreFactory::getStore( 'sqlstore' 
)->newEntityPerPage();
+               $this->wikibaseRepo = new WikibaseRepo(
+                       $settings,
+                       $store
+               );
+
+               $this->entityPerPageTable = $store->newEntityPerPage();
 
                $this->clearTables();
                $this->addItems();

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I67b9ae480c4a667043486b45027796c0c69c5ffa
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>

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

Reply via email to