From 4e29a2487c8dbcfde219e1d68855e2326df9362b Mon Sep 17 00:00:00 2001 From: Brian Moon Date: Mon, 20 Nov 2023 11:09:34 -0600 Subject: [PATCH] Added phan, php-cs-fixer and bug fixes --- .gitignore | 2 + .phan/config.php | 116 ++++++++ .php-cs-fixer.dist.php | 68 +++++ composer.json | 37 ++- phpunit.xml.dist | 46 +-- src/Constraint.php | 147 +++++----- src/Constraint/AbstractConstraint.php | 12 +- src/Constraint/Bytes.php | 9 +- src/Constraint/Currency.php | 17 +- src/Constraint/Date.php | 7 +- src/Constraint/DateTime.php | 7 +- src/Constraint/Length.php | 15 +- src/Constraint/Range.php | 31 +- src/Constraint/Time.php | 7 +- src/Constraint/URL.php | 7 +- src/Constraint/URLPath.php | 11 +- src/Constraint/Year.php | 7 +- src/ConstraintException.php | 18 +- tests/Constraint/BytesTest.php | 18 +- tests/Constraint/CurrencyTest.php | 24 +- tests/Constraint/DateTest.php | 26 +- tests/Constraint/DateTimeTest.php | 26 +- tests/Constraint/LengthTest.php | 65 +++-- tests/Constraint/RangeTest.php | 73 +++-- tests/Constraint/TimeTest.php | 38 ++- tests/Constraint/URLPathTest.php | 20 +- tests/Constraint/URLTest.php | 20 +- tests/Constraint/YearTest.php | 22 +- tests/ConstraintTest.php | 400 +++++++++++++------------- tests/bootstrap.php | 2 +- 30 files changed, 751 insertions(+), 547 deletions(-) create mode 100644 .phan/config.php create mode 100644 .php-cs-fixer.dist.php diff --git a/.gitignore b/.gitignore index cd2e33f..190fbb7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ .DS_Store *~ *.sw[aop] +.php-cs-fixer.cache +.phpunit.result.cache # Deployment dependencies vendor diff --git a/.phan/config.php b/.phan/config.php new file mode 100644 index 0000000..0349851 --- /dev/null +++ b/.phan/config.php @@ -0,0 +1,116 @@ + true, + + // Allow null to be cast as any type and for any + // type to be cast to null. + "null_casts_as_any_type" => true, + + // If this has entries, scalars (int, float, bool, string, null) + // are allowed to perform the casts listed. + // E.g. ['int' => ['float', 'string'], 'float' => ['int'], 'string' => ['int'], 'null' => ['string']] + // allows casting null to a string, but not vice versa. + // (subset of scalar_implicit_cast) + 'scalar_implicit_partial' => [ + 'int' => ['float', 'string'], + 'float' => ['int'], + 'string' => ['int'], + 'null' => ['string', 'bool'], + 'bool' => ['null'], + ], + + // Backwards Compatibility Checking + 'backward_compatibility_checks' => false, + + // Run a quick version of checks that takes less + // time + "quick_mode" => true, + + // Only emit critical issues + "minimum_severity" => 0, + + // A set of fully qualified class-names for which + // a call to parent::__construct() is required + 'parent_constructor_required' => [ + ], + + // Add any issue types (such as 'PhanUndeclaredMethod') + // here to inhibit them from being reported + 'suppress_issue_types' => [ + // These report false positives in libraries due + // to them not being used by any of the other + // library code. + 'PhanUnreferencedPublicClassConstant', + 'PhanWriteOnlyProtectedProperty', + 'PhanUnreferencedPublicMethod', + 'PhanUnreferencedUseNormal', + 'PhanUnreferencedProtectedMethod', + 'PhanUnreferencedProtectedProperty', + + ], + + // A list of directories that should be parsed for class and + // method information. After excluding the directories + // defined in exclude_analysis_directory_list, the remaining + // files will be statically analyzed for errors. + // + // Thus, both first-party and third-party code being used by + // your application should be included in this list. + 'directory_list' => [ + 'src', + 'vendor', + 'tests', + ], + + // A list of directories holding code that we want + // to parse, but not analyze + "exclude_analysis_directory_list" => [ + "vendor", + "tests", + ], + + // A file list that defines files that will be excluded + // from parsing and analysis and will not be read at all. + // + // This is useful for excluding hopelessly unanalyzable + // files that can't be removed for whatever reason. + 'exclude_file_list' => [ + ], + + // Set to true in order to attempt to detect dead + // (unreferenced) code. Keep in mind that the + // results will only be a guess given that classes, + // properties, constants and methods can be referenced + // as variables (like `$class->$property` or + // `$class->$method()`) in ways that we're unable + // to make sense of. + 'dead_code_detection' => true, +]; diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..33de634 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,68 @@ +in(__DIR__) +; + +return (new PhpCsFixer\Config()) + ->setRules([ + '@PSR2' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'binary_operator_spaces' => [ + 'default' => 'align_single_space', + ], + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => ['statements' => ['return']], + 'braces_position' => [ + 'allow_single_line_anonymous_functions' => true, + 'allow_single_line_empty_anonymous_classes' => true, + 'anonymous_classes_opening_brace' => 'same_line', + 'anonymous_functions_opening_brace' => 'same_line', + 'classes_opening_brace' => 'same_line', + 'control_structures_opening_brace' => 'same_line', + 'functions_opening_brace' => 'same_line', + ], + 'combine_consecutive_unsets' => true, + 'concat_space' => [ + 'spacing' => 'one', + ], + 'declare_equal_normalize' => true, + 'escape_implicit_backslashes' => [ + 'single_quoted' => true, + 'double_quoted' => true, + ], + 'function_typehint_space' => true, + 'include' => true, + 'lowercase_cast' => true, +// 'class_attributes_separation' => ['elements' => ['method']], + 'native_function_casing' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_comment' => true, + 'no_empty_statement' => true, + 'no_mixed_echo_print' => [ + 'use' => 'echo', + ], + 'no_multiline_whitespace_around_double_arrow' => true, + 'multiline_whitespace_before_semicolons' => false, + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_around_offset' => true, + 'no_unused_imports' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'object_operator_without_whitespace' => true, + 'ordered_imports' => true, + 'short_scalar_cast' => true, + 'single_blank_line_before_namespace' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'ternary_operator_spaces' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'whitespace_after_comma_in_array' => true, + ]) + ->setFinder($finder) +; diff --git a/composer.json b/composer.json index 97152fe..0bf446b 100644 --- a/composer.json +++ b/composer.json @@ -3,16 +3,19 @@ "type": "library", "description": "Type constraint checking library", "license": "BSD-3-Clause", - "authors": [ - { - "name": "Brian Moon", - "email": "brianm@dealnews.com", - "homepage": "https://www.dealnews.com/", - "role": "Developer" - } - ], + "config": { + "optimize-autoloader": true, + "discard-changes": true, + "sort-packages": true + }, "require": { - "php": ">=7.1.0" + "ext-mbstring": "*", + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.38", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpunit/phpunit": "^9.6" }, "autoload": { "psr-4": { @@ -24,7 +27,19 @@ "DealNews\\Constraints\\Tests\\": "tests/" } }, - "require-dev": { - "phpunit/phpunit": "^9.5" + "scripts": { + "phan": [ + "docker run --rm -e PHAN_DISABLE_XDEBUG_WARN=1 -v `pwd`:/mnt/src -w /mnt/src phanphp/phan:5 -p" + ], + "test": [ + "parallel-lint src/ tests/", + "phpunit --colors=never" + ], + "lint": [ + "parallel-lint src/ tests/" + ], + "fix": [ + "php-cs-fixer fix --config .php-cs-fixer.dist.php src tests" + ] } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 61937c6..ce37ae1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,23 +1,25 @@ - - - - ./tests - - - - - functional - - - - - ./src - - ./tests - ./vendor - - - - \ No newline at end of file + + + + ./src + + + ./tests + ./vendor + + + + + + + + ./tests + + + + + functional + + + diff --git a/src/Constraint.php b/src/Constraint.php index efae533..f3e2dad 100644 --- a/src/Constraint.php +++ b/src/Constraint.php @@ -8,38 +8,41 @@ * @copyright 1997-Present DealNews.com, Inc * @package Constraints */ - class Constraint { /** * Primitive types supported by this class * * @var array + * + * @phan-suppress PhanReadOnlyProtectedProperty */ protected $primitive_types = [ - "array", - "boolean", - "double", - "integer", - "string", + 'array', + 'boolean', + 'double', + 'integer', + 'string', ]; /** * Abstract types and the classes that validate them * * @var array + * + * @phan-suppress PhanReadOnlyProtectedProperty */ protected $abstract_types = [ - "bytes" => "\DealNews\Constraints\Constraint\Bytes", - "currency" => "\DealNews\Constraints\Constraint\Currency", - "date" => "\DealNews\Constraints\Constraint\Date", - "datetime" => "\DealNews\Constraints\Constraint\DateTime", - "length" => "\DealNews\Constraints\Constraint\Length", - "range" => "\DealNews\Constraints\Constraint\Range", - "time" => "\DealNews\Constraints\Constraint\Time", - "url" => "\DealNews\Constraints\Constraint\URL", - "url_path" => "\DealNews\Constraints\Constraint\URLPath", - "year" => "\DealNews\Constraints\Constraint\Year", + 'bytes' => \DealNews\Constraints\Constraint\Bytes::class, + 'currency' => \DealNews\Constraints\Constraint\Currency::class, + 'date' => \DealNews\Constraints\Constraint\Date::class, + 'datetime' => \DealNews\Constraints\Constraint\DateTime::class, + 'length' => \DealNews\Constraints\Constraint\Length::class, + 'range' => \DealNews\Constraints\Constraint\Range::class, + 'time' => \DealNews\Constraints\Constraint\Time::class, + 'url' => \DealNews\Constraints\Constraint\URL::class, + 'url_path' => \DealNews\Constraints\Constraint\URLPath::class, + 'year' => \DealNews\Constraints\Constraint\Year::class, ]; /** @@ -47,17 +50,19 @@ class Constraint { * constraints againt when debug is enabled. * * @var array + * + * @phan-suppress PhanReadOnlyProtectedProperty */ protected $valid_constraint = [ - "type" => "", - "default" => null, - "is_nullable" => false, - "read_only" => false, - "constraint" => [], - "min" => 0, - "max" => 0, - "allowed_values" => [], - "pattern" => "" + 'type' => '', + 'default' => null, + 'is_nullable' => false, + 'read_only' => false, + 'constraint' => [], + 'min' => 0, + 'max' => 0, + 'allowed_values' => [], + 'pattern' => '', ]; /** @@ -77,7 +82,7 @@ class Constraint { */ public function __construct(array $extra_options = []) { - if (!empty($_SERVER["DN_DEBUG"])) { + if (!empty($_SERVER['DN_DEBUG'])) { $this->debug = true; } @@ -112,34 +117,34 @@ public function check($value, array $constraint) { } - if (in_array($constraint["type"], $this->primitive_types)) { + if (in_array($constraint['type'], $this->primitive_types)) { - $new_value = $this->filterPrimitive($value, $constraint["type"], $constraint); + $new_value = $this->filterPrimitive($value, $constraint['type'], $constraint); - } elseif (isset($this->abstract_types[$constraint["type"]])) { + } elseif (isset($this->abstract_types[$constraint['type']])) { - $new_value = $this->filterAbstract($value, $this->abstract_types[$constraint["type"]], $constraint); + $new_value = $this->filterAbstract($value, $this->abstract_types[$constraint['type']], $constraint); - } elseif (is_object($value) || class_exists($constraint["type"])) { + } elseif (is_object($value) || class_exists($constraint['type'])) { - $new_value = $this->filterClass($value, $constraint["type"]); + $new_value = $this->filterClass($value, $constraint['type']); } else { throw new \LogicException("Invalid constraint $constraint[type]"); } - if (!empty($constraint["allowed_values"])) { - if (!in_array($new_value, $constraint["allowed_values"])) { + if (!empty($constraint['allowed_values'])) { + if (!in_array($new_value, $constraint['allowed_values'])) { throw new ConstraintException( $value, - "one of ".implode(", ", $constraint["allowed_values"]), - "" + 'one of ' . implode(', ', $constraint['allowed_values']), + '' ); } } - if (!empty($constraint["read_only"])) { + if (!empty($constraint['read_only'])) { // we can validate, but not modify read only values $new_value = $value; } @@ -171,7 +176,7 @@ public function filterPrimitive($value, string $type, array $constraint, array $ switch ($type) { - case "array": + case 'array': if (!is_array($value)) { $new_value = null; if (is_object($value) && $value instanceof \ArrayObject) { @@ -184,64 +189,64 @@ public function filterPrimitive($value, string $type, array $constraint, array $ $this->check($nv, $constraint['constraint']); } } catch (ConstraintException $e) { - $new_value = null; - $expectation = "array contents: " . $e->getExpected(); + $new_value = null; + $expectation = 'array contents: ' . $e->getExpected(); } } break; - case "boolean": + case 'boolean': if (!is_bool($value)) { $new_value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); } break; - case "double": + case 'double': if (!is_float($value)) { $new_value = filter_var($value, FILTER_VALIDATE_FLOAT); } if ($new_value === false) { $new_value = null; - } elseif (isset($constraint["max"]) && $new_value > $constraint["max"]) { - $new_value = null; + } elseif (isset($constraint['max']) && $new_value > $constraint['max']) { + $new_value = null; $expectation = "$constraint[max] or less"; - } elseif (isset($constraint["min"]) && $new_value < $constraint["min"]) { - $new_value = null; + } elseif (isset($constraint['min']) && $new_value < $constraint['min']) { + $new_value = null; $expectation = "$constraint[max] or more"; } break; - case "integer": + case 'integer': if (!is_int($value)) { $new_value = filter_var($value, FILTER_VALIDATE_INT); } if ($new_value === false) { $new_value = null; - } elseif (isset($constraint["max"]) && $new_value > $constraint["max"]) { - $new_value = null; + } elseif (isset($constraint['max']) && $new_value > $constraint['max']) { + $new_value = null; $expectation = "$constraint[max] or less"; - } elseif (isset($constraint["min"]) && $new_value < $constraint["min"]) { - $new_value = null; + } elseif (isset($constraint['min']) && $new_value < $constraint['min']) { + $new_value = null; $expectation = "$constraint[max] or more"; } break; - case "string": + case 'string': if (!is_scalar($value)) { $new_value = null; } else { $new_value = (string)$value; - if (isset($constraint["max"]) && strlen($new_value) > $constraint["max"]) { - $new_value = null; + if (isset($constraint['max']) && mb_strlen($new_value) > $constraint['max']) { + $new_value = null; $expectation = "maximum length of $constraint[max]"; - } elseif (isset($constraint["min"]) && strlen($new_value) < $constraint["min"]) { - $new_value = null; + } elseif (isset($constraint['min']) && mb_strlen($new_value) < $constraint['min']) { + $new_value = null; $expectation = "minimum length of $constraint[min]"; - } elseif (isset($constraint["pattern"]) && !preg_match($constraint["pattern"], $new_value)) { - $new_value = null; - $expectation = "matches pattern"; + } elseif (isset($constraint['pattern']) && !preg_match($constraint['pattern'], $new_value)) { + $new_value = null; + $expectation = 'matches pattern'; } } break; @@ -252,7 +257,7 @@ public function filterPrimitive($value, string $type, array $constraint, array $ throw new ConstraintException( $value, $expectation, - "" + '' ); } @@ -294,7 +299,7 @@ public function filterAbstract($value, string $class, array $constraint) { */ public function filterClass($value, string $class) { if (!($value instanceof $class)) { - if (is_array($value) && is_a($class, "\ArrayObject", true)) { + if (is_array($value) && is_a($class, '\\ArrayObject', true)) { $obj = new $class(); $obj->exchangeArray($value); $value = $obj; @@ -302,10 +307,11 @@ public function filterClass($value, string $class) { throw new ConstraintException( $value, "instance of $class", - "" + '' ); } } + return $value; } @@ -323,8 +329,8 @@ protected function checkDefault($value, array $constraint) { * and throw a warning on dev as that is bad form. */ if (array_key_exists('default', $constraint)) { - if ($constraint["default"] !== null && $value === null) { - $value = $constraint["default"]; + if ($constraint['default'] !== null && $value === null) { + $value = $constraint['default']; } } @@ -348,11 +354,11 @@ protected function isNull($value, array $constraint): bool { if ( $value === null && ( - !isset($constraint["is_nullable"]) || - $constraint["is_nullable"] === true || + !isset($constraint['is_nullable']) || + $constraint['is_nullable'] === true || ( - isset($constraint["default"]) && - $constraint["default"] === null + isset($constraint['default']) && + $constraint['default'] === null ) ) ) { @@ -374,9 +380,10 @@ public function validateConstraint(array $constraint): bool { throw new \LogicException("Invalid constraint option $option", 1); } if ($this->valid_constraint[$option] !== null && gettype($value) != gettype($this->valid_constraint[$option])) { - throw new \LogicException("Constraint option $option must be of type ".gettype($this->valid_constraint[$option]), 2); + throw new \LogicException("Constraint option $option must be of type " . gettype($this->valid_constraint[$option]), 2); } } + return true; } @@ -392,7 +399,7 @@ public static function init(array $extra_options = []) { $key = md5(serialize($extra_options)); if (!array_key_exists($key, $instances)) { - $class = get_called_class(); + $class = get_called_class(); $instances[$key] = new $class($extra_options); } diff --git a/src/Constraint/AbstractConstraint.php b/src/Constraint/AbstractConstraint.php index bbad5a1..3a4e601 100644 --- a/src/Constraint/AbstractConstraint.php +++ b/src/Constraint/AbstractConstraint.php @@ -2,20 +2,18 @@ namespace DealNews\Constraints\Constraint; -use DealNews\Constraints\Constraint; - abstract class AbstractConstraint { - const DESCRIPTION = "A valid value"; + const DESCRIPTION = 'A valid value'; - const EXAMPLE = "none provided"; + const EXAMPLE = 'none provided'; - const PRIMITIVE = ""; + const PRIMITIVE = ''; const PRIMITIVE_IGNORED_PROPERTIES = []; final public function __construct() { - trigger_error(get_called_class()." must not be instantiated.", E_USER_ERROR); - exit(1); + trigger_error(get_called_class() . ' must not be instantiated.', E_USER_ERROR); + exit(1); // @phan-suppress-current-line PhanPluginUnreachableCode } } diff --git a/src/Constraint/Bytes.php b/src/Constraint/Bytes.php index d1a10b0..1c8b192 100644 --- a/src/Constraint/Bytes.php +++ b/src/Constraint/Bytes.php @@ -16,11 +16,11 @@ */ class Bytes extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing an amount of bytes"; + const DESCRIPTION = 'A value describing an amount of bytes'; - const EXAMPLE = "10kb, 250MB, 500GB, 2TB"; + const EXAMPLE = '10kb, 250MB, 500GB, 2TB'; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -34,9 +34,10 @@ class Bytes extends AbstractConstraint implements ConstraintInterface { * @suppress PhanUnusedPublicMethodParameter */ public static function filter($value, array $constraint, Constraint $dc) { - if (!preg_match('/^\d[\d,\.]*[kmgtp]b$/i', $value)) { + if (!preg_match('/^\\d[\\d,\\.]*[kmgtp]b$/i', $value)) { $value = null; } + return $value; } } diff --git a/src/Constraint/Currency.php b/src/Constraint/Currency.php index 88017fc..a306adc 100644 --- a/src/Constraint/Currency.php +++ b/src/Constraint/Currency.php @@ -16,11 +16,11 @@ */ class Currency extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing a US dollar amount"; + const DESCRIPTION = 'A value describing a US dollar amount'; - const EXAMPLE = "19.99, $50, $49.99, 99 cents"; + const EXAMPLE = '19.99, $50, $49.99, 99 cents'; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -34,16 +34,17 @@ class Currency extends AbstractConstraint implements ConstraintInterface { * @suppress PhanUnusedPublicMethodParameter */ public static function filter($value, array $constraint, Constraint $dc) { - if (preg_match('/^(\d{1,2}) cents$/', $value, $match)) { - $value = "0.".$match[1]; + if (preg_match('/^(\\d{1,2}) cents$/', $value, $match)) { + $value = '0.' . $match[1]; } else { - $value = preg_replace('/^\$/', '', $value); - $value = str_replace(",", "", $value); + $value = preg_replace('/^\\$/', '', $value); + $value = str_replace(',', '', $value); $value = filter_var($value, FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE); if ($value != null) { - $value = number_format($value, 2, ".", ""); + $value = number_format($value, 2, '.', ''); } } + return $value; } } diff --git a/src/Constraint/Date.php b/src/Constraint/Date.php index b87087d..dfe6465 100644 --- a/src/Constraint/Date.php +++ b/src/Constraint/Date.php @@ -16,11 +16,11 @@ */ class Date extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing an absolute or relative date"; + const DESCRIPTION = 'A value describing an absolute or relative date'; const EXAMPLE = "'2018-07-21', 'Sat, 21 Jul 2018', 'July 21, 2018', 'today', '-2 days'"; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -38,8 +38,9 @@ public static function filter($value, array $constraint, Constraint $dc) { if ($ts === false || $ts <= 0) { $value = null; } else { - $value = date("Y-m-d", $ts); + $value = date('Y-m-d', $ts); } + return $value; } } diff --git a/src/Constraint/DateTime.php b/src/Constraint/DateTime.php index d10e562..69d954d 100644 --- a/src/Constraint/DateTime.php +++ b/src/Constraint/DateTime.php @@ -16,11 +16,11 @@ */ class DateTime extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing an absolute or relative date and time"; + const DESCRIPTION = 'A value describing an absolute or relative date and time'; const EXAMPLE = "'2018-07-21T01:21:58-05:00', Sat, 21 Jul 2018 01:22:01 -0500', 2018-07-21 01:22:07', 'July 21, 2018 1:23am', 'now', '-2 hours'"; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -38,8 +38,9 @@ public static function filter($value, array $constraint, Constraint $dc) { if ($ts === false || $ts <= 0) { $value = null; } else { - $value = date("Y-m-d H:i:s", $ts); + $value = date('Y-m-d H:i:s', $ts); } + return $value; } } diff --git a/src/Constraint/Length.php b/src/Constraint/Length.php index 8242df3..1b74e62 100644 --- a/src/Constraint/Length.php +++ b/src/Constraint/Length.php @@ -16,11 +16,11 @@ */ class Length extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing a length, possibly in feet, inches, or a metric length"; + const DESCRIPTION = 'A value describing a length, possibly in feet, inches, or a metric length'; - const EXAMPLE = "15.1, 15.1\", 15.1in, 15.1-inch, 10cm, 10m, 10km"; + const EXAMPLE = '15.1, 15.1", 15.1in, 15.1-inch, 10cm, 10m, 10km'; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -34,13 +34,14 @@ class Length extends AbstractConstraint implements ConstraintInterface { * @suppress PhanUnusedPublicMethodParameter */ public static function filter($value, array $constraint, Constraint $dc) { - if (!preg_match("/^\d\d*\.?\d*(\"|'|-?foot|-?ft|-?inch|-?in|(m|c|k)*m)*$/i", $value)) { + if (!preg_match("/^\\d\\d*\\.?\\d*(\"|'|-?foot|-?ft|-?inch|-?in|(m|c|k)*m)*$/i", $value)) { $value = null; } else { - $value = preg_replace("/(-?foot|-?ft)/i", "'", $value); - $value = preg_replace("/(-?inch|-?in)/i", "\"", $value); - $value = strtolower($value); + $value = preg_replace('/(-?foot|-?ft)/i', "'", $value); + $value = preg_replace('/(-?inch|-?in)/i', '"', $value); + $value = mb_strtolower($value); } + return $value; } } diff --git a/src/Constraint/Range.php b/src/Constraint/Range.php index 915aac0..382d5f9 100644 --- a/src/Constraint/Range.php +++ b/src/Constraint/Range.php @@ -20,21 +20,21 @@ */ class Range extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A range query structure"; + const DESCRIPTION = 'A range query structure'; const EXAMPLE = "`['>', 5]`, `['between', 5, 10]`"; - const PRIMITIVE = "array"; + const PRIMITIVE = 'array'; const PRIMITIVE_IGNORED_PROPERTIES = ['constraint']; - protected static $operators = [ - "=", - "<", - ">", - ">=", - "<=", - "between" + const OPERATORS = [ + '=', + '<', + '>', + '>=', + '<=', + 'between', ]; public static function filter($value, array $constraint, Constraint $dc) { @@ -46,22 +46,23 @@ public static function filter($value, array $constraint, Constraint $dc) { * The third (key 2) is required for a between comparison and must not be null */ if ( - in_array($value[0], self::$operators) && - isset($value[1]) && + in_array($value[0], self::OPERATORS) && + isset($value[1]) && ( - $value[0] != "between" || + $value[0] != 'between' || (array_key_exists(2, $value) && isset($value[2])) ) ) { - if (isset($constraint["constraint"])) { - $value[1] = $dc->check($value[1], $constraint["constraint"]); + if (isset($constraint['constraint'])) { + $value[1] = $dc->check($value[1], $constraint['constraint']); if (array_key_exists(2, $value)) { - $value[2] = $dc->check($value[2], $constraint["constraint"]); + $value[2] = $dc->check($value[2], $constraint['constraint']); } } $return_value = $value; } + return $return_value; } } diff --git a/src/Constraint/Time.php b/src/Constraint/Time.php index dd5298b..1c3b984 100644 --- a/src/Constraint/Time.php +++ b/src/Constraint/Time.php @@ -16,11 +16,11 @@ */ class Time extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing an absolute or relative time"; + const DESCRIPTION = 'A value describing an absolute or relative time'; const EXAMPLE = "'01:21:58-05:00', '01:22:01 -0500', '1:23am', 'now', '-2 hours'"; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -38,8 +38,9 @@ public static function filter($value, array $constraint, Constraint $dc) { if ($ts === false || $ts <= 0) { $value = null; } else { - $value = date("H:i:s", $ts); + $value = date('H:i:s', $ts); } + return $value; } } diff --git a/src/Constraint/URL.php b/src/Constraint/URL.php index 138272a..26bd2dd 100644 --- a/src/Constraint/URL.php +++ b/src/Constraint/URL.php @@ -16,11 +16,11 @@ */ class URL extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A valid URL"; + const DESCRIPTION = 'A valid URL'; - const EXAMPLE = "https://www.dealnews.com/"; + const EXAMPLE = 'https://www.dealnews.com/'; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -38,6 +38,7 @@ public static function filter($value, array $constraint, Constraint $dc) { if (!filter_var($value, FILTER_VALIDATE_URL)) { $value = null; } + return $value; } } diff --git a/src/Constraint/URLPath.php b/src/Constraint/URLPath.php index 957c568..632ed86 100644 --- a/src/Constraint/URLPath.php +++ b/src/Constraint/URLPath.php @@ -18,9 +18,9 @@ class URLPath extends AbstractConstraint implements ConstraintInterface { const DESCRIPTION = "A valid URL path which begins with '/'"; - const EXAMPLE = "/categories/laptops/"; + const EXAMPLE = '/categories/laptops/'; - const PRIMITIVE = "string"; + const PRIMITIVE = 'string'; /** * Filter function for this abstract type @@ -36,12 +36,13 @@ class URLPath extends AbstractConstraint implements ConstraintInterface { public static function filter($value, array $constraint, Constraint $dc) { $value = trim($value); if ( - empty($value) || - $value[0] != "/" || - !filter_var("http://www.example.com".$value, FILTER_VALIDATE_URL) + empty($value) || + $value[0] != '/' || + !filter_var('http://www.example.com' . $value, FILTER_VALIDATE_URL) ) { $value = null; } + return $value; } } diff --git a/src/Constraint/Year.php b/src/Constraint/Year.php index 279c78c..fd439ea 100644 --- a/src/Constraint/Year.php +++ b/src/Constraint/Year.php @@ -16,11 +16,11 @@ */ class Year extends AbstractConstraint implements ConstraintInterface { - const DESCRIPTION = "A value describing a year between 1901 and 2155"; + const DESCRIPTION = 'A value describing a year between 1901 and 2155'; - const EXAMPLE = "1998, 2000, 2018"; + const EXAMPLE = '1998, 2000, 2018'; - const PRIMITIVE = "integer"; + const PRIMITIVE = 'integer'; /** * Filter function for this abstract type @@ -37,6 +37,7 @@ public static function filter($value, array $constraint, Constraint $dc) { if ($value < 1901 || $value > 2155) { $value = null; } + return $value; } } diff --git a/src/ConstraintException.php b/src/ConstraintException.php index 5698675..5e1c48c 100644 --- a/src/ConstraintException.php +++ b/src/ConstraintException.php @@ -19,14 +19,14 @@ class ConstraintException extends \UnexpectedValueException { * * @var string */ - protected $expected = ""; + protected $expected = ''; /** * A human friendly example of valid values * * @var string */ - protected $example = ""; + protected $example = ''; /** * Constructor @@ -37,7 +37,7 @@ class ConstraintException extends \UnexpectedValueException { * @param integer $code A unique code for this thrown exception * @param \Throwable|null $previous A previously thrown exception which was caught */ - public function __construct ($value, string $expected, string $example, int $code = 0, \Throwable $previous = null) { + public function __construct($value, string $expected, string $example, int $code = 0, \Throwable $previous = null) { if (!empty($expected)) { $this->expected = $expected; } @@ -46,16 +46,16 @@ public function __construct ($value, string $expected, string $example, int $cod $this->example = $example; } - $message = "Invalid value"; + $message = 'Invalid value'; if (is_scalar($value)) { - $message.= " ".$value; + $message .= ' ' . $value; } - $message.= ". Expected: $this->expected."; + $message .= ". Expected: $this->expected."; if (!empty($this->example)) { - $message.= " Example: $this->example"; + $message .= " Example: $this->example"; } parent::__construct($message, $code, $previous); @@ -66,7 +66,7 @@ public function __construct ($value, string $expected, string $example, int $cod * * @return string */ - public function getExpected (): string { + public function getExpected(): string { return $this->expected; } @@ -75,7 +75,7 @@ public function getExpected (): string { * * @return string */ - public function getExample (): string { + public function getExample(): string { return $this->example; } } diff --git a/tests/Constraint/BytesTest.php b/tests/Constraint/BytesTest.php index 3ac0364..078f41a 100644 --- a/tests/Constraint/BytesTest.php +++ b/tests/Constraint/BytesTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Bytes; class BytesTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,22 +27,21 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "1MB", - ["type" => "bytes"], - "1MB" + '1MB', + ['type' => 'bytes'], + '1MB', ], [ - "1kb", - ["type" => "bytes"], - "1kb" + '1kb', + ['type' => 'bytes'], + '1kb', ], [ 10, - ["type" => "bytes"], - null + ['type' => 'bytes'], + null, ], ]; } diff --git a/tests/Constraint/CurrencyTest.php b/tests/Constraint/CurrencyTest.php index 935cb3e..9924447 100644 --- a/tests/Constraint/CurrencyTest.php +++ b/tests/Constraint/CurrencyTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Currency; class CurrencyTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,27 +27,26 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "$1,000.00", - ["type" => "currency"], - "1000.00" + '$1,000.00', + ['type' => 'currency'], + '1000.00', ], [ 1000.00, - ["type" => "currency"], - "1000.00" + ['type' => 'currency'], + '1000.00', ], [ - "10 cents", - ["type" => "currency"], - "0.10" + '10 cents', + ['type' => 'currency'], + '0.10', ], [ - "10¢", - ["type" => "currency"], - null + '10¢', + ['type' => 'currency'], + null, ], ]; } diff --git a/tests/Constraint/DateTest.php b/tests/Constraint/DateTest.php index 6b6a1a2..f062ad8 100644 --- a/tests/Constraint/DateTest.php +++ b/tests/Constraint/DateTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Date; class DateTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,27 +27,26 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "now", - ["type" => "date"], - date("Y-m-d") + 'now', + ['type' => 'date'], + date('Y-m-d'), ], [ - "0000-00-00 00:00:00", - ["type" => "datetime"], - null + '0000-00-00 00:00:00', + ['type' => 'datetime'], + null, ], [ - "", - ["type" => "date"], - null + '', + ['type' => 'date'], + null, ], [ - "2018-01-01", - ["type" => "date"], - "2018-01-01" + '2018-01-01', + ['type' => 'date'], + '2018-01-01', ], ]; } diff --git a/tests/Constraint/DateTimeTest.php b/tests/Constraint/DateTimeTest.php index 653ae4f..469c3b9 100644 --- a/tests/Constraint/DateTimeTest.php +++ b/tests/Constraint/DateTimeTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\DateTime; class DateTimeTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,27 +27,26 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "midnight", - ["type" => "datetime"], - date("Y-m-d")." 00:00:00" + 'midnight', + ['type' => 'datetime'], + date('Y-m-d') . ' 00:00:00', ], [ - "0000-00-00 00:00:00", - ["type" => "datetime"], - null + '0000-00-00 00:00:00', + ['type' => 'datetime'], + null, ], [ - "", - ["type" => "datetime"], - null + '', + ['type' => 'datetime'], + null, ], [ - "2018-01-01", - ["type" => "datetime"], - "2018-01-01 00:00:00" + '2018-01-01', + ['type' => 'datetime'], + '2018-01-01 00:00:00', ], ]; } diff --git a/tests/Constraint/LengthTest.php b/tests/Constraint/LengthTest.php index 5df191b..d8b4098 100644 --- a/tests/Constraint/LengthTest.php +++ b/tests/Constraint/LengthTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Length; class LengthTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -32,67 +31,67 @@ public function constraintData() { return [ [ 15.1, - ["type" => "length"], - "15.1" + ['type' => 'length'], + '15.1', ], [ - "15.1\"", - ["type" => "length"], - "15.1\"" + '15.1"', + ['type' => 'length'], + '15.1"', ], [ - "15.1in", - ["type" => "length"], - "15.1\"" + '15.1in', + ['type' => 'length'], + '15.1"', ], [ - "15.1-inch", - ["type" => "length"], - "15.1\"" + '15.1-inch', + ['type' => 'length'], + '15.1"', ], [ - "15ft", - ["type" => "length"], + '15ft', + ['type' => 'length'], "15'", ], [ "15'", - ["type" => "length"], + ['type' => 'length'], "15'", ], [ - "15-foot", - ["type" => "length"], + '15-foot', + ['type' => 'length'], "15'", ], [ - "10cm", - ["type" => "length"], - "10cm", + '10cm', + ['type' => 'length'], + '10cm', ], [ - "10m", - ["type" => "length"], - "10m", + '10m', + ['type' => 'length'], + '10m', ], [ - "10km", - ["type" => "length"], - "10km", + '10km', + ['type' => 'length'], + '10km', ], [ - "10mm", - ["type" => "length"], - "10mm", + '10mm', + ['type' => 'length'], + '10mm', ], [ - "10 feet", - ["type" => "length"], + '10 feet', + ['type' => 'length'], null, ], [ - "10 miles", - ["type" => "length"], + '10 miles', + ['type' => 'length'], null, ], ]; diff --git a/tests/Constraint/RangeTest.php b/tests/Constraint/RangeTest.php index 0257c0d..ae6e771 100644 --- a/tests/Constraint/RangeTest.php +++ b/tests/Constraint/RangeTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Range; class RangeTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -30,87 +29,87 @@ public function testConstraint($value, $constraint, $expect) { public function constraintData() { $tests = []; - foreach (["=","<",">",">=","<="] as $operator) { + foreach (['=', '<', '>', '>=', '<='] as $operator) { $tests[] = [ [$operator, 1], [ - "type" => "range", - "constraint" => [ - "type" => "integer" - ] + 'type' => 'range', + 'constraint' => [ + 'type' => 'integer', + ], ], - [$operator, 1] + [$operator, 1], ]; } $tests[] = [ - ["between", 1, 10], + ['between', 1, 10], [ - "type" => "range", - "constraint" => [ - "type" => "integer" - ] + 'type' => 'range', + 'constraint' => [ + 'type' => 'integer', + ], ], - ["between", 1, 10], + ['between', 1, 10], ]; $tests[] = [ - [">", "midnight"], + ['>', 'midnight'], [ - "type" => "range", - "constraint" => [ - "type" => "datetime" - ] + 'type' => 'range', + 'constraint' => [ + 'type' => 'datetime', + ], ], - [">", date("Y-m-d")." 00:00:00"], + ['>', date('Y-m-d') . ' 00:00:00'], ]; $tests[] = [ - [">", null], + ['>', null], [ - "type" => "range" + 'type' => 'range', ], - null + null, ]; $tests[] = [ - ["between", 1], + ['between', 1], [ - "type" => "range" + 'type' => 'range', ], - null + null, ]; $tests[] = [ - ["between", 1, null], + ['between', 1, null], [ - "type" => "range" + 'type' => 'range', ], - null + null, ]; $tests[] = [ - ["gte", 1], + ['gte', 1], [ - "type" => "range" + 'type' => 'range', ], - null + null, ]; $tests[] = [ - ["=<", 1], + ['=<', 1], [ - "type" => "range" + 'type' => 'range', ], - null + null, ]; $tests[] = [ - ["=>", 1], + ['=>', 1], [ - "type" => "range" + 'type' => 'range', ], - null + null, ]; return $tests; diff --git a/tests/Constraint/TimeTest.php b/tests/Constraint/TimeTest.php index ac0f018..ec12853 100644 --- a/tests/Constraint/TimeTest.php +++ b/tests/Constraint/TimeTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Time; class TimeTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,37 +27,36 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "midnight", - ["type" => "time"], - "00:00:00" + 'midnight', + ['type' => 'time'], + '00:00:00', ], [ - "00:00:00", - ["type" => "time"], - "00:00:00" + '00:00:00', + ['type' => 'time'], + '00:00:00', ], [ - "3pm", - ["type" => "time"], - "15:00:00" + '3pm', + ['type' => 'time'], + '15:00:00', ], [ - "25:00:00", - ["type" => "time"], - null + '25:00:00', + ['type' => 'time'], + null, ], [ - "", - ["type" => "time"], - null + '', + ['type' => 'time'], + null, ], [ - "2018-01-01", - ["type" => "time"], - "00:00:00" + '2018-01-01', + ['type' => 'time'], + '00:00:00', ], ]; } diff --git a/tests/Constraint/URLPathTest.php b/tests/Constraint/URLPathTest.php index a187e88..dcc6b74 100644 --- a/tests/Constraint/URLPathTest.php +++ b/tests/Constraint/URLPathTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\URLPath; class URLPathTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,22 +27,21 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "http://www.example.com/", - ["type" => "url_path"], - null + 'http://www.example.com/', + ['type' => 'url_path'], + null, ], [ - " ", - ["type" => "url_path"], - null + ' ', + ['type' => 'url_path'], + null, ], [ - "/foo/bar", - ["type" => "url_path"], - "/foo/bar" + '/foo/bar', + ['type' => 'url_path'], + '/foo/bar', ], ]; } diff --git a/tests/Constraint/URLTest.php b/tests/Constraint/URLTest.php index 6c0db7e..0e5fb6c 100644 --- a/tests/Constraint/URLTest.php +++ b/tests/Constraint/URLTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\URL; class URLTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,22 +27,21 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "http://www.example.com/", - ["type" => "url"], - "http://www.example.com/" + 'http://www.example.com/', + ['type' => 'url'], + 'http://www.example.com/', ], [ - " ", - ["type" => "url"], - null + ' ', + ['type' => 'url'], + null, ], [ - "asdf", - ["type" => "url"], - null + 'asdf', + ['type' => 'url'], + null, ], ]; } diff --git a/tests/Constraint/YearTest.php b/tests/Constraint/YearTest.php index 3723d17..8e8bb27 100644 --- a/tests/Constraint/YearTest.php +++ b/tests/Constraint/YearTest.php @@ -6,7 +6,6 @@ use \DealNews\Constraints\Constraint\Year; class YearTest extends \PHPUnit\Framework\TestCase { - /** * @dataProvider constraintData */ @@ -28,27 +27,26 @@ public function testConstraint($value, $constraint, $expect) { } public function constraintData() { - return [ [ - "midnight", - ["type" => "year"], - null + 'midnight', + ['type' => 'year'], + null, ], [ - "1998", - ["type" => "year"], - 1998 + '1998', + ['type' => 'year'], + 1998, ], [ 1055, - ["type" => "year"], - null + ['type' => 'year'], + null, ], [ 2200, - ["type" => "year"], - null + ['type' => 'year'], + null, ], ]; } diff --git a/tests/ConstraintTest.php b/tests/ConstraintTest.php index 80c22a6..338505b 100644 --- a/tests/ConstraintTest.php +++ b/tests/ConstraintTest.php @@ -6,72 +6,63 @@ use \DealNews\Constraints\ConstraintException; class ConstraintTest extends \PHPUnit\Framework\TestCase { - - /** - * @dataProvider successData - */ - public function testSuccess($value, $constraint, $expect) { - $_SERVER["DN_DEBUG"] = true; - $dc = new Constraint(); - if (is_object($expect)) { - $this->assertEquals( - $expect, - $dc->check($value, $constraint) - ); - } else { - $this->assertSame( - $expect, - $dc->check($value, $constraint) - ); - } + public function testMultiByteStrings() { + $input = 'foobar😀'; + $dc = Constraint::init(); + $value = $dc->check( + $input, + [ + 'type' => 'string', + 'max' => 7, + ] + ); + $this->assertEquals($input, $value); } public function testExceptionMethods() { $dc = new ConstraintException( - "some value", - "expected", - "example" + 'some value', + 'expected', + 'example' ); $this->assertEquals( - "expected", + 'expected', $dc->getExpected() ); $this->assertEquals( - "example", + 'example', $dc->getExample() ); } /** * @dataProvider exceptionData - * @expectedException \DealNews\Constraints\ConstraintException */ public function testExceptions($value, $constraint) { - $dc = Constraint::init(); + $this->expectException(ConstraintException::class); + $dc = new Constraint(); $dc->check($value, $constraint); } - /** - * @expectedException \LogicException - */ public function testInvalidType() { + $this->expectException(\LogicException::class); $dc = new Constraint(); - $dc->check(0, ["type" => "foo"]); + $dc->check(0, ['type' => 'foo']); } public function testConstraintValidation() { $valid_constraint = [ - "type" => "string", - "default" => "", - "is_nullable" => false, - "read_only" => false, - "constraint" => [ - "type" => "integer" - ], - "min" => 0, - "max" => 10, - "allowed_values" => ["foo", "bar"], - "pattern" => "" + 'type' => 'string', + 'default' => '', + 'is_nullable' => false, + 'read_only' => false, + 'constraint' => [ + 'type' => 'integer', + ], + 'min' => 0, + 'max' => 10, + 'allowed_values' => ['foo', 'bar'], + 'pattern' => '', ]; $dc = new Constraint(); $this->assertTrue( @@ -79,213 +70,225 @@ public function testConstraintValidation() { ); } - /** - * @expectedException \LogicException - * @expectedExceptionCode 2 - */ public function testConstraintValidationExceptionTypes() { + $this->expectException(\LogicException::class); + $this->expectExceptionCode(2); $dc = new Constraint(); $this->assertTrue( - $dc->validateConstraint(["type" => 1]) + $dc->validateConstraint(['type' => 1]) ); } - /** - * @expectedException \LogicException - * @expectedExceptionCode 1 - */ public function testConstraintValidationExceptionKeys() { + $this->expectException(\LogicException::class); + $this->expectExceptionCode(1); $dc = new Constraint(); $this->assertTrue( - $dc->validateConstraint(["foo" => 1]) + $dc->validateConstraint(['foo' => 1]) ); } public function testConstraintValidationExtraValues() { - $dc = new Constraint(["foo" => 0]); + $dc = new Constraint(['foo' => 0]); $this->assertTrue( - $dc->validateConstraint(["foo" => 1]) + $dc->validateConstraint(['foo' => 1]) ); } - /** - * @expectedException \LogicException - * @expectedExceptionCode 2 - */ public function testConstraintValidationExceptionExtraKeys() { - $dc = new Constraint(["foo" => 0]); + $this->expectException(\LogicException::class); + $this->expectExceptionCode(2); + $dc = new Constraint(['foo' => 0]); $this->assertTrue( - $dc->validateConstraint(["foo" => ""]) + $dc->validateConstraint(['foo' => '']) ); } - public function successData() { + /** + * @dataProvider successData + */ + public function testSuccess($value, $constraint, $expect) { + $_SERVER['DN_DEBUG'] = true; + $dc = new Constraint(); + if (is_object($expect)) { + $this->assertEquals( + $expect, + $dc->check($value, $constraint) + ); + } else { + $this->assertSame( + $expect, + $dc->check($value, $constraint) + ); + } + } + public function successData() { $dt = new \DateTime(); return [ [ - "foo", - ["type" => "string"], - "foo" + 'foo', + ['type' => 'string'], + 'foo', ], [ - "foo", + 'foo', [ - "type" => "string", - "pattern" => '/^f/' + 'type' => 'string', + 'pattern' => '/^f/', ], - "foo" + 'foo', ], [ 1, - ["type" => "string"], - "1" + ['type' => 'string'], + '1', ], [ - "Yes", + 'Yes', [ - "type" => "string", - "allowed_values" => [ - "Yes", - "No" - ] + 'type' => 'string', + 'allowed_values' => [ + 'Yes', + 'No', + ], ], - "Yes" + 'Yes', ], [ - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', [ - "type" => "string", - "max" => 50, - "min" => 10 + 'type' => 'string', + 'max' => 50, + 'min' => 10, ], - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', ], [ 1, - ["type" => "integer"], - 1 + ['type' => 'integer'], + 1, ], [ 1, [ - "type" => "integer", - "min" => 0, - "max" => 10 + 'type' => 'integer', + 'min' => 0, + 'max' => 10, ], - 1 + 1, ], [ - "1", - ["type" => "integer"], - 1 + '1', + ['type' => 'integer'], + 1, ], [ 1, - ["type" => "double"], - 1.0 + ['type' => 'double'], + 1.0, ], [ - "1", - ["type" => "double"], - 1.0 + '1', + ['type' => 'double'], + 1.0, ], [ 1, [ - "type" => "double", - "min" => 0, - "max" => 10 + 'type' => 'double', + 'min' => 0, + 'max' => 10, ], - 1.0 + 1.0, ], [ - "1", - ["type" => "boolean"], - true + '1', + ['type' => 'boolean'], + true, ], [ true, - ["type" => "boolean"], - true + ['type' => 'boolean'], + true, ], [ - "true", - ["type" => "boolean"], - true + 'true', + ['type' => 'boolean'], + true, ], // Testing integration with the abstract types // Those types are tested in files of their own [ - "http://www.example.com/", - ["type" => "url"], - "http://www.example.com/" + 'http://www.example.com/', + ['type' => 'url'], + 'http://www.example.com/', ], // testing class checking [ $dt, - ["type" => "\DateTime"], - $dt + ['type' => "\DateTime"], + $dt, ], [ null, - ["type" => "\DateTime"], - null + ['type' => "\DateTime"], + null, ], // testing is_nullable and default [ null, [ - "type" => "string", - "pattern" => '/^f/', - "is_nullable" => true + 'type' => 'string', + 'pattern' => '/^f/', + 'is_nullable' => true, ], - null + null, ], [ null, [ - "type" => "string", - "pattern" => '/^f/', - "is_nullable" => false, - "default" => "foo" + 'type' => 'string', + 'pattern' => '/^f/', + 'is_nullable' => false, + 'default' => 'foo', ], - "foo" + 'foo', ], [ - "123", + '123', [ - "type" => "integer", - "read_only" => true + 'type' => 'integer', + 'read_only' => true, ], - "123" + '123', ], [ - new \ArrayObject(), + [1,2,3], [ - "type" => "array" + 'type' => 'array', + 'constraint' => [ + 'type' => 'integer', + ], ], - [] + [1,2,3] ], [ - [], + new \ArrayObject(), [ - "type" => "\ArrayObject" + 'type' => 'array', ], - new \ArrayObject + [], ], [ - [1,2], + [], [ - "type" => "array", - "constraint" => [ - "type" => "integer" - ] + 'type' => "\ArrayObject", ], - [1,2] + new \ArrayObject, ], ]; } @@ -295,123 +298,124 @@ public function exceptionData() { [ 1000, [ - "type" => "integer", - "max" => 100 - ] + 'type' => 'integer', + 'max' => 100, + ], ], [ - "foo", - ["type" => "integer"] + 'foo', + ['type' => 'integer'], ], [ 1, [ - "type" => "integer", - "min" => 5, - "max" => 10 - ] + 'type' => 'integer', + 'min' => 5, + 'max' => 10, + ], ], [ 100, [ - "type" => "integer", - "min" => 5, - "max" => 10 - ] + 'type' => 'integer', + 'min' => 5, + 'max' => 10, + ], ], [ - "1,000", - ["type" => "double"] + '1,000', + ['type' => 'double'], ], [ 1, [ - "type" => "double", - "min" => 5, - "max" => 10 - ] + 'type' => 'double', + 'min' => 5, + 'max' => 10, + ], ], [ 100, [ - "type" => "double", - "min" => 5, - "max" => 10 - ] + 'type' => 'double', + 'min' => 5, + 'max' => 10, + ], ], [ [], - ["type" => "string"] + ['type' => 'string'], ], [ - "Bob", + 'Bob', [ - "type" => "string", - "allowed_values" => [ - "Yes", - "No" - ] - ] + 'type' => 'string', + 'allowed_values' => [ + 'Yes', + 'No', + ], + ], ], [ - "bar", + 'bar', [ - "type" => "string", - "pattern" => '/^f/' - ] + 'type' => 'string', + 'pattern' => '/^f/', + ], ], [ - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', [ - "type" => "string", - "max" => 10 - ] + 'type' => 'string', + 'max' => 10, + ], ], [ - "", + '', [ - "type" => "string", - "min" => 10 - ] + 'type' => 'string', + 'min' => 10, + ], ], [ 1, - ["type" => "array"] + ['type' => 'array'], ], [ - "Maybe", - ["type" => "boolean"] + 'Maybe', + ['type' => 'boolean'], ], // Testing integration with the abstract types // Those types are tested in files of their own [ - "asdf", - ["type" => "url"] + 'asdf', + ['type' => 'url'], ], // testing class checking [ - "foo", - ["type" => "\DateTime"] + 'foo', + ['type' => "\DateTime"], ], // testing is_nullable and missing default [ null, [ - "type" => "string", - "pattern" => '/^f/', - "is_nullable" => false, + 'type' => 'string', + 'pattern' => '/^f/', + 'is_nullable' => false, ], - "" + '', ], - [ // testing that sub constraints are processed for array types - ['foo'], + [ + [[1],2,3], [ - "type" => "array", - "constraint" => [ - 'type' => 'integer' - ] + 'type' => 'array', + 'constraint' => [ + 'type' => 'integer', + ], ] ], + ]; } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0ecc16b..d21c14d 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,3 +1,3 @@