Skip to content

Commit a9ce530

Browse files
committed
Add array not empty filter
Add array filter documentation Add array filter test cases Deny transforming filters on arrays
1 parent 3180dfc commit a9ce530

File tree

11 files changed

+180
-14
lines changed

11 files changed

+180
-14
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.2-8892BF.svg)](https://php.net/)
33
[![Maintainability](https://api.codeclimate.com/v1/badges/9e3c565c528edb3d58d5/maintainability)](https://codeclimate.com/github/wol-soft/php-json-schema-model-generator/maintainability)
44
[![Test Coverage](https://api.codeclimate.com/v1/badges/7eb29e7366dc3d6a5f44/test_coverage)](https://codeclimate.com/github/wol-soft/php-json-schema-model-generator/test_coverage)
5-
[![Build Status](https://travis-ci.org/wol-soft/php-json-schema-model-generator.svg?branch=master)](https://travis-ci.org/wol-soft/php-json-schema-model-generator)
5+
[![Build Status](https://travis-ci.com/wol-soft/php-json-schema-model-generator.svg?branch=master)](https://travis-ci.com/wol-soft/php-json-schema-model-generator)
66
[![Coverage Status](https://coveralls.io/repos/github/wol-soft/php-json-schema-model-generator/badge.svg?branch=master)](https://coveralls.io/github/wol-soft/php-json-schema-model-generator?branch=master)
77
[![MIT License](https://img.shields.io/packagist/l/wol-soft/php-json-schema-model-generator.svg)](https://github.com/wol-soft/php-json-schema-model-generator/blob/master/LICENSE)
88
[![Documentation Status](https://readthedocs.org/projects/php-json-schema-model-generator/badge/?version=latest)](https://php-json-schema-model-generator.readthedocs.io/en/latest/?badge=latest)

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
],
1313
"require": {
1414
"symplify/easy-coding-standard": "^7.2.3",
15-
"wol-soft/php-json-schema-model-generator-production": "0.8.0",
15+
"wol-soft/php-json-schema-model-generator-production": "0.9.0",
1616
"wol-soft/php-micro-template": "^1.3.1",
1717

1818
"php": ">=7.2",

docs/source/nonStandardExtensions/filter.rst

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,31 @@ If a list is used filters may include additional option parameters. In this case
4646
}
4747
}
4848
49+
Array filter
50+
------------
51+
52+
Filters may be applied to arrays. In this case the filter operates on the whole array.
53+
54+
.. code-block:: json
55+
56+
{
57+
"type": "object",
58+
"properties": {
59+
"names": {
60+
"type": "array",
61+
"filter": "notEmpty",
62+
"items": {
63+
"type": "string",
64+
"filter": "trim"
65+
}
66+
}
67+
}
68+
}
69+
70+
The array filter is executed before the items are processed. Consequently strings which aren't empty at the beginning but are empty after the trim filter is applied to each element won't be filtered out in the example given above.
71+
72+
It is not possible to use transforming filters on arrays.
73+
4974
Transforming filter
5075
-------------------
5176

@@ -112,6 +137,40 @@ If the filter trim is used for a property which doesn't require a string value a
112137

113138
* Filter trim is not compatible with property type __TYPE__ for property __PROPERTY_NAME__
114139

140+
notEmpty
141+
^^^^^^^^
142+
143+
The dateTime filter is only valid for array properties.
144+
145+
.. code-block:: json
146+
147+
{
148+
"$id": "family",
149+
"type": "object",
150+
"properties": {
151+
"members": {
152+
"type": "array",
153+
"filter": "notEmpty"
154+
}
155+
}
156+
}
157+
158+
Let's have a look how the generated model behaves:
159+
160+
.. code-block:: php
161+
162+
// valid, the name will be NULL as the name is not required
163+
$family = new Person([]);
164+
165+
// A valid example
166+
$family = new Family(['members' => [null, null]]]);
167+
$family->getMembers(); // returns an empty array
168+
// the raw model data input is not affected by the filter
169+
$family->getRawModelDataInput(); // returns ['members' => [null, null]]
170+
171+
$family->setMembers(['Hannes', null]);
172+
$family->getMembers(); // returns ['Hannes']
173+
115174
dateTime
116175
^^^^^^^^
117176

@@ -228,6 +287,9 @@ The callable filter method must be a static method. Internally it will be called
228287
229288
If the custom filter is added to the generator configuration you can now use the filter in your schema and the generator will resolve the function:
230289

290+
.. hint::
291+
292+
If a filter with the token of your custom filter already exists the existing filter will be overwritten when adding the filter to the generator configuration. By overwriting filters you may change the behaviour of builtin filters by replacing them with your custom implementation.
231293

232294
.. code-block:: json
233295

src/Model/GeneratorConfiguration.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPModelGenerator\Exception\InvalidFilterException;
88
use PHPModelGenerator\PropertyProcessor\Filter\DateTimeFilter;
99
use PHPModelGenerator\PropertyProcessor\Filter\FilterInterface;
10+
use PHPModelGenerator\PropertyProcessor\Filter\NotEmptyFilter;
1011
use PHPModelGenerator\PropertyProcessor\Filter\TransformingFilterInterface;
1112
use PHPModelGenerator\PropertyProcessor\Filter\TrimFilter;
1213
use PHPModelGenerator\Utils\ClassNameGenerator;
@@ -51,6 +52,7 @@ public function __construct()
5152

5253
$this
5354
->addFilter(new DateTimeFilter())
55+
->addFilter(new NotEmptyFilter())
5456
->addFilter(new TrimFilter());
5557
}
5658

@@ -65,7 +67,6 @@ public function __construct()
6567
*/
6668
public function addFilter(FilterInterface $filter): self
6769
{
68-
// TODO: check accepted types
6970
if (!(count($filter->getFilter()) === 2) ||
7071
!is_string($filter->getFilter()[0]) ||
7172
!is_string($filter->getFilter()[1]) ||

src/Model/Validator/FilterValidator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ private function mapDataTypes(array $acceptedTypes): array
129129
case 'boolean': return 'bool';
130130
case 'array': return 'array';
131131

132+
// @codeCoverageIgnoreStart this must not occur as invalid types are filtered out before
132133
default: throw new SchemaException("Invalid accepted type $jsonSchemaType");
134+
// @codeCoverageIgnoreEnd
133135
}
134136
}, $acceptedTypes);
135137
}

src/PropertyProcessor/Filter/FilterProcessor.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ public function process(
6565
);
6666

6767
if ($filter instanceof TransformingFilterInterface) {
68+
if ($property->getType() === 'array') {
69+
throw new SchemaException(
70+
"Applying a transforming filter to the array property {$property->getName()} is not supported"
71+
);
72+
}
6873
if ($hasTransformingFilter) {
6974
throw new SchemaException(
7075
"Applying multiple transforming filters for property {$property->getName()} is not supported"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\Filter;
6+
7+
use PHPModelGenerator\Filter\NotEmpty;
8+
9+
/**
10+
* Class NotEmptyFilter
11+
*
12+
* Removes empty elements from an array
13+
*
14+
* @package PHPModelGenerator\PropertyProcessor\Filter
15+
*/
16+
class NotEmptyFilter implements FilterInterface
17+
{
18+
/**
19+
* @inheritDoc
20+
*/
21+
public function getAcceptedTypes(): array
22+
{
23+
return ['array'];
24+
}
25+
26+
/**
27+
* @inheritDoc
28+
*/
29+
public function getToken(): string
30+
{
31+
return 'notEmpty';
32+
}
33+
34+
/**
35+
* @inheritDoc
36+
*/
37+
public function getFilter(): array
38+
{
39+
return [NotEmpty::class, 'filter'];
40+
}
41+
}

src/PropertyProcessor/Filter/TrimFilter.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,23 @@
1616
class TrimFilter implements FilterInterface
1717
{
1818
/**
19-
* Return a list of accepted data types for the filter (eg. ['string', 'int']). If the filter is applied to a
20-
* value which doesn't match an accepted type an exception will be thrown
21-
*
22-
* @return array
19+
* @inheritDoc
2320
*/
2421
public function getAcceptedTypes(): array
2522
{
2623
return ['string'];
2724
}
2825

2926
/**
30-
* Return the token for the filter
31-
*
32-
* @return string
27+
* @inheritDoc
3328
*/
3429
public function getToken(): string
3530
{
3631
return 'trim';
3732
}
3833

3934
/**
40-
* Return the filter to apply. Make sure the returned array is a callable which is also callable after the
41-
* render process
42-
*
43-
* @return array
35+
* @inheritDoc
4436
*/
4537
public function getFilter(): array
4638
{

tests/Basic/FilterTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,26 @@ public function testAdditionalFilterOptions(): void
477477
$this->assertSame(json_encode($expectedSerialization), $object->toJSON());
478478
}
479479

480+
public function testTransformingFilterAppliedToAnArrayPropertyThrowsAnException(): void
481+
{
482+
$this->expectException(SchemaException::class);
483+
$this->expectExceptionMessage(
484+
'Applying a transforming filter to the array property list is not supported'
485+
);
486+
487+
$this->generateClassFromFile(
488+
'ArrayTransformingFilter.json',
489+
(new GeneratorConfiguration())->addFilter(
490+
$this->getCustomTransformingFilter(
491+
[self::class, 'serializeBinaryToInt'],
492+
[self::class, 'filterIntToBinary'],
493+
'customArrayTransformer',
494+
['array']
495+
)
496+
)
497+
);
498+
}
499+
480500
public function testMultipleTransformingFiltersAppliedToOnePropertyThrowsAnException(): void
481501
{
482502
$this->expectException(SchemaException::class);
@@ -572,4 +592,29 @@ public static function serializeBinaryToInt(string $binary): int
572592
{
573593
return bindec($binary);
574594
}
595+
596+
/**
597+
* @dataProvider arrayFilterDataProvider
598+
*
599+
* @param array|null $input
600+
* @param array|null $output
601+
*/
602+
public function testArrayFilter(?array $input, ?array $output): void
603+
{
604+
$className = $this->generateClassFromFile('ArrayFilter.json');
605+
606+
$object = new $className(['list' => $input]);
607+
$this->assertSame($output, $object->getList());
608+
}
609+
610+
public function arrayFilterDataProvider(): array
611+
{
612+
return [
613+
'null' => [null, null],
614+
'empty array' => [[], []],
615+
'string array' => [['', 'Hello', null, '123'], ['Hello', '123']],
616+
'numeric array' => [[12, 0, 43], [12, 43]],
617+
'nested array' => [[['Hello'], [], [12], ['']], [['Hello'], [12], ['']]],
618+
];
619+
}
575620
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"list": {
5+
"type": "array",
6+
"filter": "notEmpty"
7+
}
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"list": {
5+
"type": "array",
6+
"filter": "customArrayTransformer"
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)