jenkins-bot has submitted this change and it was merged.

Change subject: (bug 54333) Validate time precision.
......................................................................


(bug 54333) Validate time precision.

This validates the precision parameter for time values.

Change-Id: I78d0dd46f478dffc9a879b8c645c7468b00949fd
---
M lib/WikibaseLib.classes.php
M lib/WikibaseLib.i18n.php
A lib/includes/Validators/NumberRangeValidator.php
M lib/includes/WikibaseDataTypeBuilders.php
A lib/tests/phpunit/Validators/NumberRangeValidatorTest.php
M lib/tests/phpunit/WikibaseDataTypeBuildersTest.php
6 files changed, 210 insertions(+), 24 deletions(-)

Approvals:
  Aude: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/lib/WikibaseLib.classes.php b/lib/WikibaseLib.classes.php
index ddf631a..fac3726 100644
--- a/lib/WikibaseLib.classes.php
+++ b/lib/WikibaseLib.classes.php
@@ -192,6 +192,7 @@
                'Wikibase\Validators\NumberValidator' => 
'includes/Validators/NumberValidator.php',
                'Wikibase\Validators\RegexValidator' => 
'includes/Validators/RegexValidator.php',
                'Wikibase\Validators\StringLengthValidator' => 
'includes/Validators/StringLengthValidator.php',
+               'Wikibase\Validators\NumberRangeValidator' => 
'includes/Validators/NumberRangeValidator.php',
                'Wikibase\Validators\TypeValidator' => 
'includes/Validators/TypeValidator.php',
                'Wikibase\Validators\ValidatorErrorLocalizer' => 
'includes/Validators/ValidatorErrorLocalizer.php',
                'Wikibase\Validators\UrlValidator' => 
'includes/Validators/UrlValidator.php',
diff --git a/lib/WikibaseLib.i18n.php b/lib/WikibaseLib.i18n.php
index 0c16d7f..ecc36e3 100644
--- a/lib/WikibaseLib.i18n.php
+++ b/lib/WikibaseLib.i18n.php
@@ -57,6 +57,8 @@
        'wikibase-validator-bad-type' => '$2 instead of $1',
        'wikibase-validator-too-long' => 'Must be no more than {{PLURAL:$1|one 
character|$1 characters}} long',
        'wikibase-validator-too-short' => 'Must be at least {{PLURAL:$1|one 
character|$1 characters}} long',
+       'wikibase-validator-too-high' => 'Out of range, must be no higher than 
$1',
+       'wikibase-validator-too-low' => 'Out of range, must be no lower than 
$1',
        'wikibase-validator-malformed-value' => 'Malformed input: $1',
        'wikibase-validator-bad-entity-id' => 'Malformed ID: $1',
        'wikibase-validator-bad-entity-type' => 'Unexpected entity type $1',
@@ -164,13 +166,21 @@
 * $2 - the actual type
 {{Related|Wikibase-validator}}',
        'wikibase-validator-too-long' => 'Input validation error shown when the 
input is too long. Parameters:
-* $1 - the minimum length
+* $1 - the maximum length
 * $2 - (Unused) the actual length
 {{Related|Wikibase-validator}}',
        'wikibase-validator-too-short' => 'Input validation error shown when 
the input is too short. Parameters:
 * $1 - the minimum length
 * $2 - (Unused) the actual length
 {{Related|Wikibase-validator}}',
+       'wikibase-validator-too-high' => 'Input validation error shown when the 
input is too high. Parameters:
+* $1 - the maximum value
+* $2 - (Unused) the actual length
+{{Related|Wikibase-validator}}',
+       'wikibase-validator-too-low' => 'Input validation error shown when the 
input is too low. Parameters:
+* $1 - the minimum value
+* $2 - (Unused) the actual length
+{{Related|Wikibase-validator}}',
        'wikibase-validator-malformed-value' => "Input validation error shown 
when the user's input was malformed in some way.
 
 Parameters:
diff --git a/lib/includes/Validators/NumberRangeValidator.php 
b/lib/includes/Validators/NumberRangeValidator.php
new file mode 100644
index 0000000..4ece070
--- /dev/null
+++ b/lib/includes/Validators/NumberRangeValidator.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Wikibase\Validators;
+
+use ValueValidators\Error;
+use ValueValidators\Result;
+use ValueValidators\ValueValidator;
+
+/**
+ * NumberRangeValidator checks that a numerical value is in a given range.
+ *
+ * @license GPL 2+
+ * @author Daniel Kinzler
+ */
+class NumberRangeValidator implements ValueValidator {
+
+       /**
+        * @var int
+        */
+       protected $min;
+
+       /**
+        * @var int
+        */
+       protected $max;
+
+       /**
+        * @var callable
+        */
+       protected $measure;
+
+       /**
+        * @param int|float  $min
+        * @param int|float  $max
+        */
+       public function __construct( $min, $max ) {
+               $this->min = $min;
+               $this->max = $max;
+       }
+
+       /**
+        * @see ValueValidator::validate()
+        *
+        * @param string $value The value to validate
+        *
+        * @return \ValueValidators\Result
+        * @throws \InvalidArgumentException
+        */
+       public function validate( $value ) {
+               if ( $value < $this->min ) {
+                       // XXX: having to provide an array is quite inconvenient
+                       return Result::newError( array(
+                               Error::newError( 'Value out of range, the 
minimum value is ' . $this->min, null, 'too-low', array( $this->min, $value ) )
+                       ) );
+               }
+
+               if ( $value > $this->max ) {
+                       return Result::newError( array(
+                               Error::newError( 'Value out of range, the 
maximum value is ' . $this->max, null, 'too-high', array( $this->max, $value ) )
+                       ) );
+               }
+
+               return Result::newSuccess();
+       }
+
+       /**
+        * @see ValueValidator::setOptions()
+        *
+        * @param array $options
+        */
+       public function setOptions( array $options ) {
+               // Do nothing. This method shouldn't even be in the interface.
+       }
+}
\ No newline at end of file
diff --git a/lib/includes/WikibaseDataTypeBuilders.php 
b/lib/includes/WikibaseDataTypeBuilders.php
index 22dc925..c0aa899 100644
--- a/lib/includes/WikibaseDataTypeBuilders.php
+++ b/lib/includes/WikibaseDataTypeBuilders.php
@@ -3,6 +3,7 @@
 namespace Wikibase\Lib;
 
 use DataTypes\DataType;
+use DataValues\TimeValue;
 use Parser;
 use Wikibase\EntityLookup;
 use Wikibase\Item;
@@ -10,6 +11,7 @@
 use Wikibase\Validators\DataFieldValidator;
 use Wikibase\Validators\DataValueValidator;
 use Wikibase\Validators\EntityExistsValidator;
+use Wikibase\Validators\NumberRangeValidator;
 use Wikibase\Validators\NumberValidator;
 use Wikibase\Validators\RegexValidator;
 use Wikibase\Validators\StringLengthValidator;
@@ -150,13 +152,28 @@
                $timeStringValidators = array();
                $timeStringValidators[] = new TypeValidator( 'string' );
 
-               $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 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', // Note: 
validate the 'calendarmodel' field
+               $validators[] = new DataFieldValidator( 'time', // Note: 
validate the 'time' field
                        new CompositeValidator( $timeStringValidators, true ) 
//Note: each validator is fatal
                );
 
+               $precisionValidators = array();
+               $precisionValidators[] = new TypeValidator( 'integer' );
+               $precisionValidators[] = new NumberRangeValidator( 
TimeValue::PRECISION_Ga, $maxPrecision );
+
+               $validators[] = new DataFieldValidator( 'precision', // Note: 
validate the 'precision' field
+                       new CompositeValidator( $precisionValidators, true ) 
//Note: each validator is fatal
+               );
+
                // top validator
                $topValidator = new DataValueValidator( //Note: validate the 
DataValue's native value.
                        new CompositeValidator( $validators, true ) //Note: 
each validator is fatal
diff --git a/lib/tests/phpunit/Validators/NumberRangeValidatorTest.php 
b/lib/tests/phpunit/Validators/NumberRangeValidatorTest.php
new file mode 100644
index 0000000..1b466a1
--- /dev/null
+++ b/lib/tests/phpunit/Validators/NumberRangeValidatorTest.php
@@ -0,0 +1,79 @@
+<?php
+ /**
+ *
+ * Copyright © 14.06.13 by the authors listed below.
+ *
+ * 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
+ *
+ * @license GPL 2+
+ * @file
+ *
+ * @ingroup WikibaseLib
+ * @ingroup Test
+ *
+ * @group WikibaseLib
+ * @group Wikibase
+ * @group WikibaseValidators
+ *
+ * @author Daniel Kinzler
+ */
+
+
+namespace Wikibase\Test\Validators;
+
+
+use Wikibase\Validators\NumberRangeValidator;
+use Wikibase\Validators\ValidatorErrorLocalizer;
+
+/**
+ * Class StringLengthValidatorTest
+ * @covers Wikibase\Validators\StringLengthValidator
+ * @package Wikibase\Test\Validators
+ */
+class NumberRangeValidatorTest extends \PHPUnit_Framework_TestCase {
+
+       public static function provideValidate() {
+               return array(
+                       array( 1, 10, 3, true, "normal fit" ),
+                       array( 0, 10, 0, true, "0 ok" ),
+                       array( 1, 10, 0, false, "0 not allowed" ),
+                       array( -2, 1, -2, true, "negative match" ),
+                       array( 1, 2, 3, false, "too high" ),
+                       array( -1, 0, -3, false, "too low" ),
+               );
+       }
+
+       /**
+        * @dataProvider provideValidate()
+        */
+       public function testValidate( $minLength, $maxLength, $value, 
$expected, $message ) {
+               $validator = new NumberRangeValidator( $minLength, $maxLength );
+               $result = $validator->validate( $value );
+
+               $this->assertEquals( $expected, $result->isValid(), $message );
+
+               if ( !$expected ) {
+                       $errors = $result->getErrors();
+                       $this->assertCount( 1, $errors, $message );
+                       $this->assertTrue( in_array( $errors[0]->getCode(), 
array( 'too-low', 'too-high' ) ), $message . "\n" . $errors[0]->getCode() );
+
+                       $localizer = new ValidatorErrorLocalizer( );
+                       $msg = $localizer->getErrorMessage( $errors[0] );
+                       $this->assertTrue( $msg->exists(), $msg );
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php 
b/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php
index 4fe2084..89a97ae 100644
--- a/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php
+++ b/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php
@@ -86,11 +86,15 @@
                        array( 'time', new NumberValue( 7 ), false, 'TimeValue 
expected' ),
 
                        //time['calendar-model']
-                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T11:22:33Z', 0, 0, 0, 0, '' ), false, 'calendar: empty 
string should be invalid' ),
-                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T11:22:33Z', 0, 0, 0, 0, 'http://' . str_repeat('x', 
256) ), false, 'calendar: too long' ),
-                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T11:22:33Z', 0, 0, 0, 0, 'http://acme.com/calendar' ), 
true, 'calendar: URL' ),
-                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T11:22:33Z', 0, 0, 0, 0, ' http://acme.com/calendar ' 
), false, 'calendar: untrimmed' ),
-                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T11:22:33Z', 0, 0, 0, 0, ' javascript:alert(1)' ), 
false, 'calendar: bad URL' ),
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T00:00:00Z', 0, 0, 0, TimeValue::PRECISION_DAY, '' ), 
false, 'calendar: empty string should be invalid' ),
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T00:00:00Z', 0, 0, 0, TimeValue::PRECISION_DAY, 
'http://' . str_repeat('x', 256) ), false, 'calendar: too long' ),
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T00:00:00Z', 0, 0, 0, TimeValue::PRECISION_DAY, 
'http://acme.com/calendar' ), true, 'calendar: URL' ),
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T00:00:00Z', 0, 0, 0, TimeValue::PRECISION_DAY, ' 
http://acme.com/calendar ' ), false, 'calendar: untrimmed' ),
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T00:00:00Z', 0, 0, 0, TimeValue::PRECISION_DAY, ' 
javascript:alert(1)' ), false, 'calendar: bad URL' ),
+
+                       //precision to the second (currently not allowed)
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T11:22:33Z', 0, 0, 0, TimeValue::PRECISION_DAY, 
'http://acme.com/calendar' ), false, 'time given to the second' ),
+                       array( 'time', new TimeValue( 
'+0000000000002013-06-06T00:00:00Z', 0, 0, 0, TimeValue::PRECISION_SECOND, 
'http://acme.com/calendar' ), false, 'precision: second' ),
 
                        //time['time']
                        //NOTE: The below will fail with a 
IllegalValueExcpetion once the TimeValue constructor enforces the time format.
@@ -133,26 +137,27 @@
                        array( 'globe-coordinate', new GlobeCoordinateValue( 
$latLonValue, 1, ' javascript:alert(1) ' ), false, 'globe: bad URL scheme' ),
                        //TODO: globe must be an item reference
                        //TODO: globe must be from a list of configured values
+
+                       // url
+                       array( 'url', 'Foo', false, 'StringValue expected, 
string supplied' ),
+                       array( 'url', new NumberValue( 7 ), false, 'StringValue 
expected' ),
+
+                       array( 'url', new StringValue( 'http://acme.com' ), 
true, 'Simple HTTP URL' ),
+                       array( 'url', new StringValue( 'https://acme.com/' ), 
true, 'Simple HTTPS URL' ),
+                       array( 'url', new StringValue( 
'http://acme.com/foo/bar?some=stuff#fragment' ), true, 'Complex HTTP URL' ),
+
+                       // evil url
+                       array( 'url', new StringValue( '//bla' ), false, 
'Protocol-relative' ),
+                       array( 'url', new StringValue( '/bla/bla' ), false, 
'relative path' ),
+                       array( 'url', new StringValue( 'just stuff' ), false, 
'just words' ),
+                       array( 'url', new StringValue( 
'javascript:alert("evil")' ), false, 'JavaScript URL' ),
+                       array( 'url', new StringValue( 'http://' ), false, 'bad 
http URL' ),
+                       array( 'url', new StringValue( 'http://' . 
str_repeat('x', 505) ), false, 'URL too long' ),
                );
 
                if ( defined( 'WB_EXPERIMENTAL_FEATURES' ) && 
WB_EXPERIMENTAL_FEATURES ) {
                        $cases = array_merge( $cases, array(
-
-                               // url
-                               array( 'url', 'Foo', false, 'StringValue 
expected, string supplied' ),
-                               array( 'url', new NumberValue( 7 ), false, 
'StringValue expected' ),
-
-                               array( 'url', new StringValue( 
'http://acme.com' ), true, 'Simple HTTP URL' ),
-                               array( 'url', new StringValue( 
'https://acme.com/' ), true, 'Simple HTTPS URL' ),
-                               array( 'url', new StringValue( 
'http://acme.com/foo/bar?some=stuff#fragment' ), true, 'Complex HTTP URL' ),
-
-                               // evil url
-                               array( 'url', new StringValue( '//bla' ), 
false, 'Protocol-relative' ),
-                               array( 'url', new StringValue( '/bla/bla' ), 
false, 'relative path' ),
-                               array( 'url', new StringValue( 'just stuff' ), 
false, 'just words' ),
-                               array( 'url', new StringValue( 
'javascript:alert("evil")' ), false, 'JavaScript URL' ),
-                               array( 'url', new StringValue( 'http://' ), 
false, 'bad http URL' ),
-                               array( 'url', new StringValue( 'http://' . 
str_repeat('x', 505) ), false, 'URL too long' ),
+                               // ....
                        ) );
                }
 

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I78d0dd46f478dffc9a879b8c645c7468b00949fd
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Lydia Pintscher <lydia.pintsc...@wikimedia.de>
Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to