├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── phpstan.neon
├── phpunit.xml
├── src
├── AbstractValidation.php
├── Exception
│ ├── ArrayValidationExceptionInterface.php
│ ├── InvalidStructureException.php
│ └── InvalidTypeException.php
├── Schema.php
├── SchemaCompiler.php
├── SchemaCompilerInterface.php
├── SchemaInterface.php
├── StrictValidation.php
├── StrictValidationFromDefinition.php
├── StrictValidationFromSchema.php
├── Validation.php
├── ValidationBuilder.php
├── ValidationDefinition.php
├── ValidationDefinitionExecutor.php
├── ValidationFromDefinition.php
├── ValidationFromSchema.php
├── ValidationInterface.php
├── Validator.php
└── ValidatorInterface.php
└── tests
├── SchemaCompilerTest.php
├── SchemaTest.php
├── StrictValidationTest.php
├── ValidationBuilderTest.php
├── ValidationDefinitionTest.php
├── ValidationFromDefinitionTest.php
├── ValidationFromSchemaTest.php
├── ValidationTest.php
└── ValidatorTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore packaged files
2 | *.7z
3 | *.dmg
4 | *.gz
5 | *.iso
6 | *.jar
7 | *.rar
8 | *.tar
9 | *.zip
10 | .phpunit.result.cache
11 | composer.lock
12 |
13 | # ignore app environment files
14 | .prod
15 | .staging
16 | .testing
17 | .dev
18 | .env
19 |
20 | # docker
21 | docker-compose.yml
22 | Dockerfile
23 | DockerfileShell
24 |
25 | # folders to ignore
26 | /.idea
27 | /_temp
28 | /vendor
29 | /tests/_reports
30 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | VERSION 3.2.0
2 | -------------
3 | Release date: 2020-04-02
4 |
5 | - added ValidationBuilder
6 |
7 | VERSION 3.1.1
8 | -------------
9 | Release date: 2020-03-27
10 |
11 | - added "autoload-dev" to composer.json (thank you @ordago)
12 | - added missing extension "ext-json" to composer.json (thank you @ordago)
13 |
14 | VERSION 3.1.0
15 | -------------
16 | Release date: 2020-03-26
17 |
18 | - use SchemaInterface instead of Schema in StrictValidationFromSchema and ValidationFromSchema
19 | - added validator expectKeyToBeObject() and expectKeysToBeObject()
20 |
21 | VERSION 3.0.0
22 | -------------
23 | Release date: 2020-03-21
24 |
25 | - introducing schema which add a new way to define your validations structure
26 | - added Schema, SchemaInterface, SchemaCompiler and SchemaCompilerInterface
27 | - added ArrayValidationExceptionInterface to help catching any validation exceptions
28 | - added StrictValidationFromSchema
29 | - rewritten StrictValidation and added AbstractValidation
30 | - added Validation, ValidationFromDefinition and ValidationFromSchema
31 | which act almost like as Strict* classes but without exceptions
32 | - fixed bug with ValidationDefinition where same method validation were not stacked but overwritten
33 | - added ValidationDefinitionExecutor
34 |
35 | VERSION 2.0.0
36 | -------------
37 | Release date: 2020-02-24
38 |
39 | - [BC] renamed method expectNElement() to expectNKeys() in ArrayValidation
40 | - added expectNKeys() and expectOnlyOneFromKeys() to StrictArrayValidator
41 | - added interfaces ArrayValidationInterface and ArrayValidatorInterface
42 | - [BC] renamed all classes and interfaces with better name
43 | - added ValidationDefinition and StrictValidationFromDefinition
44 |
45 | VERSION 1.1.0
46 | -------------
47 | Release date: 2020-02-20
48 |
49 | - added methods expectKeysToBeArray(), expectKeysToBeBoolean() and expectKeysToBeFloat() to StrictArrayValidator
50 | - transformed ArrayValidationException to 2 more specific exceptions: InvalidStructureException and InvalidTypeException
51 | - [BC] simplified and reordered constructor params of StrictArrayValidator
52 |
53 | VERSION 1.0.0
54 | -------------
55 | Release date: 2020-02-07
56 |
57 | - Initial release
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) François Lajoie
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Peak/ArrayValidation
2 |
3 |
4 |
5 |
6 |
7 | ## Installation
8 |
9 | composer require peak/array-validation
10 |
11 | ## What is this?
12 |
13 | This component help you to validate array structure by:
14 |
15 | - validating the type of any key values
16 | - ensuring a data structure with expected keys requirements
17 | - preventing structure pollution by allowing only a set of keys
18 |
19 | This is especially useful when dealing with json data request, before using the data, you must validate his content so
20 | you can afterward check the value of those keys with your business logic without worrying about the type or presence of any key value.
21 |
22 | # How to use
23 | ##### 8 Usages
24 |
25 | ## 1- General validation "à la carte" (stateless)
26 |
27 | ```php
28 | $validator = new Validator();
29 |
30 | if ($validator->expectExactlyKeys($data, $keys) === true) {
31 | // ...
32 | }
33 | ```
34 |
35 | ## 2- Validation with fluent interface (stateful)
36 |
37 | ```php
38 | $data = [ // data
39 | 'tags' => [],
40 | 'name' => 'foobar'
41 | ];
42 | $validation = new Validation($data);
43 |
44 | $validation
45 | ->expectExactlyKeys(['tags', 'name'])
46 | ->expectKeyToBeArray('tags');
47 | ->expectKeyToBeString('name');
48 |
49 | if ($validation->hasErrors()) {
50 | // $lastError = $validation->getLastError();
51 | // $errors = $validation->getErrors();
52 | }
53 | ```
54 |
55 | ## 3- Strict validation with fluent interface (stateful)
56 |
57 | ```php
58 |
59 | $validation = new StrictValidation($data);
60 |
61 | // will throw an exception if any of tests below fail
62 | $validation
63 | ->expectOnlyKeys(['id', 'title', 'description', 'isPrivate', 'tags'])
64 | ->expectAtLeastKeys(['id', 'title', 'description'])
65 | ->expectKeyToBeInteger('id')
66 | ->expectKeysToBeString(['title', 'description'])
67 | ->expectKeyToBeBoolean('isPrivate')
68 | ->expectKeyToBeArray('tags');
69 |
70 | // if we reach this point, it means the array structure is
71 | // valid according to the validation rules above.
72 |
73 | ```
74 |
75 | ## 4- Create a ValidationDefinition for later usage
76 |
77 | ```php
78 | $vDef = new ValidationDefinition();
79 | $vDef
80 | ->expectOnlyKeys(['title', 'content', 'description'])
81 | ->expectAtLeastKeys(['title', 'content'])
82 | ->expectKeysToBeString(['title', 'content', 'description']);
83 |
84 | $validation = new ValidationFromDefinition($vDef, $data);
85 |
86 | if ($validation->hasErrors()) {
87 | // $validation->getErrors();
88 | }
89 |
90 | ```
91 |
92 | ## 5- Create a validation Schema for later usage
93 |
94 | Schema is just another way to write validation definitions. This format is ideal when you want to store schemas in file (ex: json, php array file, yml, etc.)
95 |
96 | ```php
97 |
98 | $mySchema = [
99 | 'title' => [
100 | 'type' => 'string',
101 | 'required' => true
102 | ],
103 | 'content' => [
104 | 'type' => 'string',
105 | 'nullable' => true,
106 | ],
107 | ];
108 |
109 | $schema = new Schema(new SchemaCompiler(), $mySchema, 'mySchemaName');
110 |
111 | $validation = new ValidationFromSchema($schema, $data);
112 |
113 | if ($validation->hasErrors()) {
114 | // $validation->getErrors();
115 | }
116 | ```
117 |
118 |
119 |
120 | ## 6- Strict validation using ValidationDefinition
121 |
122 | ```php
123 | // all validation definitions are executed at object creation and an exception is thrown if any of tests failed
124 | new StrictValidationFromDefinition($validationDefinition, $arrayToValidate);
125 | ```
126 |
127 | ## 7- Strict validation using Schema
128 |
129 | ```php
130 | // all validation definitions are executed at object creation and an exception is thrown if any of tests failed
131 | new StrictValidationFromSchema($schema, $arrayToValidate);
132 | ```
133 |
134 | ## 8- Validation and Strict Validation with ValidationBuilder
135 |
136 | ```php
137 | $validation = new ValidationBuilder();
138 | $validation
139 | ->expectOnlyKeys(['title', 'content', 'description'])
140 | ->expectAtLeastKeys(['title', 'content'])
141 | ->expectKeysToBeString(['title', 'content', 'description']);
142 |
143 | if ($validation->validate($data) === false) {
144 | // $validation->getErrors();
145 | // $validation->getLastError();
146 | }
147 | ```
148 |
149 | and with strict validation:
150 |
151 | ```php
152 | // will throw an exception if any of tests fail
153 | $validation->strictValidate($data);
154 | ```
155 |
156 | # Validation methods
157 | ```php
158 |
159 | interface ValidationInterface
160 | {
161 | public function expectExactlyKeys(array $keys);
162 | public function expectOnlyOneFromKeys( array $keys);
163 | public function expectAtLeastKeys(array $keys);
164 | public function expectOnlyKeys(array $keys);
165 | public function expectNKeys(int $n);
166 | public function expectKeyToBeArray(string $key, bool $acceptNull = false);
167 | public function expectKeysToBeArray(array $keys, bool $acceptNull = false);
168 | public function expectKeyToBeInteger(string $key, bool $acceptNull = false);
169 | public function expectKeysToBeInteger(array $keys, bool $acceptNull = false);
170 | public function expectKeyToBeFloat(string $key, bool $acceptNull = false);
171 | public function expectKeysToBeFloat(array $keys, bool $acceptNull = false);
172 | public function expectKeyToBeString(string $key, bool $acceptNull = false);
173 | public function expectKeysToBeString(array $keys, bool $acceptNull = false);
174 | public function expectKeyToBeBoolean(string $key, bool $acceptNull = false);
175 | public function expectKeysToBeBoolean(array $keys, bool $acceptNull = false);
176 | public function expectKeyToBeObject(string $key, bool $acceptNull = false);
177 | public function expectKeysToBeObject(array $keys, bool $acceptNull = false);
178 | }
179 | ```
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "peak/array-validation",
3 | "description": "Validation utilities for array structure",
4 | "keywords": ["peak", "array", "validation"],
5 | "license": "MIT",
6 | "type": "library",
7 | "require": {
8 | "php": ">=7.2",
9 | "symfony/polyfill-php73": "^1.14",
10 | "ext-json": "*"
11 | },
12 | "require-dev": {
13 | "phpunit/phpunit": "^9.0",
14 | "phpstan/phpstan": "^0.12"
15 | },
16 | "autoload": {
17 | "psr-4": {
18 | "Peak\\ArrayValidation\\": "src/"
19 | }
20 | },
21 | "autoload-dev": {
22 | "psr-4": {
23 | "Tests\\": "tests/"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | level: max
3 | checkMissingIterableValueType: false
4 | paths:
5 | - src
6 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | ./tests
11 |
12 |
13 |
14 |
15 |
16 | src
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/AbstractValidation.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | protected $errors = [];
13 |
14 | /**
15 | * @var array
16 | */
17 | protected $errorMessages = [
18 | 'expectedN' => '{dataName}invalid data, expected {nExpected} element{nExpectedPlural}, received {nReceived} element{nReceivedPlural}',
19 | 'expected' => '{dataName}invalid data, expected {expectedType} [{keysExpected}], received [{keysReceived}]',
20 | 'type' => '{dataName}invalid type for key [{key}], type {expectedType} is expected',
21 | ];
22 |
23 | /**
24 | * @param string $type
25 | * @param array $context
26 | * @return string
27 | */
28 | protected function getErrorMessage(string $type, array $context): string
29 | {
30 | $message = $this->errorMessages[$type];
31 | $replace = [];
32 |
33 | foreach ($context as $key => $val) {
34 | // check that the value can be casted to string
35 | if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
36 | $replace['{' . $key . '}'] = $val;
37 | }
38 | }
39 | return strtr($message, $replace);
40 | }
41 |
42 | /**
43 | * @return string|null
44 | */
45 | public function getLastError(): ?string
46 | {
47 | $lastKey = array_key_last($this->errors);
48 | if ($lastKey === null) {
49 | return $lastKey;
50 | }
51 | return $this->errors[$lastKey];
52 | }
53 |
54 | /**
55 | * @return bool
56 | */
57 | public function hasErrors(): bool
58 | {
59 | return !empty($this->errors);
60 | }
61 |
62 | /**
63 | * @return array
64 | */
65 | public function getErrors(): array
66 | {
67 | return $this->errors;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/Exception/ArrayValidationExceptionInterface.php:
--------------------------------------------------------------------------------
1 | compiler = $compiler;
38 | $this->schema = $schema;
39 | $this->schemaName = $schemaName;
40 | }
41 |
42 | /**
43 | * @return string
44 | */
45 | public function getName(): string
46 | {
47 | return $this->schemaName;
48 | }
49 |
50 | /**
51 | * @return ValidationDefinition
52 | * @throws Exception\InvalidStructureException
53 | * @throws Exception\InvalidTypeException
54 | */
55 | public function compile(): ValidationDefinition
56 | {
57 | return $this->compiler->compileSchema($this->schema);
58 | }
59 |
60 | /**
61 | * @inheritDoc
62 | * @return array
63 | */
64 | public function jsonSerialize()
65 | {
66 | return $this->schema;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/SchemaCompiler.php:
--------------------------------------------------------------------------------
1 | $fieldDefinition) {
20 | if (is_string($fieldName) && is_array($fieldDefinition)) {
21 | $this->handleFieldDefinition($fieldName, $fieldDefinition, $definition);
22 | }
23 | }
24 |
25 | // handle "required"
26 | $this->handleRequiredFields($schema, $definition);
27 |
28 | return $definition;
29 | }
30 |
31 | /**
32 | * @param string $fieldName
33 | * @param array $fieldDefinition
34 | * @param ValidationDefinition $definition
35 | * @throws Exception\InvalidStructureException
36 | * @throws Exception\InvalidTypeException
37 | */
38 | private function handleFieldDefinition(string $fieldName, array $fieldDefinition, ValidationDefinition $definition): void
39 | {
40 | (new StrictValidation($fieldDefinition, 'compile.schema.field.' . $fieldName))
41 | ->expectOnlyKeys([
42 | 'comment', 'type', 'nullable', 'required', 'default', 'values'
43 | ])
44 | ->expectKeysToBeBoolean([
45 | 'nullable', 'required'
46 | ]);
47 |
48 | // handle "type" and "nullable"
49 | if (isset($fieldDefinition['type'])) {
50 | $method = 'expectKeyToBe' . ucfirst($fieldDefinition['type']);
51 | $definition->$method($fieldName, $fieldDefinition['nullable'] ?? false);
52 | }
53 | }
54 |
55 | /**
56 | * @param array $schema
57 | * @param ValidationDefinition $definition
58 | */
59 | private function handleRequiredFields(array $schema, ValidationDefinition $definition): void
60 | {
61 | $definition->expectOnlyKeys(array_keys($schema));
62 | $atLeastKeys = [];
63 | $fieldCount = 0;
64 | $requiredFieldCount = 0;
65 | foreach ($schema as $field => $fieldDef) {
66 | if (is_array($fieldDef)) {
67 | ++$fieldCount;
68 | if (isset($fieldDef['required']) && $fieldDef['required'] === true) {
69 | $atLeastKeys[] = $field;
70 | ++$requiredFieldCount;
71 | }
72 | }
73 | }
74 |
75 | if ($requiredFieldCount == $fieldCount) {
76 | $definition->expectExactlyKeys($atLeastKeys);
77 | } else {
78 | $definition->expectAtLeastKeys($atLeastKeys);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/SchemaCompilerInterface.php:
--------------------------------------------------------------------------------
1 | checkStructureErrors();
21 | }
22 |
23 | /**
24 | * @param array $keys
25 | * @return $this
26 | * @throws InvalidStructureException
27 | */
28 | public function expectAtLeastKeys(array $keys)
29 | {
30 | parent::expectAtLeastKeys($keys);
31 | return $this->checkStructureErrors();
32 | }
33 |
34 | /**
35 | * @param array $keys
36 | * @return $this
37 | * @throws InvalidStructureException
38 | */
39 | public function expectOnlyKeys(array $keys)
40 | {
41 | parent::expectOnlyKeys($keys);
42 | return $this->checkStructureErrors();
43 | }
44 |
45 | /**
46 | * @param array $keys
47 | * @return $this
48 | * @throws InvalidStructureException
49 | */
50 | public function expectOnlyOneFromKeys(array $keys)
51 | {
52 | parent::expectOnlyOneFromKeys($keys);
53 | return $this->checkStructureErrors();
54 | }
55 |
56 | /**
57 | * @param int $n
58 | * @return $this
59 | * @throws InvalidStructureException
60 | */
61 | public function expectNKeys(int $n)
62 | {
63 | parent::expectNKeys($n);
64 | return $this->checkStructureErrors();
65 | }
66 |
67 | /**
68 | * @param string $key
69 | * @param bool $acceptNull
70 | * @return $this
71 | * @throws InvalidTypeException
72 | */
73 | public function expectKeyToBeArray(string $key, bool $acceptNull = false)
74 | {
75 | parent::expectKeyToBeArray($key, $acceptNull);
76 | return $this->checkTypeErrors();
77 | }
78 |
79 | /**
80 | * @param string $key
81 | * @param bool $acceptNull
82 | * @return $this
83 | * @throws InvalidTypeException
84 | */
85 | public function expectKeyToBeInteger(string $key, bool $acceptNull = false)
86 | {
87 | parent::expectKeyToBeInteger($key, $acceptNull);
88 | return $this->checkTypeErrors();
89 | }
90 |
91 | /**
92 | * @param string $key
93 | * @param bool $acceptNull
94 | * @return $this
95 | * @throws InvalidTypeException
96 | */
97 | public function expectKeyToBeFloat(string $key, bool $acceptNull = false)
98 | {
99 | parent::expectKeyToBeFloat($key, $acceptNull);
100 | return $this->checkTypeErrors();
101 | }
102 |
103 | /**
104 | * @param string $key
105 | * @param bool $acceptNull
106 | * @return $this
107 | * @throws InvalidTypeException
108 | */
109 | public function expectKeyToBeString(string $key, bool $acceptNull = false)
110 | {
111 | parent::expectKeyToBeString($key, $acceptNull);
112 | return $this->checkTypeErrors();
113 | }
114 |
115 | /**
116 | * @param string $key
117 | * @param bool $acceptNull
118 | * @return $this
119 | * @throws InvalidTypeException
120 | */
121 | public function expectKeyToBeBoolean(string $key, bool $acceptNull = false)
122 | {
123 | parent::expectKeyToBeBoolean($key, $acceptNull);
124 | return $this->checkTypeErrors();
125 | }
126 |
127 | /**
128 | * @param array $keys
129 | * @param bool $acceptNull
130 | * @return $this|Validation
131 | * @throws InvalidTypeException
132 | */
133 | public function expectKeysToBeString(array $keys, bool $acceptNull = false)
134 | {
135 | foreach ($keys as $key) {
136 | $this->expectKeyToBeString($key, $acceptNull);
137 | }
138 | return $this;
139 | }
140 |
141 | /**
142 | * @param array $keys
143 | * @param bool $acceptNull
144 | * @return $this|Validation
145 | * @throws InvalidTypeException
146 | */
147 | public function expectKeysToBeInteger(array $keys, bool $acceptNull = false)
148 | {
149 | foreach ($keys as $key) {
150 | $this->expectKeyToBeInteger($key, $acceptNull);
151 | }
152 | return $this;
153 | }
154 |
155 | /**
156 | * @param array $keys
157 | * @param bool $acceptNull
158 | * @return $this|Validation
159 | * @throws InvalidTypeException
160 | */
161 | public function expectKeysToBeFloat(array $keys, bool $acceptNull = false)
162 | {
163 | foreach ($keys as $key) {
164 | $this->expectKeyToBeFloat($key, $acceptNull);
165 | }
166 | return $this;
167 | }
168 |
169 | /**
170 | * @param array $keys
171 | * @param bool $acceptNull
172 | * @return $this|Validation
173 | * @throws InvalidTypeException
174 | */
175 | public function expectKeysToBeBoolean(array $keys, bool $acceptNull = false)
176 | {
177 | foreach ($keys as $key) {
178 | $this->expectKeyToBeBoolean($key, $acceptNull);
179 | }
180 | return $this;
181 | }
182 |
183 | /**
184 | * @param array $keys
185 | * @param bool $acceptNull
186 | * @return $this|Validation
187 | * @throws InvalidTypeException
188 | */
189 | public function expectKeysToBeArray(array $keys, bool $acceptNull = false)
190 | {
191 | foreach ($keys as $key) {
192 | $this->expectKeyToBeArray($key, $acceptNull);
193 | }
194 | return $this;
195 | }
196 |
197 | /**
198 | * @return $this
199 | * @throws InvalidStructureException
200 | */
201 | protected function checkStructureErrors()
202 | {
203 | if ($this->hasErrors()) {
204 | throw new InvalidStructureException($this->getLastError() ?? '');
205 | }
206 | return $this;
207 | }
208 |
209 | /**
210 | * @return $this
211 | * @throws InvalidTypeException
212 | */
213 | protected function checkTypeErrors()
214 | {
215 | if ($this->hasErrors()) {
216 | throw new InvalidTypeException($this->getLastError() ?? '');
217 | }
218 | return $this;
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/src/StrictValidationFromDefinition.php:
--------------------------------------------------------------------------------
1 | validationDefinition = $validationDefinition;
29 | parent::__construct($data, $dataName, $arrayValidation);
30 |
31 | (new ValidationDefinitionExecutor())->execute(
32 | $validationDefinition,
33 | $this
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/StrictValidationFromSchema.php:
--------------------------------------------------------------------------------
1 | getName(), $arrayValidation);
23 |
24 | $validationDefinition = $schema->compile();
25 |
26 | (new ValidationDefinitionExecutor())->execute(
27 | $validationDefinition,
28 | $this
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Validation.php:
--------------------------------------------------------------------------------
1 | data = $data;
33 | $this->dataName = $dataName;
34 | if (!isset($validator)) {
35 | $validator = new Validator();
36 | }
37 | $this->validator = $validator;
38 | }
39 |
40 | /**
41 | * @param array $keys
42 | * @return $this
43 | */
44 | public function expectExactlyKeys(array $keys)
45 | {
46 | if ($this->validator->expectExactlyKeys($this->data, $keys) === false) {
47 | $keysReceived = array_keys($this->data);
48 | natsort($keys);
49 | natsort($keysReceived);
50 | $this->errors[] = $this->getErrorMessage('expected', [
51 | 'expectedType' => 'exactly keys',
52 | 'keysExpected' => implode(', ', $keys),
53 | 'keysReceived' => implode(', ', $keysReceived)
54 | ]);
55 | }
56 | return $this;
57 | }
58 |
59 | /**
60 | * @param array $keys
61 | * @return $this
62 | */
63 | public function expectAtLeastKeys(array $keys)
64 | {
65 | if ($this->validator->expectAtLeastKeys($this->data, $keys) === false) {
66 | $keysReceived = array_keys($this->data);
67 | natsort($keys);
68 | natsort($keysReceived);
69 | $this->errors[] = $this->getErrorMessage('expected', [
70 | 'expectedType' => 'at least keys',
71 | 'keysExpected' => implode(', ', $keys),
72 | 'keysReceived' => implode(', ', $keysReceived)
73 | ]);
74 | }
75 | return $this;
76 | }
77 |
78 | /**
79 | * @param array $keys
80 | * @return $this
81 | */
82 | public function expectOnlyKeys(array $keys)
83 | {
84 | if ($this->validator->expectOnlyKeys($this->data, $keys) === false) {
85 | $keysReceived = array_keys($this->data);
86 | natsort($keys);
87 | natsort($keysReceived);
88 | $this->errors[] = $this->getErrorMessage('expected', [
89 | 'expectedType' => 'only keys',
90 | 'keysExpected' => implode(', ', $keys),
91 | 'keysReceived' => implode(', ', $keysReceived)
92 | ]);
93 | }
94 | return $this;
95 | }
96 |
97 | /**
98 | * @param array $keys
99 | * @return $this
100 | */
101 | public function expectOnlyOneFromKeys(array $keys)
102 | {
103 | if ($this->validator->expectOnlyOneFromKeys($this->data, $keys) === false) {
104 | $keysReceived = array_keys($this->data);
105 | natsort($keys);
106 | natsort($keysReceived);
107 | $this->errors[] = $this->getErrorMessage('expected', [
108 | 'expectedType' => 'only one of keys',
109 | 'keysExpected' => implode(', ', $keys),
110 | 'keysReceived' => implode(', ', $keysReceived)
111 | ]);
112 | }
113 | return $this;
114 | }
115 |
116 | /**
117 | * @param int $n
118 | * @return $this
119 | */
120 | public function expectNKeys(int $n)
121 | {
122 | if ($this->validator->expectNKeys($this->data, $n) === false) {
123 | $keysReceived = array_keys($this->data);
124 | natsort($keysReceived);
125 | $this->errors[] = $this->getErrorMessage('expectedN', [
126 | 'expectedType' => 'only N keys',
127 | 'nExpected' => $n,
128 | 'nExpectedPlural' => $n > 1 ? 's' : '',
129 | 'nReceivedPlural' => count($keysReceived) > 1 ? 's' : '',
130 | 'nReceived' => count($keysReceived)
131 | ]);
132 | }
133 | return $this;
134 | }
135 |
136 | /**
137 | * @param string $key
138 | * @param bool $acceptNull
139 | * @return $this
140 | */
141 | public function expectKeyToBeArray(string $key, bool $acceptNull = false)
142 | {
143 | if (array_key_exists($key, $this->data) && $this->validator->expectKeyToBeArray($this->data, $key, $acceptNull) === false) {
144 | $this->errors[] = $this->getErrorMessage('type', [
145 | 'key' => $key,
146 | 'expectedType' => 'array',
147 | ]);
148 | }
149 | return $this;
150 | }
151 |
152 | /**
153 | * @param string $key
154 | * @param bool $acceptNull
155 | * @return $this
156 | */
157 | public function expectKeyToBeInteger(string $key, bool $acceptNull = false)
158 | {
159 | if (array_key_exists($key, $this->data) && $this->validator->expectKeyToBeInteger($this->data, $key, $acceptNull) === false) {
160 | $this->errors[] = $this->getErrorMessage('type', [
161 | 'key' => $key,
162 | 'expectedType' => 'integer',
163 | ]);
164 | }
165 | return $this;
166 | }
167 |
168 | /**
169 | * @param string $key
170 | * @param bool $acceptNull
171 | * @return $this
172 | */
173 | public function expectKeyToBeFloat(string $key, bool $acceptNull = false)
174 | {
175 | if (array_key_exists($key, $this->data) && $this->validator->expectKeyToBeFloat($this->data, $key, $acceptNull) === false) {
176 | $this->errors[] = $this->getErrorMessage('type', [
177 | 'key' => $key,
178 | 'expectedType' => 'float',
179 | ]);
180 | }
181 | return $this;
182 | }
183 |
184 | /**
185 | * @param string $key
186 | * @param bool $acceptNull
187 | * @return $this
188 | */
189 | public function expectKeyToBeString(string $key, bool $acceptNull = false)
190 | {
191 | if (array_key_exists($key, $this->data) && $this->validator->expectKeyToBeString($this->data, $key, $acceptNull) === false) {
192 | $this->errors[] = $this->getErrorMessage('type', [
193 | 'key' => $key,
194 | 'expectedType' => 'string',
195 | ]);
196 | }
197 | return $this;
198 | }
199 |
200 | /**
201 | * @param string $key
202 | * @param bool $acceptNull
203 | * @return $this
204 | */
205 | public function expectKeyToBeBoolean(string $key, bool $acceptNull = false)
206 | {
207 | if (array_key_exists($key, $this->data) && $this->validator->expectKeyToBeBoolean($this->data, $key, $acceptNull) === false) {
208 | $this->errors[] = $this->getErrorMessage('type', [
209 | 'key' => $key,
210 | 'expectedType' => 'boolean',
211 | ]);
212 | }
213 | return $this;
214 | }
215 |
216 | /**
217 | * @param string $key
218 | * @param bool $acceptNull
219 | * @return $this
220 | */
221 | public function expectKeyToBeObject(string $key, bool $acceptNull = false)
222 | {
223 | if (array_key_exists($key, $this->data) && $this->validator->expectKeyToBeObject($this->data, $key, $acceptNull) === false) {
224 | $this->errors[] = $this->getErrorMessage('type', [
225 | 'key' => $key,
226 | 'expectedType' => 'object',
227 | ]);
228 | }
229 | return $this;
230 | }
231 |
232 | /**
233 | * @param array $keys
234 | * @param bool $acceptNull
235 | * @return $this
236 | */
237 | public function expectKeysToBeString(array $keys, bool $acceptNull = false)
238 | {
239 | foreach ($keys as $key) {
240 | $this->expectKeyToBeString($key, $acceptNull);
241 | }
242 | return $this;
243 | }
244 |
245 | /**
246 | * @param array $keys
247 | * @param bool $acceptNull
248 | * @return $this
249 | */
250 | public function expectKeysToBeInteger(array $keys, bool $acceptNull = false)
251 | {
252 | foreach ($keys as $key) {
253 | $this->expectKeyToBeInteger($key, $acceptNull);
254 | }
255 | return $this;
256 | }
257 |
258 | /**
259 | * @param array $keys
260 | * @param bool $acceptNull
261 | * @return $this
262 | */
263 | public function expectKeysToBeFloat(array $keys, bool $acceptNull = false)
264 | {
265 | foreach ($keys as $key) {
266 | $this->expectKeyToBeFloat($key, $acceptNull);
267 | }
268 | return $this;
269 | }
270 |
271 | /**
272 | * @param array $keys
273 | * @param bool $acceptNull
274 | * @return $this
275 | */
276 | public function expectKeysToBeBoolean(array $keys, bool $acceptNull = false)
277 | {
278 | foreach ($keys as $key) {
279 | $this->expectKeyToBeBoolean($key, $acceptNull);
280 | }
281 | return $this;
282 | }
283 |
284 | /**
285 | * @param array $keys
286 | * @param bool $acceptNull
287 | * @return $this
288 | */
289 | public function expectKeysToBeArray(array $keys, bool $acceptNull = false)
290 | {
291 | foreach ($keys as $key) {
292 | $this->expectKeyToBeArray($key, $acceptNull);
293 | }
294 | return $this;
295 | }
296 |
297 | /**
298 | * @param array $keys
299 | * @param bool $acceptNull
300 | * @return $this
301 | */
302 | public function expectKeysToBeObject(array $keys, bool $acceptNull = false)
303 | {
304 | foreach ($keys as $key) {
305 | $this->expectKeyToBeObject($key, $acceptNull);
306 | }
307 | return $this;
308 | }
309 |
310 | /**
311 | * @return string|null
312 | */
313 | protected function getExceptionDataName(): ?string
314 | {
315 | if (isset($this->dataName)) {
316 | return '['. $this->dataName.'] ';
317 | }
318 | return null;
319 | }
320 |
321 | /**
322 | * @param string $type
323 | * @param array $context
324 | * @return string
325 | */
326 | protected function getErrorMessage(string $type, array $context): string
327 | {
328 | $context = array_merge(['dataName' => $this->getExceptionDataName()], $context);
329 | return parent::getErrorMessage($type, $context);
330 | }
331 | }
332 |
--------------------------------------------------------------------------------
/src/ValidationBuilder.php:
--------------------------------------------------------------------------------
1 | errors = $validation->getErrors();
27 | $this->lastError = $validation->getLastError();
28 | return !$validation->hasErrors();
29 | }
30 |
31 | /**
32 | * @param array $data
33 | * @throw InvalidStructureException
34 | * @throw InvalidTypeException
35 | */
36 | public function strictValidate(array $data): void
37 | {
38 | new StrictValidationFromDefinition($this, $data);
39 | }
40 |
41 | /**
42 | * @return array
43 | */
44 | public function getErrors(): array
45 | {
46 | return $this->errors;
47 | }
48 |
49 | /**
50 | * @return string|null
51 | */
52 | public function getLastError(): ?string
53 | {
54 | return $this->lastError;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/ValidationDefinition.php:
--------------------------------------------------------------------------------
1 | [],
16 | 'expectOnlyOneFromKeys' => [],
17 | 'expectAtLeastKeys' => [],
18 | 'expectOnlyKeys' => [],
19 | 'expectNKeys' => [],
20 | 'expectKeyToBeArray' => [],
21 | 'expectKeysToBeArray' => [],
22 | 'expectKeyToBeInteger' => [],
23 | 'expectKeysToBeInteger' => [],
24 | 'expectKeyToBeFloat' => [],
25 | 'expectKeysToBeFloat' => [],
26 | 'expectKeyToBeString' => [],
27 | 'expectKeysToBeString' => [],
28 | 'expectKeyToBeBoolean' => [],
29 | 'expectKeysToBeBoolean' => [],
30 | 'expectKeyToBeObject' => [],
31 | 'expectKeysToBeObject' => [],
32 | ];
33 |
34 | /**
35 | * @return array
36 | */
37 | public function getValidations(): array
38 | {
39 | $validations = [];
40 | foreach ($this->validations as $name => $args) {
41 | if (!empty($args)) {
42 | $validations[$name] = $args;
43 | }
44 | }
45 | return $validations;
46 | }
47 |
48 | /**
49 | * @param array $keys
50 | * @return $this
51 | */
52 | public function expectExactlyKeys(array $keys)
53 | {
54 | return $this->addValidation(__FUNCTION__, func_get_args());
55 | }
56 |
57 | /**
58 | * @param array $keys
59 | * @return $this
60 | */
61 | public function expectOnlyOneFromKeys(array $keys)
62 | {
63 | return $this->addValidation(__FUNCTION__, func_get_args());
64 | }
65 |
66 | /**
67 | * @param array $keys
68 | * @return $this
69 | */
70 | public function expectAtLeastKeys(array $keys)
71 | {
72 | return $this->addValidation(__FUNCTION__, func_get_args());
73 | }
74 |
75 | /**
76 | * @param array $keys
77 | * @return $this
78 | */
79 | public function expectOnlyKeys(array $keys)
80 | {
81 | return $this->addValidation(__FUNCTION__, func_get_args());
82 | }
83 |
84 | /**
85 | * @param int $n
86 | * @return $this
87 | */
88 | public function expectNKeys(int $n)
89 | {
90 | return $this->addValidation(__FUNCTION__, func_get_args());
91 | }
92 |
93 | /**
94 | * @param string $key
95 | * @param bool $acceptNull
96 | * @return $this
97 | */
98 | public function expectKeyToBeArray(string $key, bool $acceptNull = false)
99 | {
100 | return $this->addValidation(__FUNCTION__, func_get_args());
101 | }
102 |
103 | /**
104 | * @param array $keys
105 | * @param bool $acceptNull
106 | * @return $this
107 | */
108 | public function expectKeysToBeArray(array $keys, bool $acceptNull = false)
109 | {
110 | return $this->addValidation(__FUNCTION__, func_get_args());
111 | }
112 |
113 | /**
114 | * @param string $key
115 | * @param bool $acceptNull
116 | * @return $this
117 | */
118 | public function expectKeyToBeInteger(string $key, bool $acceptNull = false)
119 | {
120 | return $this->addValidation(__FUNCTION__, func_get_args());
121 | }
122 |
123 | /**
124 | * @param array $keys
125 | * @param bool $acceptNull
126 | * @return $this
127 | */
128 | public function expectKeysToBeInteger(array $keys, bool $acceptNull = false)
129 | {
130 | return $this->addValidation(__FUNCTION__, func_get_args());
131 | }
132 |
133 | /**
134 | * @param string $key
135 | * @param bool $acceptNull
136 | * @return $this
137 | */
138 | public function expectKeyToBeFloat(string $key, bool $acceptNull = false)
139 | {
140 | return $this->addValidation(__FUNCTION__, func_get_args());
141 | }
142 |
143 | /**
144 | * @param array $keys
145 | * @param bool $acceptNull
146 | * @return $this
147 | */
148 | public function expectKeysToBeFloat(array $keys, bool $acceptNull = false)
149 | {
150 | return $this->addValidation(__FUNCTION__, func_get_args());
151 | }
152 |
153 | /**
154 | * @param string $key
155 | * @param bool $acceptNull
156 | * @return $this
157 | */
158 | public function expectKeyToBeString(string $key, bool $acceptNull = false)
159 | {
160 | return $this->addValidation(__FUNCTION__, func_get_args());
161 | }
162 |
163 | /**
164 | * @param array $keys
165 | * @param bool $acceptNull
166 | * @return $this
167 | */
168 | public function expectKeysToBeString(array $keys, bool $acceptNull = false)
169 | {
170 | return $this->addValidation(__FUNCTION__, func_get_args());
171 | }
172 |
173 | /**
174 | * @param string $key
175 | * @param bool $acceptNull
176 | * @return $this
177 | */
178 | public function expectKeyToBeBoolean(string $key, bool $acceptNull = false)
179 | {
180 | return $this->addValidation(__FUNCTION__, func_get_args());
181 | }
182 |
183 | /**
184 | * @param array $keys
185 | * @param bool $acceptNull
186 | * @return $this
187 | */
188 | public function expectKeysToBeBoolean(array $keys, bool $acceptNull = false)
189 | {
190 | return $this->addValidation(__FUNCTION__, func_get_args());
191 | }
192 |
193 | /**
194 | * @param string $key
195 | * @param bool $acceptNull
196 | * @return $this
197 | */
198 | public function expectKeyToBeObject(string $key, bool $acceptNull = false)
199 | {
200 | return $this->addValidation(__FUNCTION__, func_get_args());
201 | }
202 |
203 | /**
204 | * @param array $keys
205 | * @param bool $acceptNull
206 | * @return $this
207 | */
208 | public function expectKeysToBeObject(array $keys, bool $acceptNull = false)
209 | {
210 | return $this->addValidation(__FUNCTION__, func_get_args());
211 | }
212 |
213 | /**
214 | * @inheritDoc
215 | * @return array
216 | */
217 | public function jsonSerialize()
218 | {
219 | return $this->getValidations();
220 | }
221 |
222 | /**
223 | * @param string $validationName
224 | * @param array $validationArgs
225 | * @return $this
226 | */
227 | protected function addValidation(string $validationName, array $validationArgs)
228 | {
229 | $this->validations[$validationName][] = $validationArgs;
230 | return $this;
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/src/ValidationDefinitionExecutor.php:
--------------------------------------------------------------------------------
1 | getValidations();
14 | foreach ($validations as $name => $multipleArgs) {
15 | foreach ($multipleArgs as $args) {
16 | $callable = [$validation, $name];
17 | if (is_callable($callable)) {
18 | call_user_func_array($callable, $args);
19 | }
20 | }
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/ValidationFromDefinition.php:
--------------------------------------------------------------------------------
1 | validationDefinition = $validationDefinition;
28 | parent::__construct($data, $dataName, $arrayValidation);
29 |
30 | (new ValidationDefinitionExecutor())->execute(
31 | $validationDefinition,
32 | $this
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/ValidationFromSchema.php:
--------------------------------------------------------------------------------
1 | getName(), $arrayValidation);
23 |
24 | $validationDefinition = $schema->compile();
25 | (new ValidationDefinitionExecutor())->execute(
26 | $validationDefinition,
27 | $this
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ValidationInterface.php:
--------------------------------------------------------------------------------
1 | $expectedCount) {
19 | return false;
20 | }
21 | $actuallyCount = 0;
22 | foreach ($keysName as $key) {
23 | if (array_key_exists($key, $array)) {
24 | ++$actuallyCount;
25 | }
26 | }
27 | return ($actuallyCount === $expectedCount);
28 | }
29 |
30 | /**
31 | * The array should be length of 1 and have a key from expected keys
32 | * @param array $array
33 | * @param array $keysName
34 | * @return bool
35 | */
36 | public function expectOnlyOneFromKeys(array $array, array $keysName): bool
37 | {
38 | if (count($array) <> 1) {
39 | return false;
40 | }
41 | $keys = array_keys($array);
42 | return in_array($keys[0], $keysName);
43 | }
44 |
45 | /**
46 | * The array should have at least expected keys
47 | * @param array $array
48 | * @param array $keysName
49 | * @return bool
50 | */
51 | public function expectAtLeastKeys(array $array, array $keysName): bool
52 | {
53 | foreach ($keysName as $key) {
54 | if (!array_key_exists($key, $array)) {
55 | return false;
56 | }
57 | }
58 | return true;
59 | }
60 |
61 | /**
62 | * The array keys must be in keys name.
63 | * @param array $array
64 | * @param array $keysName
65 | * @return bool
66 | */
67 | public function expectOnlyKeys(array $array, array $keysName): bool
68 | {
69 | foreach (array_keys($array) as $key) {
70 | if (!in_array($key, $keysName)) {
71 | return false;
72 | }
73 | }
74 | return true;
75 | }
76 |
77 | /**
78 | * The array should be exactly the length of X
79 | * @param array $array
80 | * @param int $n
81 | * @return bool
82 | */
83 | public function expectNKeys(array $array, int $n): bool
84 | {
85 | return ($n == count($array));
86 | }
87 |
88 | /**
89 | * @param array $array
90 | * @param string $key
91 | * @param bool $acceptNull
92 | * @return bool
93 | */
94 | public function expectKeyToBeArray(array $array, string $key, bool $acceptNull = false): bool
95 | {
96 | return $this->internalTypeValidation('is_array', $array, $key, $acceptNull);
97 | }
98 |
99 | /**
100 | * @param array $array
101 | * @param array $keys
102 | * @param bool $acceptNull
103 | * @return bool
104 | */
105 | public function expectKeysToBeArray(array $array, array $keys, bool $acceptNull = false): bool
106 | {
107 | foreach ($keys as $key) {
108 | if ($this->expectKeyToBeArray($array, $key, $acceptNull) === false) {
109 | return false;
110 | }
111 | }
112 | return true;
113 | }
114 |
115 | /**
116 | * @param array $array
117 | * @param string $key
118 | * @param bool $acceptNull
119 | * @return bool
120 | */
121 | public function expectKeyToBeInteger(array $array, string $key, bool $acceptNull = false): bool
122 | {
123 | return $this->internalTypeValidation('is_integer', $array, $key, $acceptNull);
124 | }
125 |
126 | /**
127 | * @param array $array
128 | * @param array $keys
129 | * @param bool $acceptNull
130 | * @return bool
131 | */
132 | public function expectKeysToBeInteger(array $array, array $keys, bool $acceptNull = false): bool
133 | {
134 | foreach ($keys as $key) {
135 | if ($this->expectKeyToBeInteger($array, $key, $acceptNull) === false) {
136 | return false;
137 | }
138 | }
139 | return true;
140 | }
141 |
142 | /**
143 | * @param array $array
144 | * @param string $key
145 | * @param bool $acceptNull
146 | * @return bool
147 | */
148 | public function expectKeyToBeString(array $array, string $key, bool $acceptNull = false): bool
149 | {
150 | return $this->internalTypeValidation('is_string', $array, $key, $acceptNull);
151 | }
152 |
153 | /**
154 | * @param array $array
155 | * @param array $keys
156 | * @param bool $acceptNull
157 | * @return bool
158 | */
159 | public function expectKeysToBeString(array $array, array $keys, bool $acceptNull = false): bool
160 | {
161 | foreach ($keys as $key) {
162 | if ($this->expectKeyToBeString($array, $key, $acceptNull) === false) {
163 | return false;
164 | }
165 | }
166 | return true;
167 | }
168 |
169 | /**
170 | * @param array $array
171 | * @param string $key
172 | * @param bool $acceptNull
173 | * @return bool
174 | */
175 | public function expectKeyToBeFloat(array $array, string $key, bool $acceptNull = false): bool
176 | {
177 | return $this->internalTypeValidation('is_float', $array, $key, $acceptNull);
178 | }
179 |
180 | /**
181 | * @param array $array
182 | * @param array $keys
183 | * @param bool $acceptNull
184 | * @return bool
185 | */
186 | public function expectKeysToBeFloat(array $array, array $keys, bool $acceptNull = false): bool
187 | {
188 | foreach ($keys as $key) {
189 | if ($this->expectKeyToBeFloat($array, $key, $acceptNull) === false) {
190 | return false;
191 | }
192 | }
193 | return true;
194 | }
195 |
196 | /**
197 | * @param array $array
198 | * @param string $key
199 | * @param bool $acceptNull
200 | * @return bool
201 | */
202 | public function expectKeyToBeBoolean(array $array, string $key, bool $acceptNull = false): bool
203 | {
204 | return $this->internalTypeValidation('is_bool', $array, $key, $acceptNull);
205 | }
206 |
207 | /**
208 | * @param array $array
209 | * @param array $keys
210 | * @param bool $acceptNull
211 | * @return bool
212 | */
213 | public function expectKeysToBeBoolean(array $array, array $keys, bool $acceptNull = false): bool
214 | {
215 | foreach ($keys as $key) {
216 | if ($this->expectKeyToBeBoolean($array, $key, $acceptNull) === false) {
217 | return false;
218 | }
219 | }
220 | return true;
221 | }
222 |
223 | /**
224 | * @param array $array
225 | * @param string $key
226 | * @param bool $acceptNull
227 | * @return bool
228 | */
229 | public function expectKeyToBeObject(array $array, string $key, bool $acceptNull = false): bool
230 | {
231 | return $this->internalTypeValidation('is_object', $array, $key, $acceptNull);
232 | }
233 |
234 | /**
235 | * @param array $array
236 | * @param array $keys
237 | * @param bool $acceptNull
238 | * @return bool
239 | */
240 | public function expectKeysToBeObject(array $array, array $keys, bool $acceptNull = false): bool
241 | {
242 | foreach ($keys as $key) {
243 | if ($this->expectKeyToBeObject($array, $key, $acceptNull) === false) {
244 | return false;
245 | }
246 | }
247 | return true;
248 | }
249 |
250 | /**
251 | * @param string $method
252 | * @param array $array
253 | * @param string $key
254 | * @param bool $acceptNull
255 | * @return bool
256 | */
257 | private function internalTypeValidation(string $method, array $array, string $key, bool $acceptNull = false): bool
258 | {
259 | return !(
260 | (!array_key_exists($key, $array)) ||
261 | (!$acceptNull && !$method($array[$key])) ||
262 | ($acceptNull && ($array[$key] !== null && !$method($array[$key])))
263 | );
264 | }
265 |
266 |
267 |
268 | }
269 |
--------------------------------------------------------------------------------
/src/ValidatorInterface.php:
--------------------------------------------------------------------------------
1 | 'category.schema',
23 | 'field1' => [
24 | 'type' => 'array',
25 | 'required' => true
26 | ],
27 | 'field2' => [
28 | 'type' => 'string',
29 | 'required' => true
30 | ],
31 | ],
32 | [ // data
33 | 'field1' => [],
34 | 'field2' => 'strong'
35 | ]
36 | ],
37 | [
38 | [ // schema
39 | 'name' => 'post.schema',
40 | 'field1' => [
41 | 'type' => 'array',
42 | 'required' => true
43 | ],
44 | 'field2' => [
45 | 'type' => 'string',
46 | 'required' => false,
47 | 'nullable' => true,
48 | ],
49 | ],
50 | [ // data
51 | 'field1' => [],
52 | 'field2' => null
53 | ]
54 | ],
55 | ];
56 | }
57 |
58 | /**
59 | * @dataProvider dataProvider
60 | * @param $schema
61 | * @param $data
62 | * @throws InvalidStructureException
63 | * @throws InvalidTypeException
64 | */
65 | public function testExpectExactlyKeys($schema, $data)
66 | {
67 | $def = new SchemaCompiler();
68 | $validationDefinition = $def->compileSchema($schema);
69 | $this->assertInstanceOf(ValidationInterface::class, $validationDefinition);
70 | new StrictValidationFromDefinition($validationDefinition, $data);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/tests/SchemaTest.php:
--------------------------------------------------------------------------------
1 | [
24 | 'type' => 'array',
25 | 'required' => true
26 | ],
27 | 'field2' => [
28 | 'type' => 'string',
29 | 'required' => true
30 | ],
31 | ],
32 | [ // data
33 | 'field1' => [],
34 | 'field2' => 'strong'
35 | ]
36 | ],
37 | [
38 | [ // schema
39 | 'field1' => [
40 | 'type' => 'array',
41 | 'required' => true
42 | ],
43 | 'field2' => [
44 | 'type' => 'string',
45 | 'required' => false,
46 | 'nullable' => true,
47 | ],
48 | ],
49 | [ // data
50 | 'field1' => [],
51 | 'field2' => null
52 | ]
53 | ],
54 | ];
55 | }
56 |
57 | /**
58 | * @dataProvider dataProvider
59 | * @param $schema
60 | * @param $data
61 | * @throws InvalidStructureException
62 | * @throws InvalidTypeException
63 | */
64 | public function testExpectExactlyKeys($schema, $data)
65 | {
66 | $compiler = new SchemaCompiler();
67 | $schema = new Schema($compiler, $schema, 'myName');
68 | $validationDefinition = $schema->compile();
69 | $this->assertInstanceOf(ValidationInterface::class, $validationDefinition);
70 | $this->assertTrue($schema->getName() === 'myName');
71 | new StrictValidationFromDefinition($validationDefinition, $data);
72 | }
73 |
74 | public function testJsonSerialize()
75 | {
76 | $compiler = new SchemaCompiler();
77 | $schema = new Schema($compiler, ['schema'], 'myName');
78 | $this->assertTrue(json_encode($schema) === '["schema"]');
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/tests/StrictValidationTest.php:
--------------------------------------------------------------------------------
1 | 'foo',
16 | 'content' => 'foobar',
17 | ];
18 |
19 | private $data2 = [
20 | 'id' => 1,
21 | 'title' => 'foo',
22 | 'isPrivate' => true,
23 | 'tags' => ['tag1', ''],
24 | 'money' => 15.55
25 | ];
26 |
27 | private $data3 = [
28 | 'title' => null,
29 | 'views' => 45,
30 | 'comments' => []
31 | ];
32 |
33 | /**
34 | * @throws InvalidStructureException
35 | * @throws InvalidTypeException
36 | */
37 | public function testNoException1()
38 | {
39 | $strictValidator = new StrictValidation($this->data1);
40 |
41 | $strictValidator
42 | ->expectAtLeastKeys(['title', 'content'])
43 | ->expectExactlyKeys(['title', 'content'])
44 | ->expectOnlyKeys(['title', 'content'])
45 | ->expectKeysToBeString(['title', 'content']);
46 |
47 | $this->assertTrue(true);
48 | }
49 |
50 | /**
51 | * @throws InvalidStructureException
52 | * @throws InvalidTypeException
53 | */
54 | public function testNoException2()
55 | {
56 | $strictValidator = new StrictValidation($this->data2);
57 |
58 | $strictValidator
59 | ->expectOnlyKeys(['id', 'title', 'isPrivate', 'tags', 'money'])
60 | ->expectKeysToBeInteger(['id'])
61 | ->expectKeysToBeString(['title'])
62 | ->expectKeysToBeBoolean(['isPrivate'])
63 | ->expectKeysToBeArray(['tags'])
64 | ->expectKeysToBeFloat(['money']);
65 |
66 | $this->assertTrue(true);
67 | }
68 |
69 | /**
70 | * @throws InvalidStructureException
71 | */
72 | public function testOnlyKeysException()
73 | {
74 | $this->expectException(InvalidStructureException::class);
75 | $strictValidator = new StrictValidation(['title' => 1]);
76 | $strictValidator->expectOnlyKeys(['name']);
77 | }
78 |
79 | /**
80 | * @throws InvalidStructureException
81 | */
82 | public function testNKeysException()
83 | {
84 | $this->expectException(InvalidStructureException::class);
85 | $strictValidator = new StrictValidation(['title' => 1, 'description' => 'foo']);
86 | $strictValidator->expectNKeys(1);
87 | }
88 |
89 | /**
90 | * @throws InvalidStructureException
91 | */
92 | public function testNKeysNoException()
93 | {
94 | $strictValidator = new StrictValidation(['title' => 1]);
95 | $strictValidator->expectNKeys(1);
96 | $this->assertTrue(true);
97 | }
98 |
99 | /**
100 | * @throws InvalidStructureException
101 | */
102 | public function testOnlyOneFromKeysException()
103 | {
104 | $this->expectException(InvalidStructureException::class);
105 | $strictValidator = new StrictValidation(['title' => 'x', 'description' => 'foo']);
106 | $strictValidator->expectOnlyOneFromKeys(['title', 'description']);
107 | }
108 |
109 | /**
110 | * @throws InvalidStructureException
111 | */
112 | public function testExactlyKeysException()
113 | {
114 | $this->expectException(InvalidStructureException::class);
115 | $strictValidator = new StrictValidation(['title' => 1]);
116 | $strictValidator->expectExactlyKeys(['name']);
117 | }
118 |
119 | /**
120 | * @throws InvalidStructureException
121 | */
122 | public function testOnlyOneFromKeysNoException()
123 | {
124 | $strictValidator = new StrictValidation(['title' => 1]);
125 | $strictValidator->expectOnlyOneFromKeys(['name', 'title']);
126 | $this->assertTrue(true);
127 | }
128 |
129 | /**
130 | * @throws InvalidTypeException
131 | */
132 | public function testInvalidStringException()
133 | {
134 | $this->expectException(InvalidTypeException::class);
135 | $strictValidator = new StrictValidation(['title' => 1]);
136 | $strictValidator->expectKeyToBeString('title');
137 | }
138 |
139 | /**
140 | * @throws InvalidTypeException
141 | */
142 | public function testInvalidArrayException()
143 | {
144 | $this->expectException(InvalidTypeException::class);
145 | $strictValidator = new StrictValidation(['tags' => 1]);
146 | $strictValidator->expectKeyToBeArray('tags');
147 | }
148 | /**
149 | * @throws InvalidTypeException
150 | */
151 | public function testInvalidBooleanException()
152 | {
153 | $this->expectException(InvalidTypeException::class);
154 | $strictValidator = new StrictValidation(['isPrivate' => 1]);
155 | $strictValidator->expectKeyToBeBoolean('isPrivate');
156 | }
157 |
158 | /**
159 | * @throws InvalidTypeException
160 | */
161 | public function testInvalidFloatException()
162 | {
163 | $this->expectException(InvalidTypeException::class);
164 | $strictValidator = new StrictValidation(['money' => 1]);
165 | $strictValidator->expectKeyToBeFloat('money');
166 | }
167 |
168 | /**
169 | * @throws InvalidStructureException
170 | * @throws InvalidTypeException
171 | */
172 | public function testWithInvalidTypeException()
173 | {
174 | $this->expectException(InvalidTypeException::class);
175 |
176 | $strictValidator = new StrictValidation($this->data1);
177 |
178 | $strictValidator
179 | ->expectAtLeastKeys(['title', 'content'])
180 | ->expectExactlyKeys(['title', 'content'])
181 | ->expectOnlyKeys(['title', 'content'])
182 | ->expectKeysToBeInteger(['title', 'content']);
183 |
184 | $this->assertTrue(true);
185 | }
186 |
187 | /**
188 | * @throws InvalidStructureException
189 | * @throws InvalidTypeException
190 | */
191 | public function testWithInvalidStructureException()
192 | {
193 | $this->expectException(InvalidStructureException::class);
194 |
195 | $strictValidator = new StrictValidation($this->data3, 'my data');
196 |
197 | $strictValidator
198 | ->expectAtLeastKeys(['title', 'content'])
199 | ->expectExactlyKeys(['title', 'content'])
200 | ->expectOnlyKeys(['title', 'content'])
201 | ->expectKeysToBeInteger(['title', 'content']);
202 |
203 | $this->assertTrue(true);
204 | }
205 | }
--------------------------------------------------------------------------------
/tests/ValidationBuilderTest.php:
--------------------------------------------------------------------------------
1 | expectNKeys(2)
18 | ->expectAtLeastKeys(['title', 'content'])
19 | ->expectExactlyKeys(['title', 'content'])
20 | ->expectOnlyKeys(['title', 'content'])
21 | ->expectKeysToBeString(['title', 'content'], true);
22 |
23 | $data = [
24 | 'title' => 'test',
25 | 'content' => 'test',
26 | ];
27 |
28 | $validationPass = $validation->validate($data);
29 | $this->assertTrue($validationPass);
30 | $this->assertTrue($validation->getErrors() === []);
31 | $this->assertTrue($validation->getLastError() === null);
32 | }
33 |
34 | public function testStrictValidate()
35 | {
36 | $validation = new ValidationBuilder();
37 | $validation
38 | ->expectNKeys(2)
39 | ->expectAtLeastKeys(['title', 'content'])
40 | ->expectExactlyKeys(['title', 'content'])
41 | ->expectOnlyKeys(['title', 'content'])
42 | ->expectKeysToBeString(['title', 'content'], true);
43 |
44 | $data = [
45 | 'title' => 'test',
46 | 'content' => 'test',
47 | ];
48 |
49 | $validation->strictValidate($data);
50 | $this->assertTrue(true);
51 | }
52 |
53 | public function testStrictValidateException()
54 | {
55 | $validation = new ValidationBuilder();
56 | $validation
57 | ->expectNKeys(2)
58 | ->expectAtLeastKeys(['title', 'content'])
59 | ->expectExactlyKeys(['title', 'content'])
60 | ->expectOnlyKeys(['title', 'content'])
61 | ->expectKeysToBeString(['title', 'content'], true);
62 |
63 | $data = [
64 | 'title' => 1,
65 | 'content' => 'test',
66 | ];
67 |
68 | $this->expectException(ArrayValidationExceptionInterface::class);
69 | $validation->strictValidate($data);
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/tests/ValidationDefinitionTest.php:
--------------------------------------------------------------------------------
1 | expectAtLeastKeys(['title', 'content'])
24 | ->expectExactlyKeys(['title', 'content'])
25 | ->expectOnlyKeys(['title', 'content'])
26 | ->expectKeysToBeString(['title', 'content'], true);
27 |
28 | $validations = $arrayDefinition->getValidations();
29 | $this->assertTrue(is_array($validations));
30 | $this->assertTrue(count($validations) === 4);
31 | }
32 |
33 | public function testGetDefinition2()
34 | {
35 | $arrayDefinition = new ValidationDefinition();
36 |
37 | $arrayDefinition
38 | ->expectOnlyKeys(['title', 'content', 'description', 'id', 'number', 'amount', 'fields', 'isPrivate', 'person'])
39 | ->expectOnlyOneFromKeys(['title'])
40 | ->expectKeysToBeInteger(['id'])
41 | ->expectKeyToBeInteger('number')
42 | ->expectKeyToBeFloat('amount')
43 | ->expectKeysToBeFloat(['amount'])
44 | ->expectKeysToBeArray(['fields'])
45 | ->expectKeyToBeArray('fields')
46 | ->expectKeyToBeBoolean('isPrivate')
47 | ->expectKeysToBeBoolean(['isPrivate'])
48 | ->expectKeysToBeString(['title', 'content'], true)
49 | ->expectKeyToBeString('title', true)
50 | ->expectKeyToBeString('content', true)
51 | ->expectKeyToBeString('description', false)
52 | ->expectKeyToBeObject('person', true)
53 | ->expectKeysToBeObject(['person']);
54 |
55 | $validations = $arrayDefinition->getValidations();
56 |
57 | $this->assertTrue(is_array($validations));
58 | $this->assertTrue(isset($validations['expectKeyToBeString'][0][0]));
59 | $this->assertTrue($validations['expectKeyToBeString'][0][0] === 'title');
60 | $this->assertTrue($validations['expectKeyToBeString'][0][1]);
61 |
62 | $this->assertTrue(isset($validations['expectKeyToBeString'][1][0]));
63 | $this->assertTrue($validations['expectKeyToBeString'][1][0] === 'content');
64 | $this->assertTrue($validations['expectKeyToBeString'][1][1]);
65 |
66 | $this->assertTrue(isset($validations['expectKeyToBeString'][2][0]));
67 | $this->assertTrue($validations['expectKeyToBeString'][2][0] === 'description');
68 | $this->assertFalse($validations['expectKeyToBeString'][2][1]);
69 |
70 | $this->assertTrue(isset($validations['expectKeyToBeObject'][0][0]));
71 | $this->assertTrue($validations['expectKeyToBeObject'][0][0] === 'person');
72 | $this->assertTrue($validations['expectKeyToBeObject'][0][1]);
73 | }
74 |
75 | public function testStrictArrayValidatorFromDefinition()
76 | {
77 | $arrayDefinition = new ValidationDefinition();
78 | $arrayDefinition
79 | ->expectNKeys(2)
80 | ->expectAtLeastKeys(['title', 'content'])
81 | ->expectExactlyKeys(['title', 'content'])
82 | ->expectOnlyKeys(['title', 'content'])
83 | ->expectKeysToBeString(['title', 'content'], true);
84 |
85 | $strictValidator = new StrictValidationFromDefinition($arrayDefinition, [
86 | 'title' => '',
87 | 'content' => '',
88 | ]);
89 |
90 | $this->assertTrue(true);
91 |
92 | $this->expectException(InvalidTypeException::class);
93 | $strictValidator = new StrictValidationFromDefinition($arrayDefinition, [
94 | 'title' => '',
95 | 'content' => 1,
96 | ]);
97 | }
98 |
99 | /**
100 | * @throws InvalidTypeException
101 | * @throws InvalidStructureException
102 | */
103 | public function testStrictArrayValidatorFromSchema()
104 | {
105 | $schemaArray = [
106 | 'title' => [
107 | 'type' => 'string',
108 | 'required' => true
109 | ],
110 | 'content' => [
111 | 'type' => 'string',
112 | 'nullable' => true,
113 | ],
114 | ];
115 |
116 | $schema = new Schema(
117 | new SchemaCompiler(),
118 | $schemaArray,
119 | 'mySchemaName'
120 | );
121 |
122 | $arrayToValidate = [
123 | 'title' => '',
124 | 'content' => null,
125 | ];
126 |
127 | // will throw an exception if any of tests failed,
128 | // this should pass
129 | new StrictValidationFromSchema($schema, $arrayToValidate);
130 | $this->assertTrue(true);
131 |
132 | // this should not pass
133 | $this->expectException(InvalidTypeException::class);
134 | new StrictValidationFromSchema($schema, [
135 | 'title' => '',
136 | 'content' => 1,
137 | ]);
138 |
139 | }
140 |
141 | public function testJsonSerialize()
142 | {
143 | $definition = new ValidationDefinition();
144 | $definition->expectOnlyKeys(['title', 'content']);
145 | $this->assertTrue(json_encode($definition) === '{"expectOnlyKeys":[[["title","content"]]]}');
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/tests/ValidationFromDefinitionTest.php:
--------------------------------------------------------------------------------
1 | expectAtLeastKeys(['title', 'content'])
19 | ->expectExactlyKeys(['title', 'content'])
20 | ->expectOnlyKeys(['title', 'content'])
21 | ->expectKeysToBeString(['title', 'content'], true);
22 |
23 | $data = [
24 | 'item1' => 45.1,
25 | 'item2' => 36.5,
26 | 'item3' => [],
27 | 'item4' => null,
28 | 'item5' => 99,
29 | ];
30 |
31 | $validation = new ValidationFromDefinition($validationDefinition, $data);
32 |
33 | $this->assertTrue($validation->hasErrors());
34 | $this->assertTrue(count($validation->getErrors()) === 3);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/tests/ValidationFromSchemaTest.php:
--------------------------------------------------------------------------------
1 | [
18 | 'type' => 'string',
19 | 'required' => true
20 | ],
21 | 'content' => [
22 | 'type' => 'string',
23 | 'nullable' => true,
24 | ],
25 | ];
26 |
27 | $schema = new Schema(
28 | new SchemaCompiler(),
29 | $schemaArray,
30 | 'mySchemaName'
31 | );
32 |
33 | $arrayToValidate = [
34 | 'title' => '',
35 | 'content' => null,
36 | ];
37 |
38 | // this should not pass
39 | $validation = new ValidationFromSchema($schema, [
40 | 'title' => '',
41 | 'content' => 1,
42 | ]);
43 |
44 | $this->assertTrue($validation->hasErrors());
45 | $this->assertTrue(count($validation->getErrors()) == 1);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/tests/ValidationTest.php:
--------------------------------------------------------------------------------
1 | [], 'field2' => 'text', 'field3' => 1, 'field4'=> true, 'field5' => 1.2, 'field6' => new StdClass()], // data
20 | null, // dataName
21 | [ // validation rules
22 | 'expectOnlyKeys' => [ ['field1', 'field2', 'field3', 'field4', 'field5', 'field6'] ],
23 | 'expectExactlyKeys' => [ ['field1', 'field2', 'field3', 'field4', 'field5', 'field6'] ],
24 | 'expectKeyToBeArray' => ['field1'],
25 | 'expectKeyToBeString' => ['field2'],
26 | 'expectKeyToBeInteger' => ['field3'],
27 | 'expectKeyToBeBoolean' => ['field4'],
28 | 'expectKeyToBeFloat' => ['field5'],
29 | 'expectKeyToBeObject' => ['field6'],
30 |
31 | 'expectKeysToBeArray' => [['field1']],
32 | 'expectKeysToBeString' => [['field2']],
33 | 'expectKeysToBeInteger' => [['field3']],
34 | 'expectKeysToBeBoolean' => [['field4']],
35 | 'expectKeysToBeFloat' => [['field5']],
36 | 'expectKeysToBeObject' => [['field6']],
37 | ],
38 | false, // has error(s)
39 | 0, // number of error(s)
40 | [] // error(s) messages
41 | ],
42 |
43 | // this one will test types errors
44 | [
45 | ['field6' => [], 'field5' => 'text', 'field4' => 1, 'field3'=> true, 'field2' => 1.2, 'field1' => new StdClass()], // data
46 | 'myValidation', // dataName
47 | [ // validation rules
48 | 'expectKeyToBeArray' => ['field1'],
49 | 'expectKeyToBeString' => ['field2'],
50 | 'expectKeyToBeInteger' => ['field3'],
51 | 'expectKeyToBeBoolean' => ['field4'],
52 | 'expectKeyToBeFloat' => ['field5'],
53 | 'expectKeyToBeObject' => ['field6'],
54 | ],
55 | true, // has error(s)
56 | 6, // number of error(s)
57 | [
58 | '[myValidation] invalid type for key [field1], type array is expected',
59 | '[myValidation] invalid type for key [field2], type string is expected',
60 | '[myValidation] invalid type for key [field3], type integer is expected',
61 | '[myValidation] invalid type for key [field4], type boolean is expected',
62 | '[myValidation] invalid type for key [field5], type float is expected',
63 | '[myValidation] invalid type for key [field6], type object is expected',
64 | ] // error(s) messages
65 | ],
66 |
67 | //this one will tests structure errors
68 | [
69 | ['field6' => 'im here!', 'field7' => 'foo'], // data
70 | null, // dataName
71 | [ // validation rules
72 | 'expectOnlyKeys' => [ ['field1', 'field2', 'field3', 'field4', 'field5', 'field6'] ],
73 | 'expectExactlyKeys' => [ ['field1', 'field2', 'field3', 'field4', 'field5', 'field6'] ],
74 | 'expectAtLeastKeys' => [ ['field1'] ],
75 | 'expectOnlyOneFromKeys' => [ ['field1'] ],
76 | 'expectNKeys' => [1]
77 | ],
78 | true, // has error(s)
79 | 5, // number of error(s)
80 | [
81 | 'invalid data, expected only keys [field1, field2, field3, field4, field5, field6], received [field6, field7]',
82 | 'invalid data, expected exactly keys [field1, field2, field3, field4, field5, field6], received [field6, field7]',
83 | 'invalid data, expected at least keys [field1], received [field6, field7]',
84 | 'invalid data, expected only one of keys [field1], received [field6, field7]',
85 | 'invalid data, expected 1 element, received 2 elements'
86 | ] // error(s) messages
87 | ],
88 | ];
89 | }
90 |
91 | /**
92 | * @dataProvider dataProvider
93 | * @param array $data
94 | * @param string|null $dataName
95 | * @param array $validationMethods
96 | * @param bool $hasErrors
97 | * @param int $errorsCount
98 | * @param array $errorsMsg
99 | */
100 | public function testScenarios(array $data, ?string $dataName, array $validationMethods, bool $hasErrors, int $errorsCount, array $errorsMsg)
101 | {
102 | $validation = new Validation($data, $dataName);
103 |
104 | foreach ($validationMethods as $methodName => $methodArgs) {
105 | call_user_func_array([$validation, $methodName], $methodArgs);
106 | }
107 |
108 | $this->assertTrue($validation->hasErrors() === $hasErrors);
109 | $this->assertTrue(count($validation->getErrors()) === $errorsCount);
110 | $this->assertTrue($validation->getErrors() === $errorsMsg);
111 |
112 | if ($errorsCount > 0) {
113 | $errors = $validation->getErrors();
114 | $this->assertTrue($validation->getLastError() === $errors[array_key_last($errors)]);
115 | } else {
116 | $this->assertTrue($validation->getLastError() === null);
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/tests/ValidatorTest.php:
--------------------------------------------------------------------------------
1 | 'foo',
16 | 'content' => 'foobar',
17 | ];
18 |
19 | private $data2 = [
20 | 'title' => 'foo'
21 | ];
22 |
23 | private $data3 = [
24 | 'title' => null,
25 | 'views' => 45,
26 | 'comments' => []
27 | ];
28 |
29 | public function testExpectExactlyKeys()
30 | {
31 | $validation = new Validator();
32 | $this->assertTrue($validation->expectExactlyKeys($this->data1, ['title', 'content']));
33 | $this->assertFalse($validation->expectExactlyKeys($this->data1, ['title', 'content', 'extra']));
34 | $this->assertFalse($validation->expectExactlyKeys($this->data1, ['title']));
35 | $this->assertFalse($validation->expectExactlyKeys($this->data1, ['extra']));
36 | $this->assertFalse($validation->expectExactlyKeys($this->data1, []));
37 | }
38 |
39 | public function testExpectOnlyOneFromKeys()
40 | {
41 | $validation = new Validator();
42 | $this->assertTrue($validation->expectOnlyOneFromKeys($this->data2, ['title', 'extra']));
43 | $this->assertTrue($validation->expectOnlyOneFromKeys($this->data2, ['title']));
44 | $this->assertFalse($validation->expectOnlyOneFromKeys($this->data2, ['extra']));
45 | }
46 |
47 | public function testExpectAtLeastKeys()
48 | {
49 | $validation = new Validator();
50 | $this->assertTrue($validation->expectAtLeastKeys($this->data1, ['title']));
51 | $this->assertTrue($validation->expectAtLeastKeys($this->data1, ['content']));
52 | $this->assertTrue($validation->expectAtLeastKeys($this->data1, ['title', 'content']));
53 | $this->assertFalse($validation->expectAtLeastKeys($this->data1, ['extra']));
54 | $this->assertFalse($validation->expectAtLeastKeys($this->data1, ['title', 'content', 'extra']));
55 | }
56 |
57 | public function testExpectOnlyKeys()
58 | {
59 | $validation = new Validator();
60 | $this->assertTrue($validation->expectOnlyKeys($this->data1, ['title', 'content']));
61 | $this->assertTrue($validation->expectOnlyKeys($this->data1, ['title', 'content', 'extra']));
62 | $this->assertFalse($validation->expectOnlyKeys($this->data1, ['title']));
63 | }
64 |
65 | public function testExpectNElement()
66 | {
67 | $validation = new Validator();
68 | $this->assertTrue($validation->expectNKeys($this->data1, 2));
69 | $this->assertFalse($validation->expectNKeys($this->data1, 1));
70 | }
71 |
72 | public function testIsArray()
73 | {
74 | $validation = new Validator();
75 | $this->assertTrue($validation->expectKeyToBeArray($this->data3, 'comments', false));
76 | $this->assertFalse($validation->expectKeyToBeArray($this->data3, 'title', false));
77 | $this->assertTrue($validation->expectKeyToBeArray($this->data3, 'title', true));
78 |
79 | $data = [
80 | 'item1' => 45,
81 | 'item2' => [],
82 | 'item3' => [],
83 | 'item4' => null,
84 | ];
85 | $this->assertTrue($validation->expectKeysToBeArray($data, ['item2'], false));
86 | $this->assertTrue($validation->expectKeysToBeArray($data, ['item2', 'item3'], false));
87 | $this->assertFalse($validation->expectKeysToBeArray($data, ['item2', 'item3', 'item4'], false));
88 | $this->assertTrue($validation->expectKeysToBeArray($data, ['item2', 'item3', 'item4'], true));
89 | }
90 |
91 | public function testIsInt()
92 | {
93 | $data = [
94 | 'item1' => 45,
95 | 'item2' => 36,
96 | 'item3' => [],
97 | 'item4' => null,
98 | 'item5' => '',
99 | ];
100 | $validation = new Validator();
101 | $this->assertTrue($validation->expectKeyToBeInteger($data, 'item1', false));
102 | $this->assertFalse($validation->expectKeyToBeInteger($data, 'item3', false));
103 | $this->assertFalse($validation->expectKeyToBeInteger($data, 'item4', false));
104 | $this->assertTrue($validation->expectKeyToBeInteger($data, 'item4', true));
105 |
106 |
107 | $this->assertTrue($validation->expectKeysToBeInteger($data, ['item1', 'item2'], false));
108 | $this->assertFalse($validation->expectKeysToBeInteger($data, ['item1', 'item2', 'item4'], false));
109 | $this->assertTrue($validation->expectKeysToBeInteger($data, ['item1', 'item2', 'item4'], true));
110 | $this->assertFalse($validation->expectKeysToBeInteger($data, ['item1', 'item2', 'item3', 'item4'], true));
111 | }
112 |
113 | public function testIsFloat()
114 | {
115 | $data = [
116 | 'item1' => 45.1,
117 | 'item2' => 36.5,
118 | 'item3' => [],
119 | 'item4' => null,
120 | 'item5' => 99,
121 | ];
122 | $validation = new Validator();
123 | $this->assertTrue($validation->expectKeyToBeFloat($data, 'item1', false));
124 | $this->assertFalse($validation->expectKeyToBeFloat($data, 'item3', false));
125 | $this->assertFalse($validation->expectKeyToBeFloat($data, 'item4', false));
126 | $this->assertTrue($validation->expectKeyToBeFloat($data, 'item4', true));
127 |
128 |
129 | $this->assertTrue($validation->expectKeysToBeFloat($data, ['item1', 'item2'], false));
130 | $this->assertFalse($validation->expectKeysToBeFloat($data, ['item1', 'item2', 'item4'], false));
131 | $this->assertTrue($validation->expectKeysToBeFloat($data, ['item1', 'item2', 'item4'], true));
132 | $this->assertFalse($validation->expectKeysToBeFloat($data, ['item1', 'item2', 'item3', 'item4'], true));
133 | $this->assertFalse($validation->expectKeysToBeFloat($data, ['item1', 'item2', 'item5'], false));
134 | }
135 |
136 | public function testIsBool()
137 | {
138 | $data = [
139 | 'item1' => true,
140 | 'item2' => false,
141 | 'item3' => [],
142 | 'item4' => null,
143 | 'item5' => 1,
144 | ];
145 | $validation = new Validator();
146 | $this->assertTrue($validation->expectKeyToBeBoolean($data, 'item1', false));
147 | $this->assertFalse($validation->expectKeyToBeBoolean($data, 'item3', false));
148 | $this->assertFalse($validation->expectKeyToBeBoolean($data, 'item5', false));
149 | $this->assertFalse($validation->expectKeyToBeBoolean($data, 'item4', false));
150 | $this->assertTrue($validation->expectKeyToBeBoolean($data, 'item4', true));
151 |
152 |
153 | $this->assertTrue($validation->expectKeysToBeBoolean($data, ['item1', 'item2'], false));
154 | $this->assertFalse($validation->expectKeysToBeBoolean($data, ['item1', 'item2', 'item4'], false));
155 | $this->assertTrue($validation->expectKeysToBeBoolean($data, ['item1', 'item2', 'item4'], true));
156 | $this->assertFalse($validation->expectKeysToBeBoolean($data, ['item1', 'item2', 'item3', 'item4'], true));
157 | }
158 |
159 | public function testIsString()
160 | {
161 | $data = [
162 | 'item1' => 'string',
163 | 'item2' => 'string',
164 | 'item3' => [],
165 | 'item4' => null,
166 | 'item5' => 2,
167 | ];
168 | $validation = new Validator();
169 | $this->assertTrue($validation->expectKeyToBeString($data, 'item1', false));
170 | $this->assertFalse($validation->expectKeyToBeString($data, 'item3', false));
171 | $this->assertFalse($validation->expectKeyToBeString($data, 'item4', false));
172 | $this->assertTrue($validation->expectKeyToBeString($data, 'item4', true));
173 |
174 |
175 | $this->assertTrue($validation->expectKeysToBeString($data, ['item1', 'item2'], false));
176 | $this->assertFalse($validation->expectKeysToBeString($data, ['item1', 'item2', 'item4'], false));
177 | $this->assertTrue($validation->expectKeysToBeString($data, ['item1', 'item2', 'item4'], true));
178 | $this->assertFalse($validation->expectKeysToBeString($data, ['item1', 'item2', 'item3', 'item4'], true));
179 | }
180 |
181 | public function testIsObject()
182 | {
183 | $data = [
184 | 'item1' => new stdClass(),
185 | 'item2' => new DateTime(),
186 | 'item3' => null,
187 | ];
188 | $validation = new Validator();
189 | $this->assertTrue($validation->expectKeyToBeObject($data, 'item1', false));
190 | $this->assertFalse($validation->expectKeyToBeObject($data, 'item3', false));
191 | $this->assertTrue($validation->expectKeyToBeObject($data, 'item3', true));
192 | $this->assertTrue($validation->expectKeysToBeObject($data, ['item1', 'item2'], false));
193 | $this->assertFalse($validation->expectKeysToBeObject($data, ['item1', 'item2', 'item3'], false));
194 | $this->assertTrue($validation->expectKeysToBeObject($data, ['item1', 'item2', 'item3'], true));
195 | }
196 | }
197 |
--------------------------------------------------------------------------------