Addshore has uploaded a new change for review.

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

Change subject: Add optional validation to ParseValue api
......................................................................

Add optional validation to ParseValue api

Bug: T104330
Change-Id: Ia6bcd1e85f6867663457122d19310ca4d7e9af81
---
M lib/includes/DataValueFactory.php
M repo/Wikibase.php
M repo/i18n/en.json
M repo/i18n/qqq.json
M repo/includes/api/ParseValue.php
M repo/tests/phpunit/includes/api/ParseValueTest.php
6 files changed, 155 insertions(+), 24 deletions(-)


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

diff --git a/lib/includes/DataValueFactory.php 
b/lib/includes/DataValueFactory.php
index 3f5378c..d8fafe9 100644
--- a/lib/includes/DataValueFactory.php
+++ b/lib/includes/DataValueFactory.php
@@ -23,6 +23,7 @@
         */
        protected $values = array(
                'boolean' => 'DataValues\BooleanValue',
+               'decimal' => 'DataValues\DecimalValue',
                'number' => 'DataValues\NumberValue',
                'string' => 'DataValues\StringValue',
                'unknown' => 'DataValues\UnknownValue',
diff --git a/repo/Wikibase.php b/repo/Wikibase.php
index c361c12..a97e90b 100644
--- a/repo/Wikibase.php
+++ b/repo/Wikibase.php
@@ -52,6 +52,7 @@
  * @deprecated since 0.5 This is a global registry that provides no control 
over object lifecycle
  */
 $GLOBALS['wgValueParsers'] = array();
+$GLOBALS['wgValueValidators'] = array();
 
 // Include the WikibaseLib extension if that hasn't been done yet, since it's 
required for Wikibase to work.
 if ( !defined( 'WBL_VERSION' ) ) {
diff --git a/repo/i18n/en.json b/repo/i18n/en.json
index 6e8d65d..40aedf3 100644
--- a/repo/i18n/en.json
+++ b/repo/i18n/en.json
@@ -548,8 +548,9 @@
        "apihelp-wbmergeitems-example-2": "Merges data from Q555 into Q3",
        "apihelp-wbmergeitems-example-3": "Merges data from Q66 into Q99 
ignoring any conflicting labels",
        "apihelp-wbmergeitems-example-4": "Merges data from Q66 into Q99 
ignoring any conflicting labels and descriptions",
-       "apihelp-wbparsevalue-description": "Parses values using a 
ValueParser.",
+       "apihelp-wbparsevalue-description": "Parses values using a ValueParser 
and optional Validator.",
        "apihelp-wbparsevalue-param-parser": "ID of the ValueParser to use",
+       "apihelp-wbparsevalue-param-validator": "ID of the ValueValidator to 
use",
        "apihelp-wbparsevalue-param-values": "The values to parse",
        "apihelp-wbparsevalue-param-options": "The options the parser should 
use. Provided as a JSON object.",
        "apihelp-wbparsevalue-example-1": "No change to the format of the 
string.",
diff --git a/repo/i18n/qqq.json b/repo/i18n/qqq.json
index be2aa04..3cfa9c0 100644
--- a/repo/i18n/qqq.json
+++ b/repo/i18n/qqq.json
@@ -578,6 +578,7 @@
        "apihelp-wbmergeitems-example-4": 
"{{doc-apihelp-example|wbmergeitems}}",
        "apihelp-wbparsevalue-description": 
"{{doc-apihelp-description|wbparsevalue}}",
        "apihelp-wbparsevalue-param-parser": 
"{{doc-apihelp-param|wbparsevalue|parser}}",
+       "apihelp-wbparsevalue-param-validator": 
"{{doc-apihelp-param|wbparsevalue|validator}}",
        "apihelp-wbparsevalue-param-values": 
"{{doc-apihelp-param|wbparsevalue|values}}",
        "apihelp-wbparsevalue-param-options": 
"{{doc-apihelp-param|wbparsevalue|options}}",
        "apihelp-wbparsevalue-example-1": 
"{{doc-apihelp-example|wbparsevalue}}",
diff --git a/repo/includes/api/ParseValue.php b/repo/includes/api/ParseValue.php
index 2cdfa24..5ceea92 100644
--- a/repo/includes/api/ParseValue.php
+++ b/repo/includes/api/ParseValue.php
@@ -10,7 +10,10 @@
 use ValueParsers\ParseException;
 use ValueParsers\ParserOptions;
 use ValueParsers\ValueParser;
+use ValueValidators\Result;
+use ValueValidators\ValueValidator;
 use Wikibase\Repo\ValueParserFactory;
+use Wikibase\Repo\ValueValidatorFactory;
 
 /**
  * API module for using value parsers.
@@ -20,23 +23,40 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
  * @author Daniel Kinzler
+ * @author Adam Shorland
  */
 class ParseValue extends ApiWikibase {
 
        /**
         * @var null|ValueParserFactory
         */
-       private $factory = null;
+       private $parserFactory = null;
+
+       /**
+        * @var null|ValueValidatorFactory
+        */
+       private $validatorFactory = null;
 
        /**
         * @return ValueParserFactory
         */
-       private function getFactory() {
-               if ( $this->factory === null ) {
-                       $this->factory = new ValueParserFactory( 
$GLOBALS['wgValueParsers'] );
+       private function getParserFactory() {
+               if ( $this->parserFactory === null ) {
+                       $this->parserFactory = new ValueParserFactory( 
$GLOBALS['wgValueParsers'] );
                }
 
-               return $this->factory;
+               return $this->parserFactory;
+       }
+
+       /**
+        * @return ValueValidatorFactory
+        */
+       private function getValidatorFactory() {
+               if ( $this->validatorFactory === null ) {
+                       $this->validatorFactory = new ValueValidatorFactory( 
$GLOBALS['wgValueValidators'] );
+               }
+
+               return $this->validatorFactory;
        }
 
        /**
@@ -46,6 +66,7 @@
         */
        public function execute() {
                $parser = $this->getParser();
+               $validator = $this->getValidator();
 
                $results = array();
 
@@ -55,7 +76,28 @@
                        $results[] = $this->parseStringValue( $parser, $value );
                }
 
-               $this->outputResults( $results );
+               if ( $validator !== null ) {
+                       foreach ( $results as &$result ) {
+                               $this->validateParsedValue( $validator, $result 
);
+                       }
+               }
+
+               $this->outputResults( $this->formatResultsForOutput( $results ) 
);
+       }
+
+       private function formatResultsForOutput( $results ) {
+               foreach ( $results as &$result ) {
+                       if ( array_key_exists( 'parsedvalue', $result ) ) {
+                               if ( $result['parsedvalue'] instanceof 
DataValue ) {
+                                       $result['value'] = 
$result['parsedvalue']->getArrayValue();
+                                       $result['type'] = 
$result['parsedvalue']->getType();
+                               } else {
+                                       $result['value'] = 
$result['parsedvalue'];
+                               }
+                               unset( $result['parsedvalue'] );
+                       }
+               }
+               return $results;
        }
 
        /**
@@ -65,15 +107,30 @@
        private function getParser() {
                $params = $this->extractRequestParams();
 
-               $options = $this->getOptionsObject( $params['options'] );
+               $options = $this->getParserOptionsObject( $params['options'] );
 
                try {
-                       $parser = $this->getFactory()->newParser( 
$params['parser'], $options );
+                       $parser = $this->getParserFactory()->newParser( 
$params['parser'], $options );
                } catch ( OutOfBoundsException $ex ) {
                        throw new LogicException( 'Could not obtain a 
ValueParser instance' );
                }
 
                return $parser;
+       }
+
+       /**
+        * @return ValueValidator|null
+        */
+       private function getValidator() {
+               $params = $this->extractRequestParams();
+
+               try {
+                       $validator = 
$this->getValidatorFactory()->newValidator( $params['validator'] );
+               } catch ( OutOfBoundsException $ex ) {
+                       return null;
+               }
+
+               return $validator;
        }
 
        /**
@@ -88,22 +145,42 @@
                );
 
                try {
-                       $parseResult = $parser->parse( $value );
+                       $result['parsedvalue'] = $parser->parse( $value );
                }
                catch ( ParseException $parseError ) {
                        $this->addParseErrorToResult( $result, $parseError );
-                       return $result;
-               }
-
-               if ( $parseResult instanceof DataValue ) {
-                       $result['value'] = $parseResult->getArrayValue();
-                       $result['type'] = $parseResult->getType();
-               }
-               else {
-                       $result['value'] = $parseResult;
                }
 
                return $result;
+       }
+
+       private function validateParsedValue( ValueValidator $validator, 
&$result ) {
+               if ( array_key_exists( 'parsedvalue', $result ) ) {
+
+                       if ( $result['parsedvalue'] instanceof DataValue ) {
+                               $validationResult = $validator->validate( 
$result['parsedvalue']->getValue() );
+                       } else {
+                               $validationResult = $validator->validate( 
$result['parsedvalue'] );
+                       }
+                       $this->addValidationResultToResult( $result, 
$validationResult );
+
+               } else {
+                       $result['valid'] = false;
+               }
+       }
+
+       private function addValidationResultToResult( array &$result, Result 
$validationResult ) {
+               $isValid = $validationResult->isValid();
+               if ( $isValid ) {
+                       $result['valid'] = true;
+               } else {
+                       $result['valid'] = false;
+                       $errors = $validationResult->getErrors();
+                       foreach ( $errors as $key => $error ) {
+                               $result['validation-info'][$key]['code'] = 
$error->getCode();
+                               $result['validation-info'][$key]['text'] = 
$error->getText();
+                       }
+               }
        }
 
        private function addParseErrorToResult( array &$result, ParseException 
$parseError ) {
@@ -131,7 +208,7 @@
         *
         * @return ParserOptions
         */
-       private function getOptionsObject( $optionsParam ) {
+       private function getParserOptionsObject( $optionsParam ) {
                $parserOptions = new ParserOptions();
                $parserOptions->setOption( ValueParser::OPT_LANG, 
$this->getLanguage()->getCode() );
 
@@ -156,8 +233,12 @@
        protected function getAllowedParams() {
                return array(
                        'parser' => array(
-                               ApiBase::PARAM_TYPE => 
$this->getFactory()->getParserIds(),
+                               ApiBase::PARAM_TYPE => 
$this->getParserFactory()->getParserIds(),
                                ApiBase::PARAM_REQUIRED => true,
+                       ),
+                       'validator' => array(
+                               ApiBase::PARAM_TYPE => 
$this->getValidatorFactory()->getValidatorIds(),
+                               ApiBase::PARAM_REQUIRED => false,
                        ),
                        'values' => array(
                                ApiBase::PARAM_TYPE => 'string',
@@ -176,8 +257,10 @@
         */
        protected function getExamplesMessages() {
                return array(
-                       'action=wbparsevalue&parser=null&values=foo|bar' => 
'apihelp-wbparsevalue-example-1',
-                       
'action=wbparsevalue&parser=time&values=1994-02-08&options={"precision":9}' => 
'apihelp-wbparsevalue-example-2',
+                       'action=wbparsevalue&parser=null&values=foo|bar' =>
+                               'apihelp-wbparsevalue-example-1',
+                       
'action=wbparsevalue&parser=time&values=1994-02-08&options={"precision":9}' =>
+                               'apihelp-wbparsevalue-example-2',
                );
        }
 
diff --git a/repo/tests/phpunit/includes/api/ParseValueTest.php 
b/repo/tests/phpunit/includes/api/ParseValueTest.php
index aedfc4f..bc9fa44 100644
--- a/repo/tests/phpunit/includes/api/ParseValueTest.php
+++ b/repo/tests/phpunit/includes/api/ParseValueTest.php
@@ -2,6 +2,8 @@
 
 namespace Wikibase\Test\Api;
 
+use Wikibase\Validators\StringLengthValidator;
+
 /**
  * @covers Wikibase\Api\ParseValue
  *
@@ -15,6 +17,7 @@
  *
  * @licence GNU GPL v2+
  * @author Daniel Kinzler
+ * @author Adam Shorland
  */
 class ParseValueTest extends WikibaseApiTestCase {
 
@@ -22,6 +25,17 @@
                $this->mergeMwGlobalArrayValue(
                        'wgValueParsers',
                        array( 'decimal' => 'ValueParsers\DecimalParser' )
+               );
+               $this->mergeMwGlobalArrayValue(
+                       'wgValueValidators',
+                       array(
+                               'stringLength6to8' => function() {
+                                       return new StringLengthValidator( 6, 8 
);
+                               },
+                               'stringLengthEqual1' => function() {
+                                       return new StringLengthValidator( 1, 1 
);
+                               },
+                       )
                );
                parent::setUp();
        }
@@ -110,6 +124,32 @@
                                ),
                        ),
 
+                       'decimal with string length (6-8) validation' => array(
+                               '$text' => '123.456',
+                               '$parser' => 'decimal',
+                               '$expected' => array(
+                                       '0/raw' => '123.456',
+                                       '0/type' => 'decimal',
+                                       '0/value' => '123.456',
+                                       '0/valid' => true,
+                               ),
+                               '$validator' => 'stringLength6to8',
+                       ),
+
+                       'decimal with string length (=1) validation' => array(
+                               '$text' => '123.456',
+                               '$parser' => 'decimal',
+                               '$expected' => array(
+                                       '0/raw' => '123.456',
+                                       '0/type' => 'decimal',
+                                       '0/value' => '123.456',
+                                       '0/valid' => false,
+                                       '0/validation-info/0/code' => 
'too-long',
+                                       '0/validation-info/0/text' => 'Too 
long, maximum length is 1',
+                               ),
+                               '$validator' => 'stringLengthEqual1',
+                       ),
+
                );
        }
 
@@ -132,13 +172,17 @@
        /**
         * @dataProvider provideValid
         */
-       public function testParse( $text, $parser, $expected ) {
+       public function testParse( $text, $parser, $expected, $validator = null 
) {
                $params = array(
                        'action' => 'wbparsevalue',
                        'values' => $text,
                        'parser' => $parser
                );
 
+               if ( $validator !== null ) {
+                       $params['validator'] = $validator;
+               }
+
                list( $result, , ) = $this->doApiRequest( $params );
 
                $this->assertArrayHasKey( 'results', $result );

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

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

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

Reply via email to