Skip to content
This repository was archived by the owner on Dec 19, 2022. It is now read-only.

Commit bb60a28

Browse files
author
Seif Kamal
committed
Support implicit struct array validation
1 parent 3286e1e commit bb60a28

File tree

5 files changed

+84
-17
lines changed

5 files changed

+84
-17
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,36 @@ echo "File: {$directory['file']}" . PHP_EOL;
7979
// File: /Users/seifkamal/src/struct-array/README.md
8080
```
8181

82-
Here's the same one using static class methods:
82+
You can also just use an array directly, without creating a `Struct`:
83+
84+
```php
85+
<?php
86+
87+
use function SK\StructArray\{
88+
arrayOf, optional, not, validate
89+
};
90+
91+
$directory = [...];
92+
93+
validate($directory, [
94+
'path' => 'is_dir',
95+
'file' => optional('is_file', __DIR__ . '/README.md'),
96+
'content' => arrayOf([
97+
'header' => 'is_string',
98+
'line' => not('is_null'),
99+
]),
100+
]);
101+
```
102+
103+
This is tailored for quick usage, and therefore assumes the defined interface is non-exhaustive
104+
(ie. the array submitted for validation is allowed to have keys that aren't defined here). It also
105+
means error messages will be more generic, ie you'll see:
106+
> Struct failed validation. ...
107+
108+
instead of:
109+
> Directory failed validation. ...
110+
111+
Here's another example directly using the static class methods:
83112

84113
```php
85114
<?php

src/Struct.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ public static function of(
3333
return $struct;
3434
}
3535

36+
/**
37+
* @internal
38+
*
39+
* @param array $interface
40+
* @return static
41+
*/
42+
public static function default(array $interface): self
43+
{
44+
return static::of('Struct', $interface, false);
45+
}
46+
3647
public function name(): string
3748
{
3849
return $this->name;

src/Validator.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ class Validator
88
{
99
/**
1010
* @param array $data
11-
* @param Struct $struct
11+
* @param array|Struct $struct If an array is supplied, a generic, non-exhaustive Struct is used.
1212
* @return bool
1313
* @throws Exception\StructValidationException
1414
*/
15-
public static function validate(array &$data, Struct $struct): bool
15+
public static function validate(array &$data, $struct): bool
1616
{
1717
try {
18+
if (is_array($struct)) {
19+
$struct = Struct::default($struct);
20+
}
21+
1822
$unexpectedProperties = array_diff_key($data, $struct->interface());
1923
if ($struct->isExhaustive() && !empty($unexpectedProperties)) {
2024
throw new Exception\UnexpectedPropertyException(...array_keys($unexpectedProperties));
@@ -41,6 +45,9 @@ public static function validate(array &$data, Struct $struct): bool
4145
throw new Exception\MissingPropertyException($field);
4246
}
4347

48+
if (is_array($validator)) {
49+
$validator = Struct::default($validator);
50+
}
4451
if (is_a($validator, Struct::class)) {
4552
if (!validate($value, $validator)) {
4653
throw new Exception\InvalidValueException($field);

src/functions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ function struct(string $name, array $interface, bool $exhaustive = true): Struct
9191
* @see Validator::validate()
9292
*
9393
* @param array $data
94-
* @param Struct $struct
94+
* @param array|Struct $struct If an array is supplied, a generic, non-exhaustive Struct is used.
9595
* @return bool
9696
* @throws Exception\StructValidationException
9797
*/
98-
function validate(array &$data, Struct $struct): bool
98+
function validate(array &$data, $struct): bool
9999
{
100100
return Validator::validate($data, $struct);
101101
}

tests/Unit/StructTest.php

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace SK\StructArray\Test\Unit;
44

55
use PHPUnit\Framework\TestCase;
6-
use SK\StructArray\Exception;
76
use SK\StructArray\Exception\StructValidationException;
87
use SK\StructArray\Property\Type;
98
use SK\StructArray\Struct;
@@ -15,42 +14,64 @@ class StructTest extends TestCase
1514
/**
1615
* @dataProvider dataProviderForTest
1716
*/
18-
public function test($data, $interface, $exhaustive, $expectedException)
17+
public function test($data, $struct, $expectedException)
1918
{
2019
if ($expectedException) {
2120
$this->expectException(StructValidationException::class);
2221
}
2322

24-
$this->assertTrue(validate($data, Struct::of('Test', $interface, $exhaustive)));
23+
$this->assertTrue(validate($data, $struct));
2524
}
2625

2726
public function dataProviderForTest(): array
2827
{
28+
$name = 'Test';
2929
return [
3030
[
3131
['name' => 'toasty',],
32-
['name' => 'invalid validator'],
33-
true,
32+
Struct::of($name, ['name' => 'invalid validator'], true),
3433
true,
3534
],
3635
[
3736
['name' => 10],
38-
['name' => 'is_string'],
39-
true,
37+
Struct::of($name, ['name' => 'is_string'], true),
4038
true,
4139
],
4240
[
4341
[],
44-
['name' => 'is_string'],
45-
true,
42+
Struct::of($name, ['name' => 'is_string'], true),
4643
true,
4744
],
4845
[
4946
['name' => 'toasty', 'age' => 10],
50-
['name' => 'is_string'],
51-
true,
47+
Struct::of($name, ['name' => 'is_string'], true),
5248
true,
5349
],
50+
[
51+
[
52+
'id' => '123',
53+
'type' => 'theatre',
54+
'date' => new \DateTime(),
55+
'price' => [
56+
'value' => 20.5,
57+
'currency' => 'GBP',
58+
],
59+
'tickets' => ['General', 10],
60+
'onSale' => true,
61+
'artist' => 'some guy',
62+
],
63+
Struct::of($name, [
64+
'id' => Type::allOf('is_string', 'is_numeric'),
65+
'type' => 'is_string',
66+
'date' => Type::anyOf(Type::classOf(\DateTime::class), 'is_null'),
67+
'price' => Struct::of('Price', [
68+
'value' => 'is_float',
69+
'currency' => 'is_string'
70+
]),
71+
'tickets' => Type::arrayOf(Type::not('is_null')),
72+
], false),
73+
null
74+
],
5475
[
5576
[
5677
'id' => '123',
@@ -74,7 +95,6 @@ public function dataProviderForTest(): array
7495
]),
7596
'tickets' => Type::arrayOf(Type::not('is_null')),
7697
],
77-
false,
7898
null
7999
],
80100
];

0 commit comments

Comments
 (0)