Skip to content

Commit

Permalink
Merge pull request #4 from vanilla/feature/invalid
Browse files Browse the repository at this point in the history
Add support for allowNull and default
  • Loading branch information
tburry committed Mar 12, 2017
2 parents 305c233 + 73f83c7 commit a517841
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 113 deletions.
60 changes: 60 additions & 0 deletions src/Invalid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* @author Todd Burry <[email protected]>
* @copyright 2009-2017 Vanilla Forums Inc.
* @license MIT
*/

namespace Garden\Schema;


/**
* A singleton that represents an invalid value.
*
* The purpose of this class is to provide an alternative to **null** for invalid values when **null** could be considered
* valid. This class is not meant to be used outside of this library unless you are extended the schema somehow.
*/
class Invalid {
private static $value;

/**
* Private constructor to enforce singleton.
*/
private function __constructor() {
// no-op
}

/**
* Return the invalid value.
*
* @return Invalid Returns the invalid value.
*/
public static function value() {
if (self::$value === null) {
self::$value = new Invalid();
}
return self::$value;
}

/**
* Tests a value to see if it is invalid.
*
* @param mixed $value The value to test.
* @return bool Returns **true** of the value is invalid or **false** otherwise.
*/
public static function isInvalid($value) {
return $value === self::value();
}

/**
* Tests whether a value could be valid.
*
* Unlike {@link Invalid::inValid()} a value could still be invalid in some way even if this method returns true.
*
* @param mixed $value The value to test.
* @return bool Returns **true** of the value could be invalid or **false** otherwise.
*/
public static function isValid($value) {
return $value !== self::value();
}
}
216 changes: 135 additions & 81 deletions src/Schema.php

Large diffs are not rendered by default.

24 changes: 23 additions & 1 deletion src/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ public function isValidField($field) {
return $result;
}

/**
* Get the error count, optionally for a particular field.
*
* @param string $field The name of a field or an empty string for all errors.
* @return int Returns the error count.
*/
public function getErrorCount($field = '') {
if (empty($field)) {
return iterator_count($this->getRawErrors());
} elseif (empty($this->errors[$field])) {
return 0;
} else {
return count($this->errors[$field]);
}
}

/**
* Get the error message for an error row.
*
Expand Down Expand Up @@ -256,7 +272,13 @@ private function formatMessage($format, $context = []) {
* @return string Returns the translated string.
*/
private function formatField($value, array $args = []) {
if (is_string($value)) {
if ($value === null) {
$r = $this->translate('null');
} elseif ($value === true) {
$r = $this->translate('true');
} elseif ($value === false) {
$r = $this->translate('false');
} elseif (is_string($value)) {
$r = $this->translate($value);
} elseif (is_numeric($value)) {
$r = $value;
Expand Down
19 changes: 18 additions & 1 deletion src/ValidationField.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function addTypeError($type = '') {
* @return bool Returns true if the field has no errors, false otherwise.
*/
public function isValid() {
return $this->validation->isValidField($this->field);
return $this->getValidation()->isValidField($this->getName());
}

/**
Expand Down Expand Up @@ -166,4 +166,21 @@ public function getType() {
public function val($key, $default = null) {
return isset($this->field[$key]) ? $this->field[$key] : $default;
}

/**
* Whether or not the field has a value.
*
* @param string $key The key to look at.
* @return bool Returns **true** if the field has a key or **false** otherwise.
*/
public function hasVal($key) {
return array_key_exists($key, $this->field);
}

/**
* Get the error count for this field.
*/
public function getErrorCount() {
return $this->getValidation()->getErrorCount($this->getName());
}
}
16 changes: 8 additions & 8 deletions tests/AbstractSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ abstract class AbstractSchemaTest extends \PHPUnit_Framework_TestCase {
*/
public function provideTypes() {
$result = [
'array' => ['a', 'array'],
'object' => ['o', 'object'],
'integer' => ['i', 'integer'],
'string' => ['s', 'string'],
'number' => ['f', 'number'],
'boolean' => ['b', 'boolean'],
'timestamp' => ['ts', 'timestamp'],
'datetime' => ['dt', 'datetime']
'array' => ['a', 'array', [1, 2, 3]],
'object' => ['o', 'object', ['foo' => 'bar']],
'integer' => ['i', 'integer', 123],
'string' => ['s', 'string', 'hello'],
'number' => ['f', 'number', 12.3],
'boolean' => ['b', 'boolean', true],
'timestamp' => ['ts', 'timestamp', time()],
'datetime' => ['dt', 'datetime', new \DateTimeImmutable()]
];
return $result;
}
Expand Down
61 changes: 54 additions & 7 deletions tests/BasicSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,14 @@ public function testNotRequired($shortType) {
"col:$shortType?"
]);

$nullData = ['col' => null];
$isValid = $schema->isValid($nullData);
$this->assertTrue($isValid);
$this->assertNull($nullData['col']);

$missingData = [];
$isValid = $schema->isValid($missingData);
$this->assertTrue($isValid);
$this->assertArrayNotHasKey('col', $missingData);

$nullData = ['col' => null];
$isValid = $schema->isValid($nullData);
$this->assertFalse($isValid);
}

/**
Expand Down Expand Up @@ -381,7 +380,7 @@ protected function doValidationBehavior($validationBehavior) {
*/
public function testValidateException() {
try {
$this->doValidationBehavior(Schema::FLAG_EXTRA_PROPERTIES_EXCEPTION);
$this->doValidationBehavior(Schema::VALIDATE_EXTRA_PROPERTY_EXCEPTION);
} catch (\Exception $ex) {
$msg = $ex->getMessage();
throw $ex;
Expand All @@ -394,7 +393,7 @@ public function testValidateException() {
* @expectedException \PHPUnit_Framework_Error_Notice
*/
public function testValidateNotice() {
$this->doValidationBehavior(Schema::FLAG_EXTRA_PROPERTIES_NOTICE);
$this->doValidationBehavior(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE);
}

/**
Expand Down Expand Up @@ -432,4 +431,52 @@ public function testDifferentValidationClass() {
$this->assertSame('!!value is not a valid !integer.', $ex->getMessage());
}
}

/**
* Test allow null.
*
* @param string $short The short type.
* @param string $long The long type.
* @param mixed $sample As sample value.
* @dataProvider provideTypes
*/
public function testAllowNull($short, $long, $sample) {
$schema = new Schema([":$short|n"]);

$null = $schema->validate(null);
$this->assertNull($null);

$clean = $schema->validate($sample);
$this->assertSame($sample, $clean);
}

/**
* Test default values.
*/
public function testDefault() {
$schema = new Schema([
'prop:s' => ['default' => 'foo']
]);

$valid = $schema->validate([]);
$this->assertSame(['prop' => 'foo'], $valid);

$valid = $schema->validate([], true);
$this->assertSame([], $valid);
}

/**
* Default values for non-required fields.
*/
public function testDefaultNotRequired() {
$schema = new Schema([
'prop:s?' => ['default' => 'foo']
]);

$valid = $schema->validate([]);
$this->assertSame(['prop' => 'foo'], $valid);

$valid = $schema->validate([], true);
$this->assertSame([], $valid);
}
}
4 changes: 2 additions & 2 deletions tests/NestedSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public function testArrayOfObjectsInvalid() {
* @expectedException \Garden\Schema\ValidationException
*/
public function testValidateException() {
$this->doValidationBehavior(Schema::FLAG_EXTRA_PROPERTIES_EXCEPTION);
$this->doValidationBehavior(Schema::VALIDATE_EXTRA_PROPERTY_EXCEPTION);
}

/**
Expand All @@ -194,7 +194,7 @@ public function testValidateException() {
* @expectedException \PHPUnit_Framework_Error_Notice
*/
public function testValidateNotice() {
$this->doValidationBehavior(Schema::FLAG_EXTRA_PROPERTIES_NOTICE);
$this->doValidationBehavior(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE);
}

/**
Expand Down
20 changes: 10 additions & 10 deletions tests/PropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public function testPropertyAccess() {

$this->assertSame(0, $schema->getFlags());
$behaviors = [
Schema::FLAG_EXTRA_PROPERTIES_NOTICE,
Schema::FLAG_EXTRA_PROPERTIES_EXCEPTION
Schema::VALIDATE_EXTRA_PROPERTY_NOTICE,
Schema::VALIDATE_EXTRA_PROPERTY_EXCEPTION
];
foreach ($behaviors as $behavior) {
$schema->setFlags($behavior);
Expand All @@ -38,16 +38,16 @@ public function testPropertyAccess() {
public function testGetSetFlag() {
$schema = new Schema();

$schema->setFlag(Schema::FLAG_EXTRA_PROPERTIES_NOTICE, true);
$this->assertTrue($schema->hasFlag(Schema::FLAG_EXTRA_PROPERTIES_NOTICE));
$schema->setFlag(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE, true);
$this->assertTrue($schema->hasFlag(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE));

$schema->setFlag(Schema::FLAG_EXTRA_PROPERTIES_EXCEPTION, true);
$this->assertTrue($schema->hasFlag(Schema::FLAG_EXTRA_PROPERTIES_EXCEPTION));
$this->assertTrue($schema->hasFlag(Schema::FLAG_EXTRA_PROPERTIES_NOTICE));
$schema->setFlag(Schema::VALIDATE_EXTRA_PROPERTY_EXCEPTION, true);
$this->assertTrue($schema->hasFlag(Schema::VALIDATE_EXTRA_PROPERTY_EXCEPTION));
$this->assertTrue($schema->hasFlag(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE));

$schema->setFlag(Schema::FLAG_EXTRA_PROPERTIES_NOTICE, false);
$this->assertFalse($schema->hasFlag(Schema::FLAG_EXTRA_PROPERTIES_NOTICE));
$this->assertTrue($schema->hasFlag(Schema::FLAG_EXTRA_PROPERTIES_EXCEPTION));
$schema->setFlag(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE, false);
$this->assertFalse($schema->hasFlag(Schema::VALIDATE_EXTRA_PROPERTY_NOTICE));
$this->assertTrue($schema->hasFlag(Schema::VALIDATE_EXTRA_PROPERTY_EXCEPTION));
}

/**
Expand Down
6 changes: 3 additions & 3 deletions tests/StringValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@ public function providePatternTests() {
* Test the enum constraint.
*
* @expectedException \Garden\Schema\ValidationException
* @expectedExceptionMessage value must be one of: one, two, three.
* @expectedExceptionMessage value must be one of: one, two, three, null.
* @expectedExceptionCode 422
*/
public function testEnum() {
$enum = ['one', 'two', 'three'];
$schema = new Schema([':s' => ['enum' => $enum]]);
$enum = ['one', 'two', 'three', null];
$schema = new Schema([':s|n' => ['enum' => $enum]]);

foreach ($enum as $str) {
$this->assertTrue($schema->isValid($str));
Expand Down

0 comments on commit a517841

Please sign in to comment.