Daniel Kinzler has uploaded a new change for review.
https://gerrit.wikimedia.org/r/84996
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, 220 insertions(+), 24 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase
refs/changes/96/84996/1
diff --git a/lib/WikibaseLib.classes.php b/lib/WikibaseLib.classes.php
index 0979264..1f4bc9b 100644
--- a/lib/WikibaseLib.classes.php
+++ b/lib/WikibaseLib.classes.php
@@ -186,6 +186,7 @@
'Wikibase\Validators\EntityIdValidator' =>
'includes/Validators/EntityIdValidator.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 bd28c03..6c481dd 100644
--- a/lib/WikibaseLib.i18n.php
+++ b/lib/WikibaseLib.i18n.php
@@ -56,6 +56,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',
@@ -162,13 +164,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..13cfb22
--- /dev/null
+++ b/lib/includes/Validators/NumberRangeValidator.php
@@ -0,0 +1,84 @@
+<?php
+ /**
+ *
+ * Validator for checking the range of a number.
+ *
+ * @license GPL 2+
+ * @file
+ *
+ * @author Daniel Kinzler
+ */
+
+
+namespace Wikibase\Validators;
+
+
+use ValueValidators\Error;
+use ValueValidators\Result;
+use ValueValidators\ValueValidator;
+
+/**
+ * StringLengthValidator checks a string's length
+ *
+ * @package Wikibase\Validators
+ */
+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 d41f50b..3427533 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\Client\WikibaseClient;
use Wikibase\EntityLookup;
@@ -12,6 +13,7 @@
use Wikibase\Validators\DataFieldValidator;
use Wikibase\Validators\DataValueValidator;
use Wikibase\Validators\EntityExistsValidator;
+use Wikibase\Validators\NumberRangeValidator;
use Wikibase\Validators\RegexValidator;
use Wikibase\Validators\StringLengthValidator;
use Wikibase\Validators\TypeValidator;
@@ -154,13 +156,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 f846e84..6f9f0c2 100644
--- a/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php
+++ b/lib/tests/phpunit/WikibaseDataTypeBuildersTest.php
@@ -91,11 +91,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
IllevalValueExcpetion once the TimeValue constructor enforces the time format.
@@ -118,26 +122,27 @@
array( 'globe-coordinate', new GlobeCoordinateValue(
new LatLongValue( 0, 0 ), 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: newchange
Gerrit-Change-Id: I78d0dd46f478dffc9a879b8c645c7468b00949fd
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