From 55740b3d24f8052f3a35c39e940ea6cc3ba80d66 Mon Sep 17 00:00:00 2001 From: TuningYourCode Date: Fri, 10 Aug 2018 15:00:39 +0200 Subject: [PATCH 01/19] Add EnumType #19 (#20) * Add EnumType #19 * Remove unsupported hhvm; Add php7.2; Update Readme.md --- .travis.yml | 2 +- README.md | 1 + spec/Type/EnumTypeSpec.php | 35 +++++++++++++++++++++++++++++ src/Type/DatetimeType.php | 2 +- src/Type/EnumType.php | 44 +++++++++++++++++++++++++++++++++++++ src/Type/ExactValueType.php | 2 +- src/Type/NumericType.php | 2 +- src/Type/RegexType.php | 2 +- 8 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 spec/Type/EnumTypeSpec.php create mode 100644 src/Type/EnumType.php diff --git a/.travis.yml b/.travis.yml index 1727505..a357894 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,9 @@ language: php matrix: include: - php: 5.6 - - php: hhvm - php: 7.0 - php: 7.1 + - php: 7.2 - php: nightly allow_failures: - php: nightly diff --git a/README.md b/README.md index 4bcb02c..aa40ce3 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Currently the following types are supported: * Datetime * Regex * Optional + * Enum There are some open issues with ideas for more types. Feel free to send pull requests. diff --git a/spec/Type/EnumTypeSpec.php b/spec/Type/EnumTypeSpec.php new file mode 100644 index 0000000..6eb4419 --- /dev/null +++ b/spec/Type/EnumTypeSpec.php @@ -0,0 +1,35 @@ +beConstructedWith(['test', 1, null]); + + $this->shouldHaveType(EnumType::class); + } + + function it_is_valid_for_all_allowed_values() + { + $this->beConstructedWith(['test', 1, null]); + + $this->check('test')->isValid()->shouldBe(true); + $this->check(1)->isValid()->shouldBe(true); + $this->check(null)->isValid()->shouldBe(true); + } + + function it_is_invalid_for_not_allowed_values() + { + $this->beConstructedWith(['test', 1, null]); + + $this->check('array')->isValid()->shouldBe(false); + $this->check(100)->isValid()->shouldBe(false); + $this->check(1.5)->isValid()->shouldBe(false); + $this->check(['test'])->isValid()->shouldBe(false); + } +} diff --git a/src/Type/DatetimeType.php b/src/Type/DatetimeType.php index 6271283..8994037 100644 --- a/src/Type/DatetimeType.php +++ b/src/Type/DatetimeType.php @@ -11,7 +11,7 @@ * Class DatetimeType * @package StructureCheck\Type */ -class DatetimeType +class DatetimeType implements TypeInterface { /** * @var string diff --git a/src/Type/EnumType.php b/src/Type/EnumType.php new file mode 100644 index 0000000..fede008 --- /dev/null +++ b/src/Type/EnumType.php @@ -0,0 +1,44 @@ +values = $values; + } + + /** + * @param mixed $value + * + * @return ResultInterface + */ + public function check($value) + { + $checkResult = in_array($value, $this->values, true); + + return new Result( + $checkResult, + !$checkResult ? [sprintf(self::$errorMessage, json_encode($value), implode(',', $this->values))] : [] + ); + } +} diff --git a/src/Type/ExactValueType.php b/src/Type/ExactValueType.php index ae72087..ddd5554 100644 --- a/src/Type/ExactValueType.php +++ b/src/Type/ExactValueType.php @@ -5,7 +5,7 @@ use StructureCheck\Result; use StructureCheck\ResultInterface; -class ExactValueType +class ExactValueType implements TypeInterface { /** diff --git a/src/Type/NumericType.php b/src/Type/NumericType.php index 7cc1c56..fd15db5 100644 --- a/src/Type/NumericType.php +++ b/src/Type/NumericType.php @@ -5,7 +5,7 @@ use StructureCheck\Result; use StructureCheck\ResultInterface; -class NumericType +class NumericType implements TypeInterface { private static $errorMessage = 'The value %s is not a numeric value.'; diff --git a/src/Type/RegexType.php b/src/Type/RegexType.php index fe033c8..c79e45d 100644 --- a/src/Type/RegexType.php +++ b/src/Type/RegexType.php @@ -9,7 +9,7 @@ * Class RegexType * @package StructureCheck\Type */ -class RegexType +class RegexType implements TypeInterface { /** * @var string From aadcfd7d913fc286c145c9d2011f20539304b32d Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Mon, 18 Mar 2019 17:13:00 +0100 Subject: [PATCH 02/19] Update PHP version support and move package to new space --- .travis.yml | 7 ++----- composer.json | 21 ++++++++++++++------- src/Type/ExactValueType.php | 3 +++ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index a357894..ba5c4df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,9 @@ language: php matrix: include: - - php: 5.6 - - php: 7.0 - php: 7.1 - php: 7.2 - - php: nightly + - php: 7.3 allow_failures: - php: nightly fast_finish: true @@ -18,5 +16,4 @@ install: - composer install script: - - vendor/bin/phpspec run --no-interaction - - vendor/bin/phpunit tests + - composer run check diff --git a/composer.json b/composer.json index 22fe000..a56d18a 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,27 @@ { - "name": "1blankz7/php-structure-check", - "description": "Structural check of arrays for PHP 5.6+", + "name": "cubicl/php-structure-check", + "description": "Structural check of arrays for PHP 7.1+", "keywords": ["array", "structure", "types"], - "homepage": "https://github.com/1blankz7/php-structure-check", + "homepage": "https://github.com/cubicldev/php-structure-check", "type": "library", "license": "MIT", "authors": [ { "name": "Christian Blank", - "email": "mail@cblank.de", - "homepage": "http://cblank.de" + "email": "christian@cubicl.de", + "homepage": "https://cubicl.de" } ], + "scripts": { + "check": ["@analyze", "@tests", "@tests-spec"], + "tests": "phpunit tests", + "analyze": "phpstan analyse --level 0 src", + "tests-spec": "phpspec run --no-interaction" + }, "require-dev": { - "phpspec/phpspec": "^3.2", - "phpunit/phpunit": "^5.6" + "phpspec/phpspec": "^5.1.0", + "phpunit/phpunit": "^7", + "phpstan/phpstan": "^0.11.4" }, "autoload": { "psr-4": { diff --git a/src/Type/ExactValueType.php b/src/Type/ExactValueType.php index ddd5554..fbdfd07 100644 --- a/src/Type/ExactValueType.php +++ b/src/Type/ExactValueType.php @@ -13,6 +13,9 @@ class ExactValueType implements TypeInterface */ private static $errorMessage = 'The value %s is not the same value as %s.'; + /** @var mixed */ + private $value; + /** * ExactValueType constructor. * From 42ad6dd4377b0f861bdb079f56b2a8c452da20c8 Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Thu, 21 Mar 2019 13:48:32 +0100 Subject: [PATCH 03/19] Fix broken links in readme --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aa40ce3..8d1dee0 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ PHP Structure Check =================== -[![Build Status](https://travis-ci.org/1blankz7/php-structure-check.svg?branch=master)](https://travis-ci.org/1blankz7/php-structure-check) -[![Latest Stable Version](https://poser.pugx.org/1blankz7/php-structure-check/v/stable)](https://packagist.org/packages/1blankz7/php-structure-check) -[![Total Downloads](https://poser.pugx.org/1blankz7/php-structure-check/downloads)](https://packagist.org/packages/1blankz7/php-structure-check) -[![License](https://poser.pugx.org/1blankz7/php-structure-check/license)](https://packagist.org/packages/1blankz7/php-structure-check) +[![Build Status](https://travis-ci.org/CubiclDev/php-structure-check.svg?branch=master)](https://travis-ci.org/CubiclDev/php-structure-check) +[![License](https://poser.pugx.org/cubicl/php-structure-check/license)](https://packagist.org/packages/cubicl/php-structure-check) This library can check a complex array structure against a given requirement. The purpose of this library is to create a better experience when testing a result set from an api or something similar. From eaffa5be0152eab4cc55a16ca53bffe21e5724a5 Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Thu, 21 Mar 2019 14:04:42 +0100 Subject: [PATCH 04/19] Move namespace --- composer.json | 4 ++-- phpspec.yml | 4 ++-- spec/Check/CountCheckSpec.php | 8 ++++---- spec/Check/NumericRangeCheckSpec.php | 8 ++++---- spec/CheckerSpec.php | 8 ++++---- spec/ResultSpec.php | 4 ++-- spec/Type/AnyTypeSpec.php | 4 ++-- spec/Type/BoolTypeSpec.php | 4 ++-- spec/Type/DatetimeTypeSpec.php | 4 ++-- spec/Type/EnumTypeSpec.php | 4 ++-- spec/Type/ExactValueTypeSpec.php | 4 ++-- spec/Type/FloatTypeSpec.php | 4 ++-- spec/Type/IntTypeSpec.php | 4 ++-- spec/Type/ListTypeSpec.php | 6 +++--- spec/Type/NullableTypeSpec.php | 8 ++++---- spec/Type/NumericTypeSpec.php | 4 ++-- spec/Type/ObjectTypeSpec.php | 6 +++--- spec/Type/OptionalTypeSpec.php | 8 ++++---- spec/Type/RegexTypeSpec.php | 4 ++-- spec/Type/StringTypeSpec.php | 4 ++-- src/Check/CountCheck.php | 8 ++++---- src/Check/NumericRangeCheck.php | 8 ++++---- src/Checker.php | 6 +++--- src/CheckerInterface.php | 6 +++--- src/Result.php | 4 ++-- src/ResultInterface.php | 4 ++-- src/Type/AnyType.php | 6 +++--- src/Type/BoolType.php | 8 ++++---- src/Type/DatetimeType.php | 8 ++++---- src/Type/EnumType.php | 6 +++--- src/Type/ExactValueType.php | 6 +++--- src/Type/FloatType.php | 4 ++-- src/Type/IntType.php | 8 ++++---- src/Type/ListType.php | 6 +++--- src/Type/NullableType.php | 6 +++--- src/Type/NumericType.php | 6 +++--- src/Type/ObjectType.php | 4 ++-- src/Type/OptionalType.php | 6 +++--- src/Type/RegexType.php | 8 ++++---- src/Type/StringType.php | 8 ++++---- src/Type/TypeInterface.php | 6 +++--- tests/Integration/Type/ObjectTypeTest.php | 14 +++++++------- 42 files changed, 125 insertions(+), 125 deletions(-) diff --git a/composer.json b/composer.json index a56d18a..1477424 100644 --- a/composer.json +++ b/composer.json @@ -25,10 +25,10 @@ }, "autoload": { "psr-4": { - "StructureCheck\\": [ + "Cubicl\\StructureCheck\\": [ "src" ], - "StructureCheck\\Test\\": [ + "Cubicl\\StructureCheck\\Test\\": [ "tests" ] } diff --git a/phpspec.yml b/phpspec.yml index 2a4150f..42b140e 100644 --- a/phpspec.yml +++ b/phpspec.yml @@ -1,4 +1,4 @@ suites: structure_check_suite: - namespace: StructureCheck - psr4_prefix: StructureCheck \ No newline at end of file + namespace: Cubicl\StructureCheck + psr4_prefix: Cubicl\StructureCheck \ No newline at end of file diff --git a/spec/Check/CountCheckSpec.php b/spec/Check/CountCheckSpec.php index e1c08c3..2dc068a 100644 --- a/spec/Check/CountCheckSpec.php +++ b/spec/Check/CountCheckSpec.php @@ -1,12 +1,12 @@ */ class OptionalType implements TypeInterface diff --git a/src/Type/RegexType.php b/src/Type/RegexType.php index c79e45d..6fb2888 100644 --- a/src/Type/RegexType.php +++ b/src/Type/RegexType.php @@ -1,13 +1,13 @@ */ class ObjectTypeTest extends TestCase From 4cd985408354d88748cbcc11a62052b005628ebd Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Thu, 21 Mar 2019 14:09:47 +0100 Subject: [PATCH 05/19] Update phpstan level and fix issue --- composer.json | 7 +++++-- src/Type/ListType.php | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 1477424..98f08f6 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "scripts": { "check": ["@analyze", "@tests", "@tests-spec"], "tests": "phpunit tests", - "analyze": "phpstan analyse --level 0 src", + "analyze": "phpstan analyse --level max src", "tests-spec": "phpspec run --no-interaction" }, "require-dev": { @@ -32,5 +32,8 @@ "tests" ] } - } + }, + "require": { + "ext-json": "*" + } } diff --git a/src/Type/ListType.php b/src/Type/ListType.php index 190e261..6d92ba7 100644 --- a/src/Type/ListType.php +++ b/src/Type/ListType.php @@ -13,7 +13,7 @@ class ListType implements TypeInterface private static $isNotAnArrayMessage = 'The given value %s is not an array.'; /** - * @var TypeInterface[] + * @var TypeInterface */ private $child; From e96891eaab34a0e816a251bffd50e6945d170145 Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Thu, 21 Mar 2019 14:11:06 +0100 Subject: [PATCH 06/19] Correct package name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d1dee0..14bee5e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The purpose of this library is to create a better experience when testing a resu ## Installation ``` -composer require 1blankz7/php-structure-check +composer require cubicl/php-structure-check ``` ## Usage From 528c054971277fe3ad9fb0a818dc8bce0c8e348a Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Sat, 26 Oct 2019 15:42:59 +0200 Subject: [PATCH 07/19] [#11] Add error object (#21) * [#11] Add error object * [#11] Remove composer lock again --- spec/Check/CountCheckSpec.php | 8 ++--- spec/Check/NumericRangeCheckSpec.php | 8 ++--- spec/CheckerSpec.php | 5 +-- spec/ResultSpec.php | 2 +- spec/Type/AnyTypeSpec.php | 16 +++++----- spec/Type/BoolTypeSpec.php | 14 ++++---- spec/Type/DatetimeTypeSpec.php | 14 ++++---- spec/Type/EnumTypeSpec.php | 16 +++++----- spec/Type/ExactValueTypeSpec.php | 2 +- spec/Type/FloatTypeSpec.php | 20 ++++++------ spec/Type/IntTypeSpec.php | 20 ++++++------ spec/Type/NullableTypeSpec.php | 6 ++-- spec/Type/NumericTypeSpec.php | 26 +++++++-------- spec/Type/OptionalTypeSpec.php | 4 +-- spec/Type/RegexTypeSpec.php | 14 ++++---- spec/Type/StringTypeSpec.php | 16 +++++----- src/Check/CountCheck.php | 37 +++++++-------------- src/Check/NumericRangeCheck.php | 36 +++++++-------------- src/Checker.php | 12 ++----- src/CheckerInterface.php | 9 ++---- src/Error.php | 26 +++++++++++++++ src/ErrorInterface.php | 10 ++++++ src/Result.php | 31 ++++++++++++------ src/ResultInterface.php | 10 +++--- src/Type/AnyType.php | 7 ++-- src/Type/BoolType.php | 21 ++++-------- src/Type/DatetimeType.php | 39 ++++++----------------- src/Type/EnumType.php | 26 +++++++-------- src/Type/ExactValueType.php | 18 ++++------- src/Type/FloatType.php | 16 ++++------ src/Type/IntType.php | 21 ++++-------- src/Type/ListType.php | 30 +++++++---------- src/Type/NullableType.php | 24 ++++---------- src/Type/NumericType.php | 15 +++------ src/Type/ObjectType.php | 16 +++++----- src/Type/OptionalType.php | 23 ++----------- src/Type/RegexType.php | 28 +++++----------- src/Type/StringType.php | 21 ++++-------- src/Type/TypeInterface.php | 7 ++-- tests/Integration/Type/ObjectTypeTest.php | 8 ++--- 40 files changed, 292 insertions(+), 390 deletions(-) create mode 100644 src/Error.php create mode 100644 src/ErrorInterface.php diff --git a/spec/Check/CountCheckSpec.php b/spec/Check/CountCheckSpec.php index 2dc068a..dd36f12 100644 --- a/spec/Check/CountCheckSpec.php +++ b/spec/Check/CountCheckSpec.php @@ -27,20 +27,20 @@ function it_implements_type_interface(TypeInterface $child) function it_returns_a_result_on_invalid_child_check(TypeInterface $child, ResultInterface $result) { $result->isValid()->willReturn(false); - $child->check(Argument::any())->willReturn($result); + $child->check('', Argument::any())->willReturn($result); $this->beConstructedWith($child, 1); - $this->check([])->shouldHaveType(ResultInterface::class); + $this->check('', [])->shouldHaveType(ResultInterface::class); } function it_returns_a_result_on_check(TypeInterface $child, ResultInterface $result) { $result->isValid()->willReturn(true); - $child->check(Argument::any())->willReturn($result); + $child->check('', Argument::any())->willReturn($result); $this->beConstructedWith($child, 1); - $this->check([3])->shouldHaveType(ResultInterface::class); + $this->check('', [3])->shouldHaveType(ResultInterface::class); } } diff --git a/spec/Check/NumericRangeCheckSpec.php b/spec/Check/NumericRangeCheckSpec.php index 25f72f1..ff38e28 100644 --- a/spec/Check/NumericRangeCheckSpec.php +++ b/spec/Check/NumericRangeCheckSpec.php @@ -28,20 +28,20 @@ function it_implements_type_interface(TypeInterface $child) function it_returns_a_result_on_invalid_child_check(TypeInterface $child, ResultInterface $result) { $result->isValid()->willReturn(false); - $child->check(Argument::any())->willReturn($result); + $child->check('', Argument::any())->willReturn($result); $this->beConstructedWith($child, 0, 1); - $this->check(Argument::any())->shouldHaveType(ResultInterface::class); + $this->check('', Argument::any())->shouldHaveType(ResultInterface::class); } function it_returns_a_result_on_check(TypeInterface $child, ResultInterface $result) { $result->isValid()->willReturn(true); - $child->check(Argument::any())->willReturn($result); + $child->check('', Argument::any())->willReturn($result); $this->beConstructedWith($child, 0, 1); - $this->check(0)->shouldHaveType(ResultInterface::class); + $this->check('', 0)->shouldHaveType(ResultInterface::class); } } diff --git a/spec/CheckerSpec.php b/spec/CheckerSpec.php index 73b3340..548ec51 100644 --- a/spec/CheckerSpec.php +++ b/spec/CheckerSpec.php @@ -14,14 +14,15 @@ function it_is_initializable() $this->shouldHaveType(Checker::class); } - function it_accepts_a_type_and_an_array_as_parameter_for_fulfills(TypeInterface $type) + function it_accepts_a_type_and_an_array_as_parameter_for_fulfills(TypeInterface $type, ResultInterface $result) { + $type->check('', [])->willReturn($result); $this->fulfills([], $type); } function it_returns_the_result_of_the_type_in_fulfills(TypeInterface $type, ResultInterface $result) { - $type->check([])->willReturn($result); + $type->check('', [])->willReturn($result); $this->fulfills([], $type)->shouldBe($result); } } diff --git a/spec/ResultSpec.php b/spec/ResultSpec.php index d56c5ab..5817098 100644 --- a/spec/ResultSpec.php +++ b/spec/ResultSpec.php @@ -28,7 +28,7 @@ function it_will_return_is_invalid_if_it_was_set_in_constructor() function it_will_return_an_empty_array_if_no_error_list_is_given() { - $this->beConstructedWith(true); + $this->beConstructedWith(true, []); $this->getErrors()->shouldHaveCount(0); } } diff --git a/spec/Type/AnyTypeSpec.php b/spec/Type/AnyTypeSpec.php index a6d7327..422935d 100644 --- a/spec/Type/AnyTypeSpec.php +++ b/spec/Type/AnyTypeSpec.php @@ -15,25 +15,25 @@ function it_is_initializable() function it_should_return_valid_for_null() { - $this->check(null)->isValid()->shouldBe(true); + $this->check('', null)->isValid()->shouldBe(true); } function it_should_return_empty_errors_for_null() { - $this->check(null)->getErrors()->shouldHaveCount(0); + $this->check('', null)->getErrors()->shouldHaveCount(0); } function it_should_return_valid_for_all_values() { - $this->check(true)->isValid()->shouldBe(true); - $this->check("foo")->isValid()->shouldBe(true); - $this->check(13)->isValid()->shouldBe(true); + $this->check('', true)->isValid()->shouldBe(true); + $this->check('', "foo")->isValid()->shouldBe(true); + $this->check('', 13)->isValid()->shouldBe(true); } function it_should_return_empty_errors_for_all_values() { - $this->check(true)->getErrors()->shouldHaveCount(0); - $this->check("foo")->getErrors()->shouldHaveCount(0); - $this->check(13)->getErrors()->shouldHaveCount(0); + $this->check('', true)->getErrors()->shouldHaveCount(0); + $this->check('', "foo")->getErrors()->shouldHaveCount(0); + $this->check('', 13)->getErrors()->shouldHaveCount(0); } } diff --git a/spec/Type/BoolTypeSpec.php b/spec/Type/BoolTypeSpec.php index 30fc953..6a81345 100644 --- a/spec/Type/BoolTypeSpec.php +++ b/spec/Type/BoolTypeSpec.php @@ -15,16 +15,16 @@ function it_is_initializable() function it_should_return_valid_for_bool() { - $this->check(true)->isValid()->shouldBe(true); - $this->check(false)->isValid()->shouldBe(true); + $this->check('', true)->isValid()->shouldBe(true); + $this->check('', false)->isValid()->shouldBe(true); } function it_should_return_invalid_for_others() { - $this->check(null)->isValid()->shouldBe(false); - $this->check("foo")->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(1)->isValid()->shouldBe(false); - $this->check(1.0)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', "foo")->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', 1)->isValid()->shouldBe(false); + $this->check('', 1.0)->isValid()->shouldBe(false); } } diff --git a/spec/Type/DatetimeTypeSpec.php b/spec/Type/DatetimeTypeSpec.php index 177c5b8..b54efd7 100644 --- a/spec/Type/DatetimeTypeSpec.php +++ b/spec/Type/DatetimeTypeSpec.php @@ -18,18 +18,18 @@ function it_should_return_valid_for_correct_values() { $this->beConstructedWith('d-m-Y h:m:s', 'Europe/Berlin'); - $this->check('12-12-2012 12:12:10')->isValid()->shouldBe(true); + $this->check('', '12-12-2012 12:12:10')->isValid()->shouldBe(true); } function it_should_return_invalid_for_others() { $this->beConstructedWith('d-m-Y h:m:s', 'Europe/Berlin'); - $this->check(null)->isValid()->shouldBe(false); - $this->check('foo')->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(1.234)->isValid()->shouldBe(false); - $this->check(true)->isValid()->shouldBe(false); - $this->check(false)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', 'foo')->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', 1.234)->isValid()->shouldBe(false); + $this->check('', true)->isValid()->shouldBe(false); + $this->check('', false)->isValid()->shouldBe(false); } } diff --git a/spec/Type/EnumTypeSpec.php b/spec/Type/EnumTypeSpec.php index 73e7436..36cc405 100644 --- a/spec/Type/EnumTypeSpec.php +++ b/spec/Type/EnumTypeSpec.php @@ -18,18 +18,18 @@ function it_is_valid_for_all_allowed_values() { $this->beConstructedWith(['test', 1, null]); - $this->check('test')->isValid()->shouldBe(true); - $this->check(1)->isValid()->shouldBe(true); - $this->check(null)->isValid()->shouldBe(true); + $this->check('', 'test')->isValid()->shouldBe(true); + $this->check('', 1)->isValid()->shouldBe(true); + $this->check('', null)->isValid()->shouldBe(true); } function it_is_invalid_for_not_allowed_values() { $this->beConstructedWith(['test', 1, null]); - - $this->check('array')->isValid()->shouldBe(false); - $this->check(100)->isValid()->shouldBe(false); - $this->check(1.5)->isValid()->shouldBe(false); - $this->check(['test'])->isValid()->shouldBe(false); + + $this->check('', 'array')->isValid()->shouldBe(false); + $this->check('', 100)->isValid()->shouldBe(false); + $this->check('', 1.5)->isValid()->shouldBe(false); + $this->check('', ['test'])->isValid()->shouldBe(false); } } diff --git a/spec/Type/ExactValueTypeSpec.php b/spec/Type/ExactValueTypeSpec.php index f88dc8c..e6ebeae 100644 --- a/spec/Type/ExactValueTypeSpec.php +++ b/spec/Type/ExactValueTypeSpec.php @@ -17,6 +17,6 @@ function it_is_initializable() function it_is_valid_for_null_if_null_is_the_value() { $this->beConstructedWith(null); - $this->check(null)->isValid()->shouldBe(true); + $this->check('', null)->isValid()->shouldBe(true); } } diff --git a/spec/Type/FloatTypeSpec.php b/spec/Type/FloatTypeSpec.php index 48e6dd1..2df6598 100644 --- a/spec/Type/FloatTypeSpec.php +++ b/spec/Type/FloatTypeSpec.php @@ -14,19 +14,19 @@ function it_is_initializable() function it_should_return_valid_for_floats() { - $this->check(0.0)->isValid()->shouldBe(true); - $this->check(1.1)->isValid()->shouldBe(true); - $this->check(2.0)->isValid()->shouldBe(true); - $this->check(-144.2)->isValid()->shouldBe(true); + $this->check('', 0.0)->isValid()->shouldBe(true); + $this->check('', 1.1)->isValid()->shouldBe(true); + $this->check('', 2.0)->isValid()->shouldBe(true); + $this->check('', -144.2)->isValid()->shouldBe(true); } function it_should_return_invalid_for_others() { - $this->check(null)->isValid()->shouldBe(false); - $this->check("foo")->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(1)->isValid()->shouldBe(false); - $this->check(true)->isValid()->shouldBe(false); - $this->check(false)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', "foo")->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', 1)->isValid()->shouldBe(false); + $this->check('', true)->isValid()->shouldBe(false); + $this->check('', false)->isValid()->shouldBe(false); } } diff --git a/spec/Type/IntTypeSpec.php b/spec/Type/IntTypeSpec.php index cb8eaf1..c710003 100644 --- a/spec/Type/IntTypeSpec.php +++ b/spec/Type/IntTypeSpec.php @@ -15,19 +15,19 @@ function it_is_initializable() function it_should_return_valid_for_integers() { - $this->check(0)->isValid()->shouldBe(true); - $this->check(1)->isValid()->shouldBe(true); - $this->check(20)->isValid()->shouldBe(true); - $this->check(-144)->isValid()->shouldBe(true); + $this->check('', 0)->isValid()->shouldBe(true); + $this->check('', 1)->isValid()->shouldBe(true); + $this->check('', 20)->isValid()->shouldBe(true); + $this->check('', -144)->isValid()->shouldBe(true); } function it_should_return_invalid_for_others() { - $this->check(null)->isValid()->shouldBe(false); - $this->check("foo")->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(1.234)->isValid()->shouldBe(false); - $this->check(true)->isValid()->shouldBe(false); - $this->check(false)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', "foo")->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', 1.234)->isValid()->shouldBe(false); + $this->check('', true)->isValid()->shouldBe(false); + $this->check('', false)->isValid()->shouldBe(false); } } diff --git a/spec/Type/NullableTypeSpec.php b/spec/Type/NullableTypeSpec.php index 13bc912..0d68924 100644 --- a/spec/Type/NullableTypeSpec.php +++ b/spec/Type/NullableTypeSpec.php @@ -17,12 +17,12 @@ function it_is_initializable(TypeInterface $childType) function it_should_return_valid_for_null(TypeInterface $childType) { $this->beConstructedWith($childType); - $this->check(null)->isValid()->shouldBe(true); + $this->check('', null)->isValid()->shouldBe(true); } function it_should_return_the_value_from_the_child(TypeInterface $childType) { $this->beConstructedWith($childType); - $childType->check(false)->willReturn(new Result(false, [])); - $this->check(false)->isValid()->shouldBe(false); + $childType->check('', false)->willReturn(new Result(false, [])); + $this->check('', false)->isValid()->shouldBe(false); } } diff --git a/spec/Type/NumericTypeSpec.php b/spec/Type/NumericTypeSpec.php index 8cb7af4..b3cfc29 100644 --- a/spec/Type/NumericTypeSpec.php +++ b/spec/Type/NumericTypeSpec.php @@ -15,26 +15,26 @@ function it_is_initializable() function it_should_return_valid_for_integers() { - $this->check(0)->isValid()->shouldBe(true); - $this->check(1)->isValid()->shouldBe(true); - $this->check(20)->isValid()->shouldBe(true); - $this->check(-144)->isValid()->shouldBe(true); + $this->check('', 0)->isValid()->shouldBe(true); + $this->check('', 1)->isValid()->shouldBe(true); + $this->check('', 20)->isValid()->shouldBe(true); + $this->check('', -144)->isValid()->shouldBe(true); } function it_should_return_valid_for_floats() { - $this->check(0.0)->isValid()->shouldBe(true); - $this->check(1.1235)->isValid()->shouldBe(true); - $this->check(-0.00001)->isValid()->shouldBe(true); - $this->check(-144.12313131313)->isValid()->shouldBe(true); + $this->check('', 0.0)->isValid()->shouldBe(true); + $this->check('', 1.1235)->isValid()->shouldBe(true); + $this->check('', -0.00001)->isValid()->shouldBe(true); + $this->check('', -144.12313131313)->isValid()->shouldBe(true); } function it_should_return_invalid_for_others() { - $this->check(null)->isValid()->shouldBe(false); - $this->check("foo")->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(true)->isValid()->shouldBe(false); - $this->check(false)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', "foo")->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', true)->isValid()->shouldBe(false); + $this->check('', false)->isValid()->shouldBe(false); } } diff --git a/spec/Type/OptionalTypeSpec.php b/spec/Type/OptionalTypeSpec.php index 5e3f6a8..61f4a38 100644 --- a/spec/Type/OptionalTypeSpec.php +++ b/spec/Type/OptionalTypeSpec.php @@ -17,7 +17,7 @@ function it_is_initializable(TypeInterface $childType) function it_should_return_the_value_from_the_child(TypeInterface $childType) { $this->beConstructedWith($childType); - $childType->check(false)->willReturn(new Result(false, [])); - $this->check(false)->isValid()->shouldBe(false); + $childType->check('', false)->willReturn(new Result(false, [])); + $this->check('', false)->isValid()->shouldBe(false); } } diff --git a/spec/Type/RegexTypeSpec.php b/spec/Type/RegexTypeSpec.php index e2ad031..904ee25 100644 --- a/spec/Type/RegexTypeSpec.php +++ b/spec/Type/RegexTypeSpec.php @@ -19,24 +19,24 @@ function it_should_return_valid_for_matching_strings() { $this->beConstructedWith('/^def/'); - $this->check('definitive')->isValid()->shouldBe(true); + $this->check('', 'definitive')->isValid()->shouldBe(true); } function it_should_return_invalid_for_not_matching_strings() { $this->beConstructedWith('/^def/'); - $this->check('developers')->isValid()->shouldBe(false); + $this->check('', 'developers')->isValid()->shouldBe(false); } function it_should_return_invalid_for_others() { $this->beConstructedWith('/^def/'); - $this->check(null)->isValid()->shouldBe(false); - $this->check(12.3)->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(-1)->isValid()->shouldBe(false); - $this->check(true)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', 12.3)->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', -1)->isValid()->shouldBe(false); + $this->check('', true)->isValid()->shouldBe(false); } } diff --git a/spec/Type/StringTypeSpec.php b/spec/Type/StringTypeSpec.php index 5bb35d6..f514c5f 100644 --- a/spec/Type/StringTypeSpec.php +++ b/spec/Type/StringTypeSpec.php @@ -15,17 +15,17 @@ function it_is_initializable() function it_should_return_valid_for_strings() { - $this->check("")->isValid()->shouldBe(true); - $this->check("fooo")->isValid()->shouldBe(true); - $this->check('adadsad asd a')->isValid()->shouldBe(true); + $this->check('', '')->isValid()->shouldBe(true); + $this->check('', 'fooo')->isValid()->shouldBe(true); + $this->check('', 'adadsad asd a')->isValid()->shouldBe(true); } function it_should_return_invalid_for_others() { - $this->check(null)->isValid()->shouldBe(false); - $this->check(12.3)->isValid()->shouldBe(false); - $this->check([])->isValid()->shouldBe(false); - $this->check(-1)->isValid()->shouldBe(false); - $this->check(true)->isValid()->shouldBe(false); + $this->check('', null)->isValid()->shouldBe(false); + $this->check('', 12.3)->isValid()->shouldBe(false); + $this->check('', [])->isValid()->shouldBe(false); + $this->check('', -1)->isValid()->shouldBe(false); + $this->check('', true)->isValid()->shouldBe(false); } } diff --git a/src/Check/CountCheck.php b/src/Check/CountCheck.php index 72d283e..6f09a2d 100644 --- a/src/Check/CountCheck.php +++ b/src/Check/CountCheck.php @@ -3,13 +3,11 @@ namespace Cubicl\StructureCheck\Check; use Countable; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; use Cubicl\StructureCheck\Type\TypeInterface; -/** - * Class CountCheck - * @package Cubicl\StructureCheck\Check - */ class CountCheck implements TypeInterface { /** @@ -32,43 +30,32 @@ class CountCheck implements TypeInterface */ private $count; - /** - * CountCheck constructor. - * - * @param TypeInterface $child - * @param int $count - */ - public function __construct(TypeInterface $child, $count) + public function __construct(TypeInterface $child, int $count) { $this->child = $child; $this->count = $count; } - /** - * @inheritdoc - */ - public function check($value) + public function check(string $key, $value): ResultInterface { - $result = $this->child->check($value); + $result = $this->child->check($key, $value); if (!$result->isValid()) { return $result; } if (!$value instanceof Countable) { - return new Result( - false, - [sprintf(self::$countableErrorMessage, json_encode($value))] - ); + return Result::invalid([ + new Error($key, sprintf(self::$countableErrorMessage, json_encode($value))) + ]); } if (count($value) !== $this->count) { - return new Result( - false, - [sprintf(self::$countErrorMessage, json_encode($value), $this->count)] - ); + return Result::invalid([ + new Error($key, sprintf(self::$countErrorMessage, json_encode($value), $this->count)) + ]); } - return new Result(true); + return Result::valid(); } } diff --git a/src/Check/NumericRangeCheck.php b/src/Check/NumericRangeCheck.php index 414c2d9..a23a718 100644 --- a/src/Check/NumericRangeCheck.php +++ b/src/Check/NumericRangeCheck.php @@ -2,13 +2,11 @@ namespace Cubicl\StructureCheck\Check; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; use Cubicl\StructureCheck\Type\TypeInterface; -/** - * Class NumericRangeCheck - * @package Cubicl\StructureCheck\Check - */ class NumericRangeCheck implements TypeInterface { /** @@ -36,43 +34,33 @@ class NumericRangeCheck implements TypeInterface */ private $upperBound; - /** - * @param TypeInterface $child - * @param int $upperBound - * @param int $lowerBound - */ - public function __construct(TypeInterface $child, $upperBound, $lowerBound) + public function __construct(TypeInterface $child, int $upperBound, int $lowerBound) { $this->child = $child; $this->upperBound = $upperBound; $this->lowerBound = $lowerBound; } - /** - * @inheritdoc - */ - public function check($value) + public function check(string $key, $value): ResultInterface { - $result = $this->child->check($value); + $result = $this->child->check($key, $value); if (!$result->isValid()) { return $result; } if ($this->lowerBound > $value) { - return new Result( - false, - [sprintf(self::$lowerBoundErrorMessage, $this->lowerBound, $value)] - ); + return Result::invalid([ + new Error($key, sprintf(self::$lowerBoundErrorMessage, $this->lowerBound, $value)) + ]); } if ($this->upperBound < $value) { - return new Result( - false, - [sprintf(self::$upperBoundErrorMessage, $this->upperBound, $value)] - ); + return Result::invalid([ + new Error($key, sprintf(self::$upperBoundErrorMessage, $this->lowerBound, $value)) + ]); } - return new Result(true); + return Result::valid(); } } diff --git a/src/Checker.php b/src/Checker.php index b7097a0..861a490 100644 --- a/src/Checker.php +++ b/src/Checker.php @@ -4,19 +4,13 @@ use Cubicl\StructureCheck\Type\TypeInterface; -/** - * Class Checker - * @package Cubicl\StructureCheck - */ class Checker implements CheckerInterface { - /** * @inheritdoc */ - public function fulfills($element, TypeInterface $requirement) + public function fulfills($element, TypeInterface $requirement): ResultInterface { - return $requirement->check($element); + return $requirement->check('', $element); } - -} \ No newline at end of file +} diff --git a/src/CheckerInterface.php b/src/CheckerInterface.php index af764bc..1cc8ef3 100644 --- a/src/CheckerInterface.php +++ b/src/CheckerInterface.php @@ -4,18 +4,13 @@ use Cubicl\StructureCheck\Type\TypeInterface; -/** - * Interface CheckerInterface - * @package Cubicl\StructureCheck - */ interface CheckerInterface { - /** * @param mixed $element the element which should be tested * @param TypeInterface $requirement * * @return ResultInterface */ - public function fulfills($element, TypeInterface $requirement); -} \ No newline at end of file + public function fulfills($element, TypeInterface $requirement): ResultInterface; +} diff --git a/src/Error.php b/src/Error.php new file mode 100644 index 0000000..d21a104 --- /dev/null +++ b/src/Error.php @@ -0,0 +1,26 @@ +key = $key; + $this->message = $message; + } + + public function getKey(): string + { + return $this->key; + } + + public function getMessage(): string + { + return $this->message; + } +} diff --git a/src/ErrorInterface.php b/src/ErrorInterface.php new file mode 100644 index 0000000..ffd6246 --- /dev/null +++ b/src/ErrorInterface.php @@ -0,0 +1,10 @@ +valid = $valid; $this->errors = $errors; } + public static function valid(): ResultInterface + { + return new self(true, []); + } + + /** + * @param ErrorInterface[] $errors + * + * @return ResultInterface + */ + public static function invalid(array $errors): ResultInterface + { + return new self(false, $errors); + } + /** * @inheritdoc */ - public function isValid() + public function isValid(): bool { return $this->valid; } @@ -42,8 +53,8 @@ public function isValid() /** * @inheritdoc */ - public function getErrors() + public function getErrors(): array { return $this->errors; } -} \ No newline at end of file +} diff --git a/src/ResultInterface.php b/src/ResultInterface.php index dda5ac6..7bb0184 100644 --- a/src/ResultInterface.php +++ b/src/ResultInterface.php @@ -10,15 +10,13 @@ interface ResultInterface { /** * Returns TRUE if the check was successful. - * - * @return bool */ - public function isValid(); + public function isValid(): bool; /** * Returns a list of errors. If no error occurred, it will return an empty array. * - * @return array + * @return ErrorInterface[] */ - public function getErrors(); -} \ No newline at end of file + public function getErrors(): array; +} diff --git a/src/Type/AnyType.php b/src/Type/AnyType.php index 11a441d..dc2b925 100644 --- a/src/Type/AnyType.php +++ b/src/Type/AnyType.php @@ -3,6 +3,7 @@ namespace Cubicl\StructureCheck\Type; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; /** * Class AnyType @@ -13,8 +14,8 @@ class AnyType implements TypeInterface /** * @inheritdoc */ - public function check($value) + public function check(string $key, $value): ResultInterface { - return new Result(true); + return Result::valid(); } -} \ No newline at end of file +} diff --git a/src/Type/BoolType.php b/src/Type/BoolType.php index 1cd5003..10bede9 100644 --- a/src/Type/BoolType.php +++ b/src/Type/BoolType.php @@ -2,29 +2,20 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; -/** - * Class BoolType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class BoolType implements TypeInterface { private static $errorMessage = 'The value %s is not a boolean.'; - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_bool($value); - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([new Error($key, sprintf(self::$errorMessage, json_encode($value)))]); } -} \ No newline at end of file +} diff --git a/src/Type/DatetimeType.php b/src/Type/DatetimeType.php index 9e24770..f4e212b 100644 --- a/src/Type/DatetimeType.php +++ b/src/Type/DatetimeType.php @@ -2,15 +2,12 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use DateTime; use DateTimeZone; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; -/** - * Class DatetimeType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class DatetimeType implements TypeInterface { /** @@ -28,42 +25,26 @@ class DatetimeType implements TypeInterface */ private $datetimeZone; - /** - * DatetimeType constructor. - * - * @param string $format - * @param string $datetimeZone - */ - public function __construct($format, $datetimeZone) + public function __construct(string $format, string $datetimeZone) { $this->datetimeFormat = $format; $this->datetimeZone = $datetimeZone; } - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_string($value) && $this->isValidDatetime($value); - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([new Error($key, sprintf(self::$errorMessage, json_encode($value)))]); } - /** - * @param string $value - * - * @return bool - */ - private function isValidDatetime($value) { + private function isValidDatetime(string $value): bool + { $date = DateTime::createFromFormat($this->datetimeFormat, $value, new DateTimeZone($this->datetimeZone)); - $errors = DateTime::getLastErrors()["warning_count"]; + $errors = DateTime::getLastErrors(); - return $date && $errors["warning_count"] == 0 && $errors["error_count"] == 0; + return $date && $errors['warning_count'] === 0 && $errors['error_count'] === 0; } } diff --git a/src/Type/EnumType.php b/src/Type/EnumType.php index fa06419..f63f96d 100644 --- a/src/Type/EnumType.php +++ b/src/Type/EnumType.php @@ -2,20 +2,21 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; class EnumType implements TypeInterface { /** - * @var array + * @var string */ - private $values = []; + private static $errorMessage = 'The value %s is not in the allowed values (%s).'; /** - * @var string + * @var array */ - private static $errorMessage = 'The value %s is not in the allowed values (%s).'; + private $values; /** * EnumType constructor. @@ -27,18 +28,13 @@ public function __construct(array $values) $this->values = $values; } - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = in_array($value, $this->values, true); - - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value), implode(',', $this->values))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([ + new Error($key, sprintf(self::$errorMessage, json_encode($value), implode(',', $this->values))) + ]); } } diff --git a/src/Type/ExactValueType.php b/src/Type/ExactValueType.php index e1323c1..91c908d 100644 --- a/src/Type/ExactValueType.php +++ b/src/Type/ExactValueType.php @@ -2,12 +2,12 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; class ExactValueType implements TypeInterface { - /** * @var string */ @@ -26,18 +26,14 @@ public function __construct($value) $this->value = $value; } - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = $this->value === $value; - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value), $this->value)] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([ + new Error($key, sprintf(self::$errorMessage, json_encode($value), json_encode($this->value))) + ]); } } diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 49889fc..87c7eb0 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -2,22 +2,20 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; class FloatType implements TypeInterface { private static $errorMessage = 'The value %s is not a float.'; - /** - * @inheritdoc - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_float($value); - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([new Error($key, sprintf(self::$errorMessage, json_encode($value)))]); } -} \ No newline at end of file +} diff --git a/src/Type/IntType.php b/src/Type/IntType.php index 2aaa8b4..7e4e036 100644 --- a/src/Type/IntType.php +++ b/src/Type/IntType.php @@ -2,29 +2,20 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; -/** - * Class IntType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class IntType implements TypeInterface { private static $errorMessage = 'The value %s is not an integer.'; - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_int($value); - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([new Error($key, sprintf(self::$errorMessage, json_encode($value)))]); } -} \ No newline at end of file +} diff --git a/src/Type/ListType.php b/src/Type/ListType.php index 6d92ba7..0c5af64 100644 --- a/src/Type/ListType.php +++ b/src/Type/ListType.php @@ -2,12 +2,10 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; -/** - * Class ListType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class ListType implements TypeInterface { private static $isNotAnArrayMessage = 'The given value %s is not an array.'; @@ -17,38 +15,32 @@ class ListType implements TypeInterface */ private $child; - /** - * ListType constructor. - * - * @param TypeInterface $child - */ public function __construct(TypeInterface $child) { $this->child = $child; } - /** - * @inheritdoc - */ - public function check($value) + public function check(string $key, $value): ResultInterface { if (!is_array($value)) { - return new Result( - false, - [sprintf(self::$isNotAnArrayMessage, json_encode($value))] + return Result::invalid( + [new Error($key, sprintf(self::$isNotAnArrayMessage, json_encode($value)))] ); } $errors = []; $valid = true; - foreach ($value as $item) { - $result = $this->child->check($item); + foreach ($value as $idx => $item) { + $result = $this->child->check(sprintf('%s.%d', $key, $idx), $item); $valid = $valid && $result->isValid(); $errors += $result->getErrors(); } - return new Result($valid, $errors); + return $valid + ? Result::valid() + : Result::invalid($errors); + } } diff --git a/src/Type/NullableType.php b/src/Type/NullableType.php index 6f4d06f..c66f5a4 100644 --- a/src/Type/NullableType.php +++ b/src/Type/NullableType.php @@ -3,38 +3,26 @@ namespace Cubicl\StructureCheck\Type; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; -/** - * Class NullableType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class NullableType implements TypeInterface { - /** * @var TypeInterface */ private $child; - /** - * NullableType constructor. - * - * @param TypeInterface $child - */ public function __construct(TypeInterface $child) { $this->child = $child; } - /** - * @inheritdoc - */ - public function check($value) + public function check(string $key, $value): ResultInterface { - if(is_null($value)) { - return new Result(true); + if($value === null) { + return Result::valid(); } - return $this->child->check($value); + return $this->child->check($key, $value); } -} \ No newline at end of file +} diff --git a/src/Type/NumericType.php b/src/Type/NumericType.php index 68fa1c1..796f092 100644 --- a/src/Type/NumericType.php +++ b/src/Type/NumericType.php @@ -2,6 +2,7 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; @@ -9,18 +10,12 @@ class NumericType implements TypeInterface { private static $errorMessage = 'The value %s is not a numeric value.'; - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_numeric($value); - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([new Error($key, sprintf(self::$errorMessage, json_encode($value)))]); } } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index da369b4..49a9fb6 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -2,7 +2,9 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; +use Cubicl\StructureCheck\ResultInterface; class ObjectType implements TypeInterface { @@ -23,25 +25,23 @@ public function __construct(array $children) $this->children = $children; } - /** - * @inheritdoc - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $errors = []; $valid = true; - foreach ($this->children as $key => $child) { - if (!array_key_exists($key, $value)) { + foreach ($this->children as $objectProperty => $child) { + $fullKey = sprintf('%s.%s', $key, $objectProperty); + if (!array_key_exists($objectProperty, $value)) { if (!$child instanceof OptionalType) { $valid = false; - $errors[] = sprintf(self::$missingKeyErrorMessage, $key); + $errors[] = new Error($fullKey, sprintf(self::$missingKeyErrorMessage, $objectProperty)); } continue; } - $result = $child->check($value[$key]); + $result = $child->check($fullKey, $value[$objectProperty]); $valid = $valid && $result->isValid(); $errors += $result->getErrors(); } diff --git a/src/Type/OptionalType.php b/src/Type/OptionalType.php index b300150..7b68ba4 100644 --- a/src/Type/OptionalType.php +++ b/src/Type/OptionalType.php @@ -4,34 +4,17 @@ use Cubicl\StructureCheck\ResultInterface; -/** - * Class OptionalType - * @package Cubicl\Cubicl\StructureCheck\Type - * @author Christian Blank - */ class OptionalType implements TypeInterface { - /** - * @var TypeInterface - */ private $child; - /** - * OptionalType constructor. - * @param TypeInterface $child - */ public function __construct(TypeInterface $child) { $this->child = $child; } - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { - return $this->child->check($value); + return $this->child->check($key, $value); } -} \ No newline at end of file +} diff --git a/src/Type/RegexType.php b/src/Type/RegexType.php index 6fb2888..84d5256 100644 --- a/src/Type/RegexType.php +++ b/src/Type/RegexType.php @@ -2,13 +2,10 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; -/** - * Class RegexType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class RegexType implements TypeInterface { /** @@ -21,28 +18,19 @@ class RegexType implements TypeInterface */ private $regex; - /** - * RegexType constructor. - * - * @param string $regex - */ - public function __construct($regex) + public function __construct(string $regex) { $this->regex = $regex; } - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_string($value) && preg_match($this->regex, $value) === 1; - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value), $this->regex)] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([ + new Error($key, sprintf(self::$errorMessage, json_encode($value), json_encode($this->regex))) + ]); } } diff --git a/src/Type/StringType.php b/src/Type/StringType.php index 9c69f2a..4e2441d 100644 --- a/src/Type/StringType.php +++ b/src/Type/StringType.php @@ -2,29 +2,20 @@ namespace Cubicl\StructureCheck\Type; +use Cubicl\StructureCheck\Error; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; -/** - * Class StringType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class StringType implements TypeInterface { private static $errorMessage = 'The value %s is not a string.'; - /** - * @param mixed $value - * - * @return ResultInterface - */ - public function check($value) + public function check(string $key, $value): ResultInterface { $checkResult = is_string($value); - return new Result( - $checkResult, - !$checkResult ? [sprintf(self::$errorMessage, json_encode($value))] : [] - ); + return $checkResult + ? Result::valid() + : Result::invalid([new Error($key, sprintf(self::$errorMessage, json_encode($value)))]); } -} \ No newline at end of file +} diff --git a/src/Type/TypeInterface.php b/src/Type/TypeInterface.php index 4ee25e5..450989c 100644 --- a/src/Type/TypeInterface.php +++ b/src/Type/TypeInterface.php @@ -11,9 +11,10 @@ interface TypeInterface { /** - * @param mixed $value + * @param string $key + * @param mixed $value * * @return ResultInterface */ - public function check($value); -} \ No newline at end of file + public function check(string $key, $value): ResultInterface; +} diff --git a/tests/Integration/Type/ObjectTypeTest.php b/tests/Integration/Type/ObjectTypeTest.php index 91a9592..0750194 100644 --- a/tests/Integration/Type/ObjectTypeTest.php +++ b/tests/Integration/Type/ObjectTypeTest.php @@ -24,7 +24,7 @@ class ObjectTypeTest extends TestCase /** * */ - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->checker = new Checker(); @@ -33,14 +33,14 @@ protected function setUp() /** * @test */ - public function itShouldHandleAbsenceOfOptionalDeclaredType() + public function itShouldHandleAbsenceOfOptionalDeclaredType(): void { $structure = new ObjectType([ 'opt' => new OptionalType(new AnyType()) ]); - $actual = $structure->check([]); + $actual = $structure->check('', []); $this->assertSame(true, $actual->isValid()); } -} \ No newline at end of file +} From 6d248da83df9504faafe28d376fc8e0bcdd9b8d5 Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Fri, 25 Sep 2020 06:40:43 +0200 Subject: [PATCH 08/19] 22 datetime error (#24) * [#22] Add PHP 7.4 for testing environment * [#22] Add better type hints --- .gitignore | 1 + .travis.yml | 6 +----- composer.json | 8 ++++---- spec/CheckerSpec.php | 2 +- spec/Type/DatetimeTypeSpec.php | 6 +++--- spec/Type/OptionalTypeSpec.php | 5 +++-- spec/Type/RegexTypeSpec.php | 8 ++++---- spec/Type/StringTypeSpec.php | 6 +++--- src/Check/CountCheck.php | 26 +++++++------------------- src/Error.php | 4 ++-- src/Type/AnyType.php | 4 ---- src/Type/BoolType.php | 2 +- src/Type/DatetimeType.php | 20 ++++++-------------- src/Type/EnumType.php | 24 +++++++++++++----------- src/Type/ExactValueType.php | 7 +------ src/Type/FloatType.php | 2 +- src/Type/IntType.php | 2 +- src/Type/ListType.php | 7 ++----- src/Type/NullableType.php | 5 +---- src/Type/NumericType.php | 2 +- src/Type/ObjectType.php | 10 +++------- src/Type/OptionalType.php | 2 +- src/Type/RegexType.php | 10 ++-------- src/Type/StringType.php | 2 +- src/Type/TypeInterface.php | 4 ---- 25 files changed, 63 insertions(+), 112 deletions(-) diff --git a/.gitignore b/.gitignore index 0a60947..3d4b9b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea/ vendor composer.lock +.phpunit.result.cache diff --git a/.travis.yml b/.travis.yml index ba5c4df..5774099 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,15 +3,11 @@ language: php matrix: include: - - php: 7.1 - - php: 7.2 - - php: 7.3 + - php: 7.4 allow_failures: - php: nightly fast_finish: true -before_install: - install: - composer install diff --git a/composer.json b/composer.json index 98f08f6..5ff644f 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "cubicl/php-structure-check", - "description": "Structural check of arrays for PHP 7.1+", + "description": "Structural check of arrays for PHP 7.3+", "keywords": ["array", "structure", "types"], "homepage": "https://github.com/cubicldev/php-structure-check", "type": "library", @@ -19,9 +19,9 @@ "tests-spec": "phpspec run --no-interaction" }, "require-dev": { - "phpspec/phpspec": "^5.1.0", - "phpunit/phpunit": "^7", - "phpstan/phpstan": "^0.11.4" + "phpspec/phpspec": "^6.2", + "phpunit/phpunit": "^9.3", + "phpstan/phpstan": "^0.12" }, "autoload": { "psr-4": { diff --git a/spec/CheckerSpec.php b/spec/CheckerSpec.php index 548ec51..b91780e 100644 --- a/spec/CheckerSpec.php +++ b/spec/CheckerSpec.php @@ -9,7 +9,7 @@ class CheckerSpec extends ObjectBehavior { - function it_is_initializable() + function it_is_initializable(): void { $this->shouldHaveType(Checker::class); } diff --git a/spec/Type/DatetimeTypeSpec.php b/spec/Type/DatetimeTypeSpec.php index b54efd7..05f1231 100644 --- a/spec/Type/DatetimeTypeSpec.php +++ b/spec/Type/DatetimeTypeSpec.php @@ -8,20 +8,20 @@ class DatetimeTypeSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable(): void { $this->beConstructedWith('d-m-Y h:m:s', 'UTC'); $this->shouldHaveType(DatetimeType::class); } - function it_should_return_valid_for_correct_values() + public function it_should_return_valid_for_correct_values(): void { $this->beConstructedWith('d-m-Y h:m:s', 'Europe/Berlin'); $this->check('', '12-12-2012 12:12:10')->isValid()->shouldBe(true); } - function it_should_return_invalid_for_others() + public function it_should_return_invalid_for_others(): void { $this->beConstructedWith('d-m-Y h:m:s', 'Europe/Berlin'); diff --git a/spec/Type/OptionalTypeSpec.php b/spec/Type/OptionalTypeSpec.php index 61f4a38..0786dba 100644 --- a/spec/Type/OptionalTypeSpec.php +++ b/spec/Type/OptionalTypeSpec.php @@ -9,13 +9,14 @@ class OptionalTypeSpec extends ObjectBehavior { - function it_is_initializable(TypeInterface $childType) + function it_is_initializable(TypeInterface $childType): void { $this->beConstructedWith($childType); $this->shouldHaveType(OptionalType::class); } - function it_should_return_the_value_from_the_child(TypeInterface $childType) { + function it_should_return_the_value_from_the_child(TypeInterface $childType): void + { $this->beConstructedWith($childType); $childType->check('', false)->willReturn(new Result(false, [])); $this->check('', false)->isValid()->shouldBe(false); diff --git a/spec/Type/RegexTypeSpec.php b/spec/Type/RegexTypeSpec.php index 904ee25..30c3250 100644 --- a/spec/Type/RegexTypeSpec.php +++ b/spec/Type/RegexTypeSpec.php @@ -8,28 +8,28 @@ class RegexTypeSpec extends ObjectBehavior { - function it_is_initializable() + function it_is_initializable(): void { $this->beConstructedWith('/^def/'); $this->shouldHaveType(RegexType::class); } - function it_should_return_valid_for_matching_strings() + function it_should_return_valid_for_matching_strings(): void { $this->beConstructedWith('/^def/'); $this->check('', 'definitive')->isValid()->shouldBe(true); } - function it_should_return_invalid_for_not_matching_strings() + function it_should_return_invalid_for_not_matching_strings(): void { $this->beConstructedWith('/^def/'); $this->check('', 'developers')->isValid()->shouldBe(false); } - function it_should_return_invalid_for_others() + function it_should_return_invalid_for_others(): void { $this->beConstructedWith('/^def/'); diff --git a/spec/Type/StringTypeSpec.php b/spec/Type/StringTypeSpec.php index f514c5f..4d95b5d 100644 --- a/spec/Type/StringTypeSpec.php +++ b/spec/Type/StringTypeSpec.php @@ -8,19 +8,19 @@ class StringTypeSpec extends ObjectBehavior { - function it_is_initializable() + function it_is_initializable(): void { $this->shouldHaveType(StringType::class); } - function it_should_return_valid_for_strings() + function it_should_return_valid_for_strings(): void { $this->check('', '')->isValid()->shouldBe(true); $this->check('', 'fooo')->isValid()->shouldBe(true); $this->check('', 'adadsad asd a')->isValid()->shouldBe(true); } - function it_should_return_invalid_for_others() + function it_should_return_invalid_for_others(): void { $this->check('', null)->isValid()->shouldBe(false); $this->check('', 12.3)->isValid()->shouldBe(false); diff --git a/src/Check/CountCheck.php b/src/Check/CountCheck.php index 6f09a2d..6dd09ef 100644 --- a/src/Check/CountCheck.php +++ b/src/Check/CountCheck.php @@ -10,25 +10,13 @@ class CountCheck implements TypeInterface { - /** - * @var string - */ - private static $countErrorMessage = 'The given countable %s has not the expected count %d.'; - - /** - * @var string - */ - private static $countableErrorMessage = 'The given value %s is not a countable'; - - /** - * @var TypeInterface - */ - private $child; - - /** - * @var int - */ - private $count; + private static string $countErrorMessage = 'The given countable %s has not the expected count %d.'; + + private static string $countableErrorMessage = 'The given value %s is not a countable'; + + private TypeInterface $child; + + private int $count; public function __construct(TypeInterface $child, int $count) { diff --git a/src/Error.php b/src/Error.php index d21a104..19e45e5 100644 --- a/src/Error.php +++ b/src/Error.php @@ -4,9 +4,9 @@ class Error implements ErrorInterface { - private $key; + private string $key; - private $message; + private string $message; public function __construct(string $key, string $message) { diff --git a/src/Type/AnyType.php b/src/Type/AnyType.php index dc2b925..ce52d93 100644 --- a/src/Type/AnyType.php +++ b/src/Type/AnyType.php @@ -5,10 +5,6 @@ use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; -/** - * Class AnyType - * @package Cubicl\Cubicl\StructureCheck\Type - */ class AnyType implements TypeInterface { /** diff --git a/src/Type/BoolType.php b/src/Type/BoolType.php index 10bede9..3181a5f 100644 --- a/src/Type/BoolType.php +++ b/src/Type/BoolType.php @@ -8,7 +8,7 @@ class BoolType implements TypeInterface { - private static $errorMessage = 'The value %s is not a boolean.'; + private static string $errorMessage = 'The value %s is not a boolean.'; public function check(string $key, $value): ResultInterface { diff --git a/src/Type/DatetimeType.php b/src/Type/DatetimeType.php index f4e212b..0926244 100644 --- a/src/Type/DatetimeType.php +++ b/src/Type/DatetimeType.php @@ -7,23 +7,15 @@ use DateTimeZone; use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; +use JsonException; class DatetimeType implements TypeInterface { - /** - * @var string - */ - private static $errorMessage = 'The value %s is not a valid datetime.'; - - /** - * @var string - */ - private $datetimeFormat; - - /** - * @var string - */ - private $datetimeZone; + private static string $errorMessage = 'The value %s is not a valid datetime.'; + + private string $datetimeFormat; + + private string $datetimeZone; public function __construct(string $format, string $datetimeZone) { diff --git a/src/Type/EnumType.php b/src/Type/EnumType.php index f63f96d..fa570e9 100644 --- a/src/Type/EnumType.php +++ b/src/Type/EnumType.php @@ -6,28 +6,30 @@ use Cubicl\StructureCheck\Result; use Cubicl\StructureCheck\ResultInterface; +/** + * @template T + */ class EnumType implements TypeInterface { - /** - * @var string - */ - private static $errorMessage = 'The value %s is not in the allowed values (%s).'; + private static string $errorMessage = 'The value %s is not in the allowed values (%s).'; - /** - * @var array - */ - private $values; + /** @var array */ + private array $values; /** - * EnumType constructor. - * - * @param array $values + * @param array $values */ public function __construct(array $values) { $this->values = $values; } + /** + * @param string $key + * @param T $value + * + * @return ResultInterface + */ public function check(string $key, $value): ResultInterface { $checkResult = in_array($value, $this->values, true); diff --git a/src/Type/ExactValueType.php b/src/Type/ExactValueType.php index 91c908d..971e4ce 100644 --- a/src/Type/ExactValueType.php +++ b/src/Type/ExactValueType.php @@ -8,17 +8,12 @@ class ExactValueType implements TypeInterface { - /** - * @var string - */ - private static $errorMessage = 'The value %s is not the same value as %s.'; + private static string $errorMessage = 'The value %s is not the same value as %s.'; /** @var mixed */ private $value; /** - * ExactValueType constructor. - * * @param mixed $value */ public function __construct($value) diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 87c7eb0..2739d5e 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -8,7 +8,7 @@ class FloatType implements TypeInterface { - private static $errorMessage = 'The value %s is not a float.'; + private static string $errorMessage = 'The value %s is not a float.'; public function check(string $key, $value): ResultInterface { diff --git a/src/Type/IntType.php b/src/Type/IntType.php index 7e4e036..ae15b82 100644 --- a/src/Type/IntType.php +++ b/src/Type/IntType.php @@ -8,7 +8,7 @@ class IntType implements TypeInterface { - private static $errorMessage = 'The value %s is not an integer.'; + private static string $errorMessage = 'The value %s is not an integer.'; public function check(string $key, $value): ResultInterface { diff --git a/src/Type/ListType.php b/src/Type/ListType.php index 0c5af64..c0d0a0a 100644 --- a/src/Type/ListType.php +++ b/src/Type/ListType.php @@ -8,12 +8,9 @@ class ListType implements TypeInterface { - private static $isNotAnArrayMessage = 'The given value %s is not an array.'; + private static string $isNotAnArrayMessage = 'The given value %s is not an array.'; - /** - * @var TypeInterface - */ - private $child; + private TypeInterface $child; public function __construct(TypeInterface $child) { diff --git a/src/Type/NullableType.php b/src/Type/NullableType.php index c66f5a4..287756b 100644 --- a/src/Type/NullableType.php +++ b/src/Type/NullableType.php @@ -7,10 +7,7 @@ class NullableType implements TypeInterface { - /** - * @var TypeInterface - */ - private $child; + private TypeInterface $child; public function __construct(TypeInterface $child) { diff --git a/src/Type/NumericType.php b/src/Type/NumericType.php index 796f092..e3797d1 100644 --- a/src/Type/NumericType.php +++ b/src/Type/NumericType.php @@ -8,7 +8,7 @@ class NumericType implements TypeInterface { - private static $errorMessage = 'The value %s is not a numeric value.'; + private static string $errorMessage = 'The value %s is not a numeric value.'; public function check(string $key, $value): ResultInterface { diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 49a9fb6..fedb850 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -8,16 +8,12 @@ class ObjectType implements TypeInterface { - private static $missingKeyErrorMessage = 'The key "%s" does not exists'; + private static string $missingKeyErrorMessage = 'The key "%s" does not exists'; - /** - * @var TypeInterface[] - */ - private $children; + /** @var TypeInterface[] */ + private array $children; /** - * ObjectType constructor. - * * @param TypeInterface[] $children */ public function __construct(array $children) diff --git a/src/Type/OptionalType.php b/src/Type/OptionalType.php index 7b68ba4..7c0a26f 100644 --- a/src/Type/OptionalType.php +++ b/src/Type/OptionalType.php @@ -6,7 +6,7 @@ class OptionalType implements TypeInterface { - private $child; + private TypeInterface $child; public function __construct(TypeInterface $child) { diff --git a/src/Type/RegexType.php b/src/Type/RegexType.php index 84d5256..4d93d74 100644 --- a/src/Type/RegexType.php +++ b/src/Type/RegexType.php @@ -8,15 +8,9 @@ class RegexType implements TypeInterface { - /** - * @var string - */ - private static $errorMessage = 'The value %s does not match the regex %s'; + private static string $errorMessage = 'The value %s does not match the regex %s'; - /** - * @var string - */ - private $regex; + private string $regex; public function __construct(string $regex) { diff --git a/src/Type/StringType.php b/src/Type/StringType.php index 4e2441d..e26addb 100644 --- a/src/Type/StringType.php +++ b/src/Type/StringType.php @@ -8,7 +8,7 @@ class StringType implements TypeInterface { - private static $errorMessage = 'The value %s is not a string.'; + private static string $errorMessage = 'The value %s is not a string.'; public function check(string $key, $value): ResultInterface { diff --git a/src/Type/TypeInterface.php b/src/Type/TypeInterface.php index 450989c..59f311a 100644 --- a/src/Type/TypeInterface.php +++ b/src/Type/TypeInterface.php @@ -4,10 +4,6 @@ use Cubicl\StructureCheck\ResultInterface; -/** - * Interface TypeInterface - * @package Cubicl\Cubicl\StructureCheck\Type - */ interface TypeInterface { /** From 6e8961ffad3d025e87f0ec09c9f649281d62af7e Mon Sep 17 00:00:00 2001 From: srmnq <52739584+srmnq@users.noreply.github.com> Date: Sat, 24 Oct 2020 14:50:17 +0200 Subject: [PATCH 09/19] Php7.4 (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Declare strict types * Typehinting * Remove redundant docbloc Co-authored-by: Sara Gfrörer --- composer.json | 77 +++++++++++++---------- spec/Check/CountCheckSpec.php | 2 + spec/Check/NumericRangeCheckSpec.php | 2 + spec/CheckerSpec.php | 2 + spec/ResultSpec.php | 2 + spec/Type/AnyTypeSpec.php | 2 + spec/Type/BoolTypeSpec.php | 2 + spec/Type/DatetimeTypeSpec.php | 2 + spec/Type/EnumTypeSpec.php | 2 + spec/Type/ExactValueTypeSpec.php | 2 + spec/Type/FloatTypeSpec.php | 2 + spec/Type/IntTypeSpec.php | 2 + spec/Type/ListTypeSpec.php | 2 + spec/Type/NullableTypeSpec.php | 2 + spec/Type/NumericTypeSpec.php | 2 + spec/Type/ObjectTypeSpec.php | 2 + spec/Type/OptionalTypeSpec.php | 2 + spec/Type/RegexTypeSpec.php | 2 + spec/Type/StringTypeSpec.php | 2 + src/Check/CountCheck.php | 2 + src/Check/NumericRangeCheck.php | 2 + src/Checker.php | 5 +- src/CheckerInterface.php | 5 +- src/Error.php | 2 + src/ErrorInterface.php | 2 + src/Result.php | 29 +++------ src/ResultInterface.php | 5 +- src/Type/AnyType.php | 5 +- src/Type/BoolType.php | 2 + src/Type/DatetimeType.php | 3 +- src/Type/EnumType.php | 4 +- src/Type/ExactValueType.php | 2 + src/Type/FloatType.php | 2 + src/Type/IntType.php | 2 + src/Type/ListType.php | 3 +- src/Type/NullableType.php | 2 + src/Type/NumericType.php | 2 + src/Type/ObjectType.php | 3 +- src/Type/OptionalType.php | 2 + src/Type/RegexType.php | 2 + src/Type/StringType.php | 2 + src/Type/TypeInterface.php | 7 +-- tests/Integration/Type/ObjectTypeTest.php | 10 +-- 43 files changed, 136 insertions(+), 82 deletions(-) diff --git a/composer.json b/composer.json index 5ff644f..e62ccb5 100644 --- a/composer.json +++ b/composer.json @@ -1,39 +1,48 @@ { - "name": "cubicl/php-structure-check", - "description": "Structural check of arrays for PHP 7.3+", - "keywords": ["array", "structure", "types"], - "homepage": "https://github.com/cubicldev/php-structure-check", - "type": "library", - "license": "MIT", - "authors": [ - { - "name": "Christian Blank", - "email": "christian@cubicl.de", - "homepage": "https://cubicl.de" - } + "name": "cubicl/php-structure-check", + "description": "Structural check of arrays for PHP 7.3+", + "keywords": [ + "array", + "structure", + "types" + ], + "homepage": "https://github.com/cubicldev/php-structure-check", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Christian Blank", + "email": "christian@cubicl.de", + "homepage": "https://cubicl.de" + } + ], + "scripts": { + "check": [ + "@analyze", + "@tests", + "@tests-spec" ], - "scripts": { - "check": ["@analyze", "@tests", "@tests-spec"], - "tests": "phpunit tests", - "analyze": "phpstan analyse --level max src", - "tests-spec": "phpspec run --no-interaction" - }, - "require-dev": { - "phpspec/phpspec": "^6.2", - "phpunit/phpunit": "^9.3", - "phpstan/phpstan": "^0.12" - }, - "autoload": { - "psr-4": { - "Cubicl\\StructureCheck\\": [ - "src" - ], - "Cubicl\\StructureCheck\\Test\\": [ - "tests" - ] - } - }, + "tests": "phpunit tests", + "analyze": "phpstan analyse --level max src", + "tests-spec": "phpspec run --no-interaction" + }, + "require-dev": { + "phpspec/phpspec": "^6.2", + "phpunit/phpunit": "^9.3", + "phpstan/phpstan": "^0.12" + }, + "autoload": { + "psr-4": { + "Cubicl\\StructureCheck\\": [ + "src" + ], + "Cubicl\\StructureCheck\\Test\\": [ + "tests" + ] + } + }, "require": { - "ext-json": "*" + "ext-json": "*", + "php": "^7.4" } } diff --git a/spec/Check/CountCheckSpec.php b/spec/Check/CountCheckSpec.php index dd36f12..6a53485 100644 --- a/spec/Check/CountCheckSpec.php +++ b/spec/Check/CountCheckSpec.php @@ -1,5 +1,7 @@ check('', $element); diff --git a/src/CheckerInterface.php b/src/CheckerInterface.php index 1cc8ef3..e6ecc55 100644 --- a/src/CheckerInterface.php +++ b/src/CheckerInterface.php @@ -1,5 +1,7 @@ */ - private $errors; + private array $errors; /** - * Result constructor. - * - * @param bool $valid - * @param ErrorInterface[] $errors + * @param array $errors */ - public function __construct($valid, array $errors) + public function __construct(bool $valid, array $errors) { $this->valid = $valid; $this->errors = $errors; @@ -33,26 +28,18 @@ public static function valid(): ResultInterface } /** - * @param ErrorInterface[] $errors - * - * @return ResultInterface + * @param array $errors */ public static function invalid(array $errors): ResultInterface { return new self(false, $errors); } - /** - * @inheritdoc - */ public function isValid(): bool { return $this->valid; } - /** - * @inheritdoc - */ public function getErrors(): array { return $this->errors; diff --git a/src/ResultInterface.php b/src/ResultInterface.php index 7bb0184..17eabde 100644 --- a/src/ResultInterface.php +++ b/src/ResultInterface.php @@ -1,9 +1,10 @@ */ public function getErrors(): array; } diff --git a/src/Type/AnyType.php b/src/Type/AnyType.php index ce52d93..aecd21b 100644 --- a/src/Type/AnyType.php +++ b/src/Type/AnyType.php @@ -1,5 +1,7 @@ Date: Sat, 24 Oct 2020 15:32:21 +0200 Subject: [PATCH 10/19] Phpstan (#26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add phpstan-deprecated and -unit Co-authored-by: Sara Gfrörer --- .gitignore | 1 + composer.json | 9 ++++++--- phpstan.neon.dist | 8 ++++++++ phpunit.xml.dist | 11 +++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 phpstan.neon.dist create mode 100644 phpunit.xml.dist diff --git a/.gitignore b/.gitignore index 3d4b9b6..9a8c46e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ vendor composer.lock .phpunit.result.cache +/data/ \ No newline at end of file diff --git a/composer.json b/composer.json index e62ccb5..0c80ab7 100644 --- a/composer.json +++ b/composer.json @@ -23,13 +23,16 @@ "@tests-spec" ], "tests": "phpunit tests", - "analyze": "phpstan analyse --level max src", + "analyze": "phpstan analyse --level max", "tests-spec": "phpspec run --no-interaction" }, "require-dev": { "phpspec/phpspec": "^6.2", - "phpunit/phpunit": "^9.3", - "phpstan/phpstan": "^0.12" + "phpunit/phpunit": "^9.4", + "phpstan/phpstan": "^0.12.51", + "phpstan/phpstan-deprecation-rules": "^0.12.4", + "phpstan/phpstan-phpunit": "^0.12.16", + "squizlabs/php_codesniffer": "^3.5.5" }, "autoload": { "psr-4": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..773f149 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,8 @@ +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-deprecation-rules/rules.neon +parameters: + tmpDir: data + level: max + paths: + - src \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..a2d1acc --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,11 @@ + + + + + ./tests/ + + + \ No newline at end of file From f780f90297b051667fcd7a3d68580310427e65ac Mon Sep 17 00:00:00 2001 From: srmnq <52739584+srmnq@users.noreply.github.com> Date: Sat, 24 Oct 2020 15:49:57 +0200 Subject: [PATCH 11/19] Phpunit (#28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Include tests folder to phpstan Co-authored-by: Sara Gfrörer --- phpstan.neon.dist | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 773f149..da420ab 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,4 +5,5 @@ parameters: tmpDir: data level: max paths: - - src \ No newline at end of file + - src + - tests \ No newline at end of file From 098c1808a4981c0cfff983db004bf98461a3618e Mon Sep 17 00:00:00 2001 From: srmnq <52739584+srmnq@users.noreply.github.com> Date: Sat, 24 Oct 2020 16:57:32 +0200 Subject: [PATCH 12/19] Codestyle with phpcs (#29) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add phpcs Co-authored-by: Sara Gfrörer --- composer.json | 7 +++++-- phpcs.xml.dist | 21 +++++++++++++++++++++ src/Check/NumericRangeCheck.php | 2 +- src/Type/NullableType.php | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 phpcs.xml.dist diff --git a/composer.json b/composer.json index 0c80ab7..f9e81c6 100644 --- a/composer.json +++ b/composer.json @@ -20,11 +20,14 @@ "check": [ "@analyze", "@tests", - "@tests-spec" + "@tests-spec", + "@cs-check" ], "tests": "phpunit tests", "analyze": "phpstan analyse --level max", - "tests-spec": "phpspec run --no-interaction" + "tests-spec": "phpspec run --no-interaction", + "cs-check": "phpcs --parallel=50", + "cs-fix": "phpcbf" }, "require-dev": { "phpspec/phpspec": "^6.2", diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..1c5e692 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + src + tests + \ No newline at end of file diff --git a/src/Check/NumericRangeCheck.php b/src/Check/NumericRangeCheck.php index 581ccee..ef3dc38 100644 --- a/src/Check/NumericRangeCheck.php +++ b/src/Check/NumericRangeCheck.php @@ -48,7 +48,7 @@ public function check(string $key, $value): ResultInterface $result = $this->child->check($key, $value); if (!$result->isValid()) { - return $result; + return $result; } if ($this->lowerBound > $value) { diff --git a/src/Type/NullableType.php b/src/Type/NullableType.php index 56b8a97..f3eb64e 100644 --- a/src/Type/NullableType.php +++ b/src/Type/NullableType.php @@ -18,7 +18,7 @@ public function __construct(TypeInterface $child) public function check(string $key, $value): ResultInterface { - if($value === null) { + if ($value === null) { return Result::valid(); } From ba32c719090cebdeeca0be1ccc156b71d92fe9dd Mon Sep 17 00:00:00 2001 From: srmnq <52739584+srmnq@users.noreply.github.com> Date: Sat, 24 Oct 2020 16:58:33 +0200 Subject: [PATCH 13/19] Add workflow ci (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add workflow ci * Delete travis yml Co-authored-by: Sara Gfrörer --- .github/workflows/ci.yml | 41 ++++++++++++++++++++++++++++++++++++++++ .travis.yml | 15 --------------- 2 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1ec64b1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,41 @@ +name: CI Tests + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run test suite + run: composer test + + - name: Run phpstan + run: composer analyze + + - name: Run codestyle checker + run: composer cs-check + + - uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5774099..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -dist: trusty -language: php - -matrix: - include: - - php: 7.4 - allow_failures: - - php: nightly - fast_finish: true - -install: - - composer install - -script: - - composer run check From 982a7639e1f9da7a71535b0d6d50f68e3a10dcaf Mon Sep 17 00:00:00 2001 From: srmnq <52739584+srmnq@users.noreply.github.com> Date: Sat, 24 Oct 2020 17:34:21 +0200 Subject: [PATCH 14/19] Fix Typo in Workflow file (#31) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix typo Co-authored-by: Sara Gfrörer --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ec64b1..d431c4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,8 +24,8 @@ jobs: - name: Install dependencies run: composer install --prefer-dist --no-progress - - name: Run test suite - run: composer test + - name: Run tests suite + run: composer tests - name: Run phpstan run: composer analyze From f4e5181036b361944e6b784318d39fbf3eeb5a27 Mon Sep 17 00:00:00 2001 From: srmnq <52739584+srmnq@users.noreply.github.com> Date: Sun, 25 Oct 2020 09:47:05 +0100 Subject: [PATCH 15/19] Add build matrix capability (#32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add workflow for possible future php versions Co-authored-by: Sara Gfrörer --- .github/workflows/ci.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d431c4d..bfe53b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,9 +10,25 @@ jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + operating-system: [ ubuntu-latest ] + php: [ '7.4' ] +# php: [ '7.4', '8.0' ] + + name: PHP ${{ matrix.php }} + steps: - uses: actions/checkout@v2 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: none + ini-values: expose_php=1 + - name: Validate composer.json and composer.lock run: composer validate From a62e6c6321e35d9ebb6c1a9f9421f02fa20af3e6 Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Tue, 16 Nov 2021 18:50:10 +0100 Subject: [PATCH 16/19] Allow to install in PHP8 environment (#35) --- .github/workflows/ci.yml | 5 ++--- composer.json | 4 ++-- src/Type/DatetimeType.php | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfe53b6..bc2181a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,8 +13,7 @@ jobs: strategy: matrix: operating-system: [ ubuntu-latest ] - php: [ '7.4' ] -# php: [ '7.4', '8.0' ] + php: [ '7.4', '8.0' ] name: PHP ${{ matrix.php }} @@ -54,4 +53,4 @@ jobs: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: | - ${{ runner.os }}-composer- \ No newline at end of file + ${{ runner.os }}-composer- diff --git a/composer.json b/composer.json index f9e81c6..edac254 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "cubicl/php-structure-check", - "description": "Structural check of arrays for PHP 7.3+", + "description": "Structural check of arrays for PHP 7.4+", "keywords": [ "array", "structure", @@ -49,6 +49,6 @@ }, "require": { "ext-json": "*", - "php": "^7.4" + "php": "^7.4|^8.0" } } diff --git a/src/Type/DatetimeType.php b/src/Type/DatetimeType.php index 789b2b7..b361271 100644 --- a/src/Type/DatetimeType.php +++ b/src/Type/DatetimeType.php @@ -38,6 +38,6 @@ private function isValidDatetime(string $value): bool $date = DateTime::createFromFormat($this->datetimeFormat, $value, new DateTimeZone($this->datetimeZone)); $errors = DateTime::getLastErrors(); - return $date && $errors['warning_count'] === 0 && $errors['error_count'] === 0; + return $date && !$errors; } } From 3fbf583e575adf344ccba2a6453265b74e5d63da Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Fri, 4 Mar 2022 16:54:32 +0100 Subject: [PATCH 17/19] Add spec tests to Github action --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc2181a..b641120 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,9 @@ jobs: - name: Install dependencies run: composer install --prefer-dist --no-progress + - name: Run spec tests + run: composer tests-spec + - name: Run tests suite run: composer tests From 8299ee8e5825c4966d62cadbd0894867781a0bff Mon Sep 17 00:00:00 2001 From: Christian Blank Date: Fri, 4 Mar 2022 16:57:56 +0100 Subject: [PATCH 18/19] Fix error in validation of datetime --- src/Type/DatetimeType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Type/DatetimeType.php b/src/Type/DatetimeType.php index b361271..93c598d 100644 --- a/src/Type/DatetimeType.php +++ b/src/Type/DatetimeType.php @@ -38,6 +38,6 @@ private function isValidDatetime(string $value): bool $date = DateTime::createFromFormat($this->datetimeFormat, $value, new DateTimeZone($this->datetimeZone)); $errors = DateTime::getLastErrors(); - return $date && !$errors; + return $date && (!$errors || $errors['warning_count'] === 0 && $errors['error_count'] === 0); } } From 08e54b5ae3cab7ac76bef9dcecace13391f788cd Mon Sep 17 00:00:00 2001 From: func0der <529819+func0der@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:25:06 +0000 Subject: [PATCH 19/19] [revert-datetimetype-changes] Clarify operator precedence in error (#37) checking. --- src/Type/DatetimeType.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Type/DatetimeType.php b/src/Type/DatetimeType.php index 93c598d..1bed289 100644 --- a/src/Type/DatetimeType.php +++ b/src/Type/DatetimeType.php @@ -38,6 +38,8 @@ private function isValidDatetime(string $value): bool $date = DateTime::createFromFormat($this->datetimeFormat, $value, new DateTimeZone($this->datetimeZone)); $errors = DateTime::getLastErrors(); - return $date && (!$errors || $errors['warning_count'] === 0 && $errors['error_count'] === 0); + return $date && ( + !$errors || ($errors['warning_count'] === 0 && $errors['error_count'] === 0) + ); } }