Skip to content

Commit 7dd095e

Browse files
committed
Add validation to filter options (closes #62)
1 parent 26d8b02 commit 7dd095e

File tree

5 files changed

+133
-1
lines changed

5 files changed

+133
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
}
1212
],
1313
"require": {
14-
"wol-soft/php-json-schema-model-generator-production": "^0.17.0",
14+
"wol-soft/php-json-schema-model-generator-production": "^0.18.0",
1515
"wol-soft/php-micro-template": "^1.3.2",
1616

1717
"php": ">=7.2",

docs/source/nonStandardExtensions/filter.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,19 @@ The option will be available if your JSON-Schema uses the object-notation for th
392392
}
393393
}
394394
395+
Validating filter options
396+
^^^^^^^^^^^^^^^^^^^^^^^^^
397+
398+
If your filter accepts additional filter options you may want to validate the provided options during the model generation process to avoid runtime errors.
399+
To achieve a validation of the options your custom filter must implement the **PHPModelGenerator\\Filter\\ValidateOptionsInterface**.
400+
This interface adds the following method to your implementation:
401+
402+
.. code-block:: php
403+
public function validateOptions(array $options): void;
404+
405+
The options provided in the schema which utilizes the filter are passed to the method during the model generation.
406+
If invalid options are detected just throw an exception which will result in a **SchemaException**.
407+
395408
Custom transforming filter
396409
^^^^^^^^^^^^^^^^^^^^^^^^^^
397410

src/PropertyProcessor/Filter/FilterProcessor.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
namespace PHPModelGenerator\PropertyProcessor\Filter;
66

7+
use Exception;
78
use PHPModelGenerator\Exception\SchemaException;
89
use PHPModelGenerator\Filter\TransformingFilterInterface;
10+
use PHPModelGenerator\Filter\ValidateOptionsInterface;
911
use PHPModelGenerator\Model\GeneratorConfiguration;
1012
use PHPModelGenerator\Model\Property\PropertyInterface;
1113
use PHPModelGenerator\Model\Property\PropertyType;
@@ -70,6 +72,22 @@ public function process(
7072
);
7173
}
7274

75+
if ($filter instanceof ValidateOptionsInterface) {
76+
try {
77+
$filter->validateOptions($filterOptions);
78+
} catch (Exception $exception) {
79+
throw new SchemaException(
80+
sprintf(
81+
'Invalid filter options on filter %s on property %s in file %s: %s',
82+
$filterToken,
83+
$property->getName(),
84+
$property->getJsonSchema()->getFile(),
85+
$exception->getMessage()
86+
)
87+
);
88+
}
89+
}
90+
7391
$property->addValidator(
7492
new FilterValidator($generatorConfiguration, $filter, $property, $filterOptions, $transformingFilter),
7593
$filterPriority++

tests/Basic/FilterTest.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PHPModelGenerator\Filter\FilterInterface;
1212
use PHPModelGenerator\Filter\TransformingFilterInterface;
1313
use PHPModelGenerator\Filter\Trim;
14+
use PHPModelGenerator\Filter\ValidateOptionsInterface;
1415
use PHPModelGenerator\Model\GeneratorConfiguration;
1516
use PHPModelGenerator\PropertyProcessor\Filter\DateTimeFilter;
1617
use PHPModelGenerator\PropertyProcessor\Filter\TrimFilter;
@@ -290,6 +291,97 @@ public function customFilterDataProvider(): array
290291
];
291292
}
292293

294+
/**
295+
* @dataProvider invalidEncodingFilterConfigurationsDataProvider
296+
*/
297+
public function testInvalidCustomFilterOptionValidation(string $configuration, string $expectedErrorMessage): void
298+
{
299+
$this->expectException(SchemaException::class);
300+
$this->expectExceptionMessageMatches(
301+
"/Invalid filter options on filter encode on property .*\: $expectedErrorMessage/"
302+
);
303+
304+
$this->generateClassFromFileTemplate(
305+
'Encode.json',
306+
[$configuration],
307+
(new GeneratorConfiguration())->setImmutable(false)->addFilter($this->getEncodeFilter()),
308+
false
309+
);
310+
}
311+
312+
public function invalidEncodingFilterConfigurationsDataProvider(): array
313+
{
314+
return [
315+
'simple notation without options' => ['"encode"', 'Missing charset configuration'],
316+
'object notation without charset configuration' => ['{"filter": "encode"}', 'Missing charset configuration'],
317+
'Invalid charset configuration' => ['{"filter": "encode", "charset": 1}', 'Unsupported charset'],
318+
'Invalid charset configuration 2' => ['{"filter": "encode", "charset": "UTF-16"}', 'Unsupported charset'],
319+
];
320+
}
321+
322+
/**
323+
* @dataProvider validEncodingsDataProvider
324+
*/
325+
public function testValidCustomFilterOptionValidation(string $encoding, string $input, string $output): void
326+
{
327+
$classname = $this->generateClassFromFileTemplate(
328+
'Encode.json',
329+
[sprintf('{"filter": "encode", "charset": "%s"}', $encoding)],
330+
(new GeneratorConfiguration())->setImmutable(false)->addFilter($this->getEncodeFilter()),
331+
false
332+
);
333+
334+
$object = new $classname(['property' => $input]);
335+
336+
$this->assertSame($encoding, mb_detect_encoding($object->getProperty()));
337+
$this->assertSame($output, $object->getProperty());
338+
}
339+
340+
public function validEncodingsDataProvider(): array
341+
{
342+
return [
343+
'ASCII to ASCII' => ['ASCII', 'Hello World', 'Hello World'],
344+
'UTF-8 to ASCII' => ['ASCII', 'áéó', '???'],
345+
'UTF-8 to UTF-8' => ['UTF-8', 'áéó', 'áéó'],
346+
];
347+
}
348+
349+
private function getEncodeFilter()
350+
{
351+
return new class () implements FilterInterface, ValidateOptionsInterface {
352+
public function getAcceptedTypes(): array
353+
{
354+
return ['string'];
355+
}
356+
357+
public function getToken(): string
358+
{
359+
return 'encode';
360+
}
361+
362+
public function getFilter(): array
363+
{
364+
return [FilterTest::class, 'encode'];
365+
}
366+
367+
public function validateOptions(array $options): void
368+
{
369+
if (!isset($options['charset'])) {
370+
throw new Exception('Missing charset configuration');
371+
}
372+
373+
if (!in_array($options['charset'], ['UTF-8', 'ASCII'])) {
374+
throw new Exception('Unsupported charset');
375+
}
376+
}
377+
};
378+
}
379+
380+
public static function encode(string $value, array $options): string
381+
{
382+
return mb_convert_encoding($value, $options['charset'], 'auto');
383+
}
384+
293385
/**
294386
* @dataProvider multipleFilterDataProvider
295387
*

tests/Schema/FilterTest/Encode.json

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+
"property": {
5+
"type": "string",
6+
"filter": %s
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)