From 64147a6a88f04ab35a800b488deaf5141d538985 Mon Sep 17 00:00:00 2001 From: Terah Date: Mon, 15 Dec 2014 15:24:54 +1000 Subject: [PATCH 01/10] Adding isCallable, propertyExists, propertiesExist --- lib/Assert/Assertion.php | 135 +++++++++++++++++++++++++++++++++- lib/Assert/AssertionChain.php | 9 +++ lib/Assert/LazyAssertion.php | 9 +++ 3 files changed, 149 insertions(+), 4 deletions(-) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index a187d18b..0da16194 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -28,6 +28,7 @@ * @method static void nullOrInteger($value, $message = null, $propertyPath = null) * @method static void nullOrFloat($value, $message = null, $propertyPath = null) * @method static void nullOrDigit($value, $message = null, $propertyPath = null) + * @method static void nullOrDate($value, $message = null, $propertyPath = null) * @method static void nullOrIntegerish($value, $message = null, $propertyPath = null) * @method static void nullOrBoolean($value, $message = null, $propertyPath = null) * @method static void nullOrScalar($value, $message = null, $propertyPath = null) @@ -48,8 +49,12 @@ * @method static void nullOrNumeric($value, $message = null, $propertyPath = null) * @method static void nullOrIsArray($value, $message = null, $propertyPath = null) * @method static void nullOrKeyExists($value, $key, $message = null, $propertyPath = null) + * @method static void nullOrKeysExist($value, $keys, $message = null, $propertyPath = null) + * @method static void nullOrPropertyExists($value, $key, $message = null, $propertyPath = null) + * @method static void nullOrPropertiesExist($value, $keys, $message = null, $propertyPath = null) * @method static void nullOrNotEmptyKey($value, $key, $message = null, $propertyPath = null) * @method static void nullOrNotBlank($value, $message = null, $propertyPath = null) + * @method static void nullOrIsCallable($value, $message = null, $propertyPath = null) * @method static void nullOrIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void nullOrNotIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void nullOrSubclassOf($value, $className, $message = null, $propertyPath = null) @@ -70,6 +75,9 @@ * @method static void nullOrIsJsonString($value, $message = null, $propertyPath = null) * @method static void nullOrUuid($value, $message = null, $propertyPath = null) * @method static void nullOrCount($countable, $count, $message = null, $propertyPath = null) + * @method static void nullOrChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null) + * @method static void nullOrMethodExists($value, $object, $message = null, $propertyPath = null) + * @method static void nullOrIsObject($value, $message = null, $propertyPath = null) * @method static void allEq($value, $value2, $message = null, $propertyPath = null) * @method static void allSame($value, $value2, $message = null, $propertyPath = null) * @method static void allNotEq($value1, $value2, $message = null, $propertyPath = null) @@ -77,6 +85,7 @@ * @method static void allInteger($value, $message = null, $propertyPath = null) * @method static void allFloat($value, $message = null, $propertyPath = null) * @method static void allDigit($value, $message = null, $propertyPath = null) + * @method static void allDate($value, $message = null, $propertyPath = null) * @method static void allIntegerish($value, $message = null, $propertyPath = null) * @method static void allBoolean($value, $message = null, $propertyPath = null) * @method static void allScalar($value, $message = null, $propertyPath = null) @@ -97,8 +106,12 @@ * @method static void allNumeric($value, $message = null, $propertyPath = null) * @method static void allIsArray($value, $message = null, $propertyPath = null) * @method static void allKeyExists($value, $key, $message = null, $propertyPath = null) + * @method static void allKeysExist($value, $keys, $message = null, $propertyPath = null) + * @method static void allPropertyExists($value, $key, $message = null, $propertyPath = null) + * @method static void allPropertiesExist($value, $keys, $message = null, $propertyPath = null) * @method static void allNotEmptyKey($value, $key, $message = null, $propertyPath = null) * @method static void allNotBlank($value, $message = null, $propertyPath = null) + * @method static void allIsCallable($value, $message = null, $propertyPath = null) * @method static void allIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void allNotIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void allSubclassOf($value, $className, $message = null, $propertyPath = null) @@ -119,9 +132,9 @@ * @method static void allIsJsonString($value, $message = null, $propertyPath = null) * @method static void allUuid($value, $message = null, $propertyPath = null) * @method static void allCount($countable, $count, $message = null, $propertyPath = null) - * @method static void choiceNotEmpty($values, $choices, $message = null, $propertyPath = null) - * @method static void methodExists($value, $object, $message = null, $propertyPath = null) - * @method static void isObject($value, $message = null, $propertyPath = null) + * @method static void allChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null) + * @method static void allMethodExists($value, $object, $message = null, $propertyPath = null) + * @method static void allIsObject($value, $message = null, $propertyPath = null) * METHODEND */ class Assertion @@ -174,7 +187,11 @@ class Assertion const INVALID_OBJECT = 207; const INVALID_METHOD = 208; const INVALID_SCALAR = 209; - + const INVALID_DATE = 210; + const INVALID_CALLABLE = 211; + const INVALID_KEYS_EXIST = 300; + const INVALID_PROPERTY_EXISTS = 301; + const INVALID_PROPERTIES_EXIST = 302; /** * Exception to throw when an assertion failed. * @@ -346,6 +363,18 @@ public static function digit($value, $message = null, $propertyPath = null) } } + public static function date($value, $message=null, $propertyPath=null) + { + if ( strtotime($value) === false ) + { + $message = $message ?: sprintf( + 'Value "%s" is not a date.', + self::stringify($value) + ); + throw static::createException($value, $message, static::INVALID_DATE, $propertyPath); + } + } + /** * Assert that value is a php integer'ish. * @param mixed $value @@ -824,6 +853,84 @@ public static function keyExists($value, $key, $message = null, $propertyPath = } } + /** + * Assert that keys exist in array + * + * @param mixed $value + * @param string|integer $key + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function keysExist($value, $keys, $message = null, $propertyPath = null) + { + static::isArray($value, $message, $propertyPath); + + foreach ( $keys as $key ) { + + if ( ! array_key_exists($key, $value)) { + $message = $message ?: sprintf( + 'Array does not contain an element with key "%s"', + self::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_KEYS_EXIST, $propertyPath, array('key' => $key)); + } + } + + } + + /** + * Assert that property exists in array + * + * @param mixed $value + * @param string|integer $key + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function propertyExists($value, $key, $message = null, $propertyPath = null) + { + static::isObject($value); + + if ( ! property_exists($value, $key)) { + $message = $message ?: sprintf( + 'Object does not contain an property with key "%s"', + self::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_PROPERTY_EXISTS, $propertyPath, array('key' => $key)); + + } + } + + /** + * Assert that properties exists in array + * + * @param mixed $value + * @param array $keys + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function propertiesExist($value, array $keys, $message = null, $propertyPath = null) + { + static::isObject($value); + foreach ($keys as $key ) + { + if ( !property_exists($value, $key) ) + { + $message = $message ?: sprintf( + 'Object does not contain an property with key "%s"', + self::stringify($key) + ); + throw static::createException($value, $message, static::INVALID_PROPERTIES_EXIST, $propertyPath, array('key' => $key)); + } + } + } /** * Assert that key exists in array and it's value not empty. * @@ -861,6 +968,26 @@ public static function notBlank($value, $message = null, $propertyPath = null) } } + /** + * Assert that value is callable + * + * @param mixed $value + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function isCallable($value, $message = null, $propertyPath = null) + { + if (false === $value || (empty($value) && '0' != $value)) { + $message = $message ?: sprintf( + 'Callable is not callable.' + ); + + throw static::createException($value, $message, static::INVALID_CALLABLE, $propertyPath); + } + } + /** * Assert that value is instance of given class-name. * diff --git a/lib/Assert/AssertionChain.php b/lib/Assert/AssertionChain.php index 64aec7b0..5382a10d 100644 --- a/lib/Assert/AssertionChain.php +++ b/lib/Assert/AssertionChain.php @@ -29,8 +29,10 @@ * @method \Assert\AssertionChain integer($message = null, $propertyPath = null) * @method \Assert\AssertionChain float($message = null, $propertyPath = null) * @method \Assert\AssertionChain digit($message = null, $propertyPath = null) + * @method \Assert\AssertionChain date($message = null, $propertyPath = null) * @method \Assert\AssertionChain integerish($message = null, $propertyPath = null) * @method \Assert\AssertionChain boolean($message = null, $propertyPath = null) + * @method \Assert\AssertionChain scalar($message = null, $propertyPath = null) * @method \Assert\AssertionChain notEmpty($message = null, $propertyPath = null) * @method \Assert\AssertionChain noContent($message = null, $propertyPath = null) * @method \Assert\AssertionChain notNull($message = null, $propertyPath = null) @@ -48,8 +50,12 @@ * @method \Assert\AssertionChain numeric($message = null, $propertyPath = null) * @method \Assert\AssertionChain isArray($message = null, $propertyPath = null) * @method \Assert\AssertionChain keyExists($key, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain keysExist($keys, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain propertyExists($key, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain propertiesExist($keys, $message = null, $propertyPath = null) * @method \Assert\AssertionChain notEmptyKey($key, $message = null, $propertyPath = null) * @method \Assert\AssertionChain notBlank($message = null, $propertyPath = null) + * @method \Assert\AssertionChain isCallable($message = null, $propertyPath = null) * @method \Assert\AssertionChain isInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\AssertionChain notIsInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\AssertionChain subclassOf($className, $message = null, $propertyPath = null) @@ -70,6 +76,9 @@ * @method \Assert\AssertionChain isJsonString($message = null, $propertyPath = null) * @method \Assert\AssertionChain uuid($message = null, $propertyPath = null) * @method \Assert\AssertionChain count($count, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain choicesNotEmpty($choices, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain methodExists($object, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain isObject($message = null, $propertyPath = null) * METHODEND */ class AssertionChain diff --git a/lib/Assert/LazyAssertion.php b/lib/Assert/LazyAssertion.php index 4ecc6e13..76a1a1fd 100644 --- a/lib/Assert/LazyAssertion.php +++ b/lib/Assert/LazyAssertion.php @@ -26,8 +26,10 @@ * @method \Assert\LazyAssertion integer($message = null, $propertyPath = null) * @method \Assert\LazyAssertion float($message = null, $propertyPath = null) * @method \Assert\LazyAssertion digit($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion date($message = null, $propertyPath = null) * @method \Assert\LazyAssertion integerish($message = null, $propertyPath = null) * @method \Assert\LazyAssertion boolean($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion scalar($message = null, $propertyPath = null) * @method \Assert\LazyAssertion notEmpty($message = null, $propertyPath = null) * @method \Assert\LazyAssertion noContent($message = null, $propertyPath = null) * @method \Assert\LazyAssertion notNull($message = null, $propertyPath = null) @@ -45,8 +47,12 @@ * @method \Assert\LazyAssertion numeric($message = null, $propertyPath = null) * @method \Assert\LazyAssertion isArray($message = null, $propertyPath = null) * @method \Assert\LazyAssertion keyExists($key, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion keysExist($keys, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion propertyExists($key, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion propertiesExist($keys, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion notEmptyKey($key, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion notBlank($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion isCallable($message = null, $propertyPath = null) * @method \Assert\LazyAssertion isInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion notIsInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion subclassOf($className, $message = null, $propertyPath = null) @@ -67,6 +73,9 @@ * @method \Assert\LazyAssertion isJsonString($message = null, $propertyPath = null) * @method \Assert\LazyAssertion uuid($message = null, $propertyPath = null) * @method \Assert\LazyAssertion count($count, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion choicesNotEmpty($choices, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion methodExists($object, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion isObject($message = null, $propertyPath = null) * @method \Assert\LazyAssertion all() * @method \Assert\LazyAssertion nullOr() * METHODEND From ae76d58fcd0d0ed9a698b1a17ba550e193f95f70 Mon Sep 17 00:00:00 2001 From: Terah Date: Wed, 7 Jan 2015 13:01:55 +1000 Subject: [PATCH 02/10] Adding outfit validator --- lib/Assert/Assertion.php | 39 +++++++++++++++++++++++++++++++ lib/Assert/AssertionChain.php | 1 + lib/Assert/LazyAssertion.php | 1 + tests/Assert/Tests/AssertTest.php | 11 +++++++++ 4 files changed, 52 insertions(+) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index 0da16194..388666f7 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -78,6 +78,7 @@ * @method static void nullOrChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null) * @method static void nullOrMethodExists($value, $object, $message = null, $propertyPath = null) * @method static void nullOrIsObject($value, $message = null, $propertyPath = null) + * @method static void nullOrUtf8($value, $message = null, $propertyPath = null) * @method static void allEq($value, $value2, $message = null, $propertyPath = null) * @method static void allSame($value, $value2, $message = null, $propertyPath = null) * @method static void allNotEq($value1, $value2, $message = null, $propertyPath = null) @@ -135,6 +136,7 @@ * @method static void allChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null) * @method static void allMethodExists($value, $object, $message = null, $propertyPath = null) * @method static void allIsObject($value, $message = null, $propertyPath = null) + * @method static void allUtf8($value, $message = null, $propertyPath = null) * METHODEND */ class Assertion @@ -192,6 +194,7 @@ class Assertion const INVALID_KEYS_EXIST = 300; const INVALID_PROPERTY_EXISTS = 301; const INVALID_PROPERTIES_EXIST = 302; + const INVALID_UTF8 = 303; /** * Exception to throw when an assertion failed. * @@ -931,6 +934,42 @@ public static function propertiesExist($value, array $keys, $message = null, $pr } } } + + /** + * Assert that string is valid utf8 + * + * @param mixed $value + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function utf8($value, $message = null, $propertyPath = null) + { + static::string($value, $message, $propertyPath); + $pattern = '/^(?: + [\x09\x0A\x0D\x20-\x7E] # ASCII + | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )+$|^$/xs'; + + + if (!preg_match($pattern, $value)) { + $message = $message ?: sprintf( + 'Value "%s" was expected to be a valid UTF8 string', + self::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_UTF8, $propertyPath); + } + + } + /** * Assert that key exists in array and it's value not empty. * diff --git a/lib/Assert/AssertionChain.php b/lib/Assert/AssertionChain.php index 5382a10d..37e04592 100644 --- a/lib/Assert/AssertionChain.php +++ b/lib/Assert/AssertionChain.php @@ -79,6 +79,7 @@ * @method \Assert\AssertionChain choicesNotEmpty($choices, $message = null, $propertyPath = null) * @method \Assert\AssertionChain methodExists($object, $message = null, $propertyPath = null) * @method \Assert\AssertionChain isObject($message = null, $propertyPath = null) + * @method \Assert\AssertionChain utf8($message = null, $propertyPath = null) * METHODEND */ class AssertionChain diff --git a/lib/Assert/LazyAssertion.php b/lib/Assert/LazyAssertion.php index 76a1a1fd..90f305f6 100644 --- a/lib/Assert/LazyAssertion.php +++ b/lib/Assert/LazyAssertion.php @@ -76,6 +76,7 @@ * @method \Assert\LazyAssertion choicesNotEmpty($choices, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion methodExists($object, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion isObject($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion utf8($message = null, $propertyPath = null) * @method \Assert\LazyAssertion all() * @method \Assert\LazyAssertion nullOr() * METHODEND diff --git a/tests/Assert/Tests/AssertTest.php b/tests/Assert/Tests/AssertTest.php index 8ed3aa61..283e3b4f 100644 --- a/tests/Assert/Tests/AssertTest.php +++ b/tests/Assert/Tests/AssertTest.php @@ -357,6 +357,17 @@ public function testValidNumeric() Assertion::numeric(1.23); } + public function testInvalidUtf8() + { + $this->setExpectedException('Assert\AssertionFailedException', null, Assertion::INVALID_UTF8); + Assertion::utf8("foo"); + } + + public function testValidUtf8() + { + Assertion::utf8("1"); + } + public static function dataInvalidArray() { return array( From 494defd85674de916cd33a228cacc49b2fbd4590 Mon Sep 17 00:00:00 2001 From: Terah Date: Tue, 27 Jan 2015 16:10:12 +1000 Subject: [PATCH 03/10] Added a few methods --- lib/Assert/Assertion.php | 145 +++++++++++++++++++++++++++++++++- lib/Assert/AssertionChain.php | 6 ++ lib/Assert/LazyAssertion.php | 6 ++ 3 files changed, 156 insertions(+), 1 deletion(-) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index 472f1928..fd825c9c 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -28,6 +28,7 @@ * @method static void nullOrInteger($value, $message = null, $propertyPath = null) * @method static void nullOrFloat($value, $message = null, $propertyPath = null) * @method static void nullOrDigit($value, $message = null, $propertyPath = null) + * @method static void nullOrDate($value, $message = null, $propertyPath = null) * @method static void nullOrIntegerish($value, $message = null, $propertyPath = null) * @method static void nullOrBoolean($value, $message = null, $propertyPath = null) * @method static void nullOrScalar($value, $message = null, $propertyPath = null) @@ -50,9 +51,13 @@ * @method static void nullOrIsTraversable($value, $message = null, $propertyPath = null) * @method static void nullOrIsArrayAccessible($value, $message = null, $propertyPath = null) * @method static void nullOrKeyExists($value, $key, $message = null, $propertyPath = null) + * @method static void nullOrKeysExist($value, $keys, $message = null, $propertyPath = null) * @method static void nullOrKeyIsset($value, $key, $message = null, $propertyPath = null) + * @method static void nullOrPropertyExists($value, $key, $message = null, $propertyPath = null) + * @method static void nullOrPropertiesExist($value, $keys, $message = null, $propertyPath = null) * @method static void nullOrNotEmptyKey($value, $key, $message = null, $propertyPath = null) * @method static void nullOrNotBlank($value, $message = null, $propertyPath = null) + * @method static void nullOrIsCallable($value, $message = null, $propertyPath = null) * @method static void nullOrIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void nullOrNotIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void nullOrSubclassOf($value, $className, $message = null, $propertyPath = null) @@ -76,6 +81,7 @@ * @method static void nullOrChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null) * @method static void nullOrMethodExists($value, $object, $message = null, $propertyPath = null) * @method static void nullOrIsObject($value, $message = null, $propertyPath = null) + * @method static void nullOrUtf8($value, $message = null, $propertyPath = null) * @method static void allEq($value, $value2, $message = null, $propertyPath = null) * @method static void allSame($value, $value2, $message = null, $propertyPath = null) * @method static void allNotEq($value1, $value2, $message = null, $propertyPath = null) @@ -83,6 +89,7 @@ * @method static void allInteger($value, $message = null, $propertyPath = null) * @method static void allFloat($value, $message = null, $propertyPath = null) * @method static void allDigit($value, $message = null, $propertyPath = null) + * @method static void allDate($value, $message = null, $propertyPath = null) * @method static void allIntegerish($value, $message = null, $propertyPath = null) * @method static void allBoolean($value, $message = null, $propertyPath = null) * @method static void allScalar($value, $message = null, $propertyPath = null) @@ -105,9 +112,13 @@ * @method static void allIsTraversable($value, $message = null, $propertyPath = null) * @method static void allIsArrayAccessible($value, $message = null, $propertyPath = null) * @method static void allKeyExists($value, $key, $message = null, $propertyPath = null) + * @method static void allKeysExist($value, $keys, $message = null, $propertyPath = null) * @method static void allKeyIsset($value, $key, $message = null, $propertyPath = null) + * @method static void allPropertyExists($value, $key, $message = null, $propertyPath = null) + * @method static void allPropertiesExist($value, $keys, $message = null, $propertyPath = null) * @method static void allNotEmptyKey($value, $key, $message = null, $propertyPath = null) * @method static void allNotBlank($value, $message = null, $propertyPath = null) + * @method static void allIsCallable($value, $message = null, $propertyPath = null) * @method static void allIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void allNotIsInstanceOf($value, $className, $message = null, $propertyPath = null) * @method static void allSubclassOf($value, $className, $message = null, $propertyPath = null) @@ -131,6 +142,7 @@ * @method static void allChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null) * @method static void allMethodExists($value, $object, $message = null, $propertyPath = null) * @method static void allIsObject($value, $message = null, $propertyPath = null) + * @method static void allUtf8($value, $message = null, $propertyPath = null) * METHODEND */ class Assertion @@ -186,7 +198,12 @@ class Assertion const INVALID_OBJECT = 207; const INVALID_METHOD = 208; const INVALID_SCALAR = 209; - + const INVALID_DATE = 210; + const INVALID_CALLABLE = 211; + const INVALID_KEYS_EXIST = 300; + const INVALID_PROPERTY_EXISTS = 301; + const INVALID_PROPERTIES_EXIST = 302; + const INVALID_UTF8 = 303; /** * Exception to throw when an assertion failed. * @@ -358,6 +375,18 @@ public static function digit($value, $message = null, $propertyPath = null) } } + public static function date($value, $message=null, $propertyPath=null) + { + if ( strtotime($value) === false ) + { + $message = sprintf( + $message ?: 'Value "%s" is not a date.', + self::stringify($value) + ); + throw static::createException($value, $message, static::INVALID_DATE, $propertyPath); + } + } + /** * Assert that value is a php integer'ish. * @param mixed $value @@ -878,6 +907,120 @@ public static function keyExists($value, $key, $message = null, $propertyPath = } } + /** + * Assert that keys exist in array + * + * @param mixed $value + * @param string|integer $key + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function keysExist($value, $keys, $message = null, $propertyPath = null) + { + static::isArray($value, $message, $propertyPath); + + foreach ( $keys as $key ) { + + if ( ! array_key_exists($key, $value)) { + $message = $message ?: sprintf( + 'Array does not contain an element with key "%s"', + self::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_KEYS_EXIST, $propertyPath, array('key' => $key)); + } + } + + } + + /** + * Assert that property exists in array + * + * @param mixed $value + * @param string|integer $key + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function propertyExists($value, $key, $message = null, $propertyPath = null) + { + static::isObject($value); + + if ( ! property_exists($value, $key)) { + $message = $message ?: sprintf( + 'Object does not contain an property with key "%s"', + self::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_PROPERTY_EXISTS, $propertyPath, array('key' => $key)); + + } + } + + /** + * Assert that properties exists in array + * + * @param mixed $value + * @param array $keys + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function propertiesExist($value, array $keys, $message = null, $propertyPath = null) + { + static::isObject($value); + foreach ($keys as $key ) + { + if ( !property_exists($value, $key) ) + { + $message = $message ?: sprintf( + 'Object does not contain an property with key "%s"', + self::stringify($key) + ); + throw static::createException($value, $message, static::INVALID_PROPERTIES_EXIST, $propertyPath, array('key' => $key)); + } + } + } + + /** + * Assert that string is valid utf8 + * + * @param mixed $value + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ + public static function utf8($value, $message = null, $propertyPath = null) + { + static::string($value, $message, $propertyPath); + $pattern = '/^(?: + [\x09\x0A\x0D\x20-\x7E] # ASCII + | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )+$|^$/xs'; + + + if (!preg_match($pattern, $value)) { + $message = $message ?: sprintf( + 'Value "%s" was expected to be a valid UTF8 string', + self::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_UTF8, $propertyPath); + } + + } + /** * Assert that key exists in an array/array-accessible object using isset() * diff --git a/lib/Assert/AssertionChain.php b/lib/Assert/AssertionChain.php index 7689558a..37e04592 100644 --- a/lib/Assert/AssertionChain.php +++ b/lib/Assert/AssertionChain.php @@ -29,6 +29,7 @@ * @method \Assert\AssertionChain integer($message = null, $propertyPath = null) * @method \Assert\AssertionChain float($message = null, $propertyPath = null) * @method \Assert\AssertionChain digit($message = null, $propertyPath = null) + * @method \Assert\AssertionChain date($message = null, $propertyPath = null) * @method \Assert\AssertionChain integerish($message = null, $propertyPath = null) * @method \Assert\AssertionChain boolean($message = null, $propertyPath = null) * @method \Assert\AssertionChain scalar($message = null, $propertyPath = null) @@ -49,8 +50,12 @@ * @method \Assert\AssertionChain numeric($message = null, $propertyPath = null) * @method \Assert\AssertionChain isArray($message = null, $propertyPath = null) * @method \Assert\AssertionChain keyExists($key, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain keysExist($keys, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain propertyExists($key, $message = null, $propertyPath = null) + * @method \Assert\AssertionChain propertiesExist($keys, $message = null, $propertyPath = null) * @method \Assert\AssertionChain notEmptyKey($key, $message = null, $propertyPath = null) * @method \Assert\AssertionChain notBlank($message = null, $propertyPath = null) + * @method \Assert\AssertionChain isCallable($message = null, $propertyPath = null) * @method \Assert\AssertionChain isInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\AssertionChain notIsInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\AssertionChain subclassOf($className, $message = null, $propertyPath = null) @@ -74,6 +79,7 @@ * @method \Assert\AssertionChain choicesNotEmpty($choices, $message = null, $propertyPath = null) * @method \Assert\AssertionChain methodExists($object, $message = null, $propertyPath = null) * @method \Assert\AssertionChain isObject($message = null, $propertyPath = null) + * @method \Assert\AssertionChain utf8($message = null, $propertyPath = null) * METHODEND */ class AssertionChain diff --git a/lib/Assert/LazyAssertion.php b/lib/Assert/LazyAssertion.php index a6352b3a..90f305f6 100644 --- a/lib/Assert/LazyAssertion.php +++ b/lib/Assert/LazyAssertion.php @@ -26,6 +26,7 @@ * @method \Assert\LazyAssertion integer($message = null, $propertyPath = null) * @method \Assert\LazyAssertion float($message = null, $propertyPath = null) * @method \Assert\LazyAssertion digit($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion date($message = null, $propertyPath = null) * @method \Assert\LazyAssertion integerish($message = null, $propertyPath = null) * @method \Assert\LazyAssertion boolean($message = null, $propertyPath = null) * @method \Assert\LazyAssertion scalar($message = null, $propertyPath = null) @@ -46,8 +47,12 @@ * @method \Assert\LazyAssertion numeric($message = null, $propertyPath = null) * @method \Assert\LazyAssertion isArray($message = null, $propertyPath = null) * @method \Assert\LazyAssertion keyExists($key, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion keysExist($keys, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion propertyExists($key, $message = null, $propertyPath = null) + * @method \Assert\LazyAssertion propertiesExist($keys, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion notEmptyKey($key, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion notBlank($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion isCallable($message = null, $propertyPath = null) * @method \Assert\LazyAssertion isInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion notIsInstanceOf($className, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion subclassOf($className, $message = null, $propertyPath = null) @@ -71,6 +76,7 @@ * @method \Assert\LazyAssertion choicesNotEmpty($choices, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion methodExists($object, $message = null, $propertyPath = null) * @method \Assert\LazyAssertion isObject($message = null, $propertyPath = null) + * @method \Assert\LazyAssertion utf8($message = null, $propertyPath = null) * @method \Assert\LazyAssertion all() * @method \Assert\LazyAssertion nullOr() * METHODEND From af771a8359c91fc083aff6727f06cac109e2bc30 Mon Sep 17 00:00:00 2001 From: Terry Cullen Date: Wed, 11 Feb 2015 11:34:22 +1000 Subject: [PATCH 04/10] Fixing utf and doc blocks for date --- lib/Assert/Assertion.php | 22 ++++++++++------------ tests/bootstrap.php | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index fd825c9c..3c7aafe5 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -375,6 +375,15 @@ public static function digit($value, $message = null, $propertyPath = null) } } + /** + * Validates if an string is a date . + * + * @param string $value + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ public static function date($value, $message=null, $propertyPath=null) { if ( strtotime($value) === false ) @@ -998,19 +1007,8 @@ public static function propertiesExist($value, array $keys, $message = null, $pr public static function utf8($value, $message = null, $propertyPath = null) { static::string($value, $message, $propertyPath); - $pattern = '/^(?: - [\x09\x0A\x0D\x20-\x7E] # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )+$|^$/xs'; - - if (!preg_match($pattern, $value)) { + if ( mb_detect_encoding($value, 'UTF-8', true) !== 'UTF-8' ) { $message = $message ?: sprintf( 'Value "%s" was expected to be a valid UTF8 string', self::stringify($value) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 61e452d4..a4fe94a1 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,5 +1,5 @@ Date: Wed, 11 Feb 2015 12:24:13 +1000 Subject: [PATCH 05/10] Tests --- tests/Assert/Tests/AssertTest.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/Assert/Tests/AssertTest.php b/tests/Assert/Tests/AssertTest.php index 014a0a81..dbb46c92 100644 --- a/tests/Assert/Tests/AssertTest.php +++ b/tests/Assert/Tests/AssertTest.php @@ -358,15 +358,13 @@ public function testValidNumeric() Assertion::numeric(1.23); } - public function testInvalidUtf8() - { - $this->setExpectedException('Assert\AssertionFailedException', null, Assertion::INVALID_UTF8); - Assertion::utf8("foo"); - } - public function testValidUtf8() { - Assertion::utf8("1"); + $text = 'Française señor café 0123 කොහොමද ශ්‍රී ලංකා hello Žluťoučký kůň ' + . 'ÀÁÂ,ÃÄÅ,Æ,ÇÈ,ÉÊË,ÌÍÎ,ÏÐÑ,ÒÓÔ,ÕÖØ,ÙÚÛ,ÜÝ,Þ,' + . 'ß,àáâ,ãäå,æ,çèé,êëì,íîï,ðñò,óôõ,öøù,úûýý,þ,ÿŔŕ ' + . 'YA(亚) HE(何) Tra Mỹ'; + Assertion::utf8($text); } public static function dataInvalidArray() From ee6cbaeeddfc3932a586e5368d94be17cdd068ec Mon Sep 17 00:00:00 2001 From: Terry Cullen Date: Wed, 11 Feb 2015 12:27:12 +1000 Subject: [PATCH 06/10] Removed a bit of debugging code --- tests/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a4fe94a1..61e452d4 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,5 +1,5 @@ Date: Tue, 17 Feb 2015 12:12:20 +1000 Subject: [PATCH 07/10] Adding utf8 --- lib/Assert/Assertion.php | 22 ++++++++++------------ tests/Assert/Tests/AssertTest.php | 12 +++++------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index fd825c9c..3c7aafe5 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -375,6 +375,15 @@ public static function digit($value, $message = null, $propertyPath = null) } } + /** + * Validates if an string is a date . + * + * @param string $value + * @param string|null $message + * @param string|null $propertyPath + * @return void + * @throws \Assert\AssertionFailedException + */ public static function date($value, $message=null, $propertyPath=null) { if ( strtotime($value) === false ) @@ -998,19 +1007,8 @@ public static function propertiesExist($value, array $keys, $message = null, $pr public static function utf8($value, $message = null, $propertyPath = null) { static::string($value, $message, $propertyPath); - $pattern = '/^(?: - [\x09\x0A\x0D\x20-\x7E] # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )+$|^$/xs'; - - if (!preg_match($pattern, $value)) { + if ( mb_detect_encoding($value, 'UTF-8', true) !== 'UTF-8' ) { $message = $message ?: sprintf( 'Value "%s" was expected to be a valid UTF8 string', self::stringify($value) diff --git a/tests/Assert/Tests/AssertTest.php b/tests/Assert/Tests/AssertTest.php index 014a0a81..dbb46c92 100644 --- a/tests/Assert/Tests/AssertTest.php +++ b/tests/Assert/Tests/AssertTest.php @@ -358,15 +358,13 @@ public function testValidNumeric() Assertion::numeric(1.23); } - public function testInvalidUtf8() - { - $this->setExpectedException('Assert\AssertionFailedException', null, Assertion::INVALID_UTF8); - Assertion::utf8("foo"); - } - public function testValidUtf8() { - Assertion::utf8("1"); + $text = 'Française señor café 0123 කොහොමද ශ්‍රී ලංකා hello Žluťoučký kůň ' + . 'ÀÁÂ,ÃÄÅ,Æ,ÇÈ,ÉÊË,ÌÍÎ,ÏÐÑ,ÒÓÔ,ÕÖØ,ÙÚÛ,ÜÝ,Þ,' + . 'ß,àáâ,ãäå,æ,çèé,êëì,íîï,ðñò,óôõ,öøù,úûýý,þ,ÿŔŕ ' + . 'YA(亚) HE(何) Tra Mỹ'; + Assertion::utf8($text); } public static function dataInvalidArray() From 8d4ad7347d73d6a7e23f5874638f7486835ac174 Mon Sep 17 00:00:00 2001 From: Terah Date: Thu, 26 Feb 2015 17:11:18 +1000 Subject: [PATCH 08/10] property_exists doesn't work on magic properties --- lib/Assert/Assertion.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index 3c7aafe5..e5a1c462 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -984,7 +984,8 @@ public static function propertiesExist($value, array $keys, $message = null, $pr static::isObject($value); foreach ($keys as $key ) { - if ( !property_exists($value, $key) ) + // Using isset to allow resolution of magically defined properties + if ( ! property_exists($value, $key) && ! isset($value->$key) ) { $message = $message ?: sprintf( 'Object does not contain an property with key "%s"', From 129fba01dbc5406617ead5fc6229a101b37db698 Mon Sep 17 00:00:00 2001 From: Terah Date: Fri, 27 Feb 2015 14:07:16 +1000 Subject: [PATCH 09/10] Making propertiesExist support magic properties --- lib/Assert/Assertion.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index e5a1c462..33015c41 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -958,7 +958,7 @@ public static function propertyExists($value, $key, $message = null, $propertyPa { static::isObject($value); - if ( ! property_exists($value, $key)) { + if ( ! property_exists($value, $key) && ! isset($value->$key) ) { $message = $message ?: sprintf( 'Object does not contain an property with key "%s"', self::stringify($key) From 7b2c874274863555868839fb09de4a60ede02995 Mon Sep 17 00:00:00 2001 From: Terah Date: Tue, 3 Mar 2015 15:33:28 +1000 Subject: [PATCH 10/10] Setting a custom exception class --- lib/Assert/Assertion.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Assert/Assertion.php b/lib/Assert/Assertion.php index 33015c41..38159e6f 100644 --- a/lib/Assert/Assertion.php +++ b/lib/Assert/Assertion.php @@ -222,6 +222,11 @@ protected static function createException($value, $message, $code, $propertyPath return new $exceptionClass($message, $code, $propertyPath, $value, $constraints); } + public static function setExceptionClass($exceptionClass) + { + static::$exceptionClass = $exceptionClass; + } + /** * Assert that two values are equal (using == ). *