diff --git a/.travis.yml b/.travis.yml index aa7e57f..1b32d89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,26 @@ language: php sudo: false env: - global: - - CC_TEST_REPORTER_ID=5e32818628fac9eb11d34e2b35289f88169610cc4a98c6f170c74923342284f1 + - TEST_SUITE="PHPModelGenerator" FILTER="." CC_TEST_REPORTER_ID=5e32818628fac9eb11d34e2b35289f88169610cc4a98c6f170c74923342284f1 + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft3\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft3/optional\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft4\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft4/optional\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft6\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft6/optional\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft7\]" + - TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft7/optional\]" + +jobs: + allow_failures: + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft3\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft3/optional\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft4\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft4/optional\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft6\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft6/optional\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft7\]" + - env: TEST_SUITE="JsonSchemaTestSuite" FILTER="Draft suite\[draft7/optional\]" php: - 7.2 @@ -28,7 +46,7 @@ before_script: - mkdir -p build/logs script: - - ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml --testdox + - ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml --testdox --testsuite="$TEST_SUITE" --filter="$FILTER" after_script: - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT diff --git a/composer.json b/composer.json index 4dd7229..22fed22 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "ext-mbstring": "*" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.4" + "phpunit/phpunit": "^8.5 || ^9.4", + "json-schema/json-schema-test-suite": "2.0.0" }, "suggest": { "symplify/easy-coding-standard": "Allows pretty printing of the generated code" @@ -29,6 +30,20 @@ "PHPModelGenerator\\": "src" } }, + "repositories": [ + { + "type": "package", + "package": { + "name": "json-schema/json-schema-test-suite", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/json-schema/JSON-Schema-Test-Suite", + "reference": "2.0.0" + } + } + } + ], "autoload-dev": { "psr-4": { "PHPModelGenerator\\Tests\\": "tests", diff --git a/docs/source/generator/postProcessor.rst b/docs/source/generator/postProcessor.rst index 0244708..14ba4a3 100644 --- a/docs/source/generator/postProcessor.rst +++ b/docs/source/generator/postProcessor.rst @@ -144,7 +144,7 @@ By default additional properties are not included in serialized models. If the * Custom Post Processors ---------------------- -You can implement custom post processors to accomplish your tasks. Each post processor must implement the **PHPModelGenerator\\SchemaProcessor\\PostProcessor\\PostProcessorInterface**. If you have implemented a post processor add the post processor to your `ModelGenerator` and the post processor will be executed for each class. +You can implement custom post processors to accomplish your tasks. Each post processor must extend the class **PHPModelGenerator\\SchemaProcessor\\PostProcessor\\PostProcessor**. If you have implemented a post processor add the post processor to your `ModelGenerator` and the post processor will be executed for each class. A custom post processor which adds a custom trait to the generated model (eg. a trait adding methods for an active record pattern implementation) may look like: @@ -153,9 +153,9 @@ A custom post processor which adds a custom trait to the generated model (eg. a namespace MyApp\Model\Generator\PostProcessor; use MyApp\Model\ActiveRecordTrait; - use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; + use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; - class ActiveRecordPostProcessor implements PostProcessorInterface + class ActiveRecordPostProcessor extends PostProcessor { public function process(Schema $schema, GeneratorConfiguration $generatorConfiguration): void { @@ -184,3 +184,5 @@ What can you do inside your custom post processor? If a setter for a property is called with the same value which is already stored internally (consequently no update of the property is required), the setters will return directly and as a result of that the setter hooks will not be executed. This behaviour also applies also to properties changed via the *populate* method added by the `PopulatePostProcessor <#populatepostprocessor>`__ and the *setAdditionalProperty* method added by the `AdditionalPropertiesAccessorPostProcessor <#additionalpropertiesaccessorpostprocessor>`__ + +To execute code before/after the processing of the schemas override the methods **preProcess** and **postProcess** inside your custom post processor. \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 9418892..53e4386 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -16,8 +16,14 @@ src - - tests - tests/manual - + + + tests + tests/manual + tests/JsonSchemaTestSuite + + + tests/JsonSchemaTestSuite + + diff --git a/src/Model/RenderJob.php b/src/Model/RenderJob.php index 1084415..3b9effe 100644 --- a/src/Model/RenderJob.php +++ b/src/Model/RenderJob.php @@ -11,7 +11,7 @@ use PHPModelGenerator\Exception\ValidationException; use PHPModelGenerator\Model\Validator\AbstractComposedPropertyValidator; use PHPModelGenerator\SchemaProcessor\Hook\SchemaHookResolver; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\Utils\RenderHelper; /** @@ -51,7 +51,7 @@ public function __construct( } /** - * @param PostProcessorInterface[] $postProcessors + * @param PostProcessor[] $postProcessors * @param GeneratorConfiguration $generatorConfiguration */ public function postProcess(array $postProcessors, GeneratorConfiguration $generatorConfiguration) diff --git a/src/ModelGenerator.php b/src/ModelGenerator.php index 2dd43d3..a5eb642 100644 --- a/src/ModelGenerator.php +++ b/src/ModelGenerator.php @@ -10,7 +10,7 @@ use PHPModelGenerator\Exception\SchemaException; use PHPModelGenerator\Model\GeneratorConfiguration; use PHPModelGenerator\SchemaProcessor\PostProcessor\Internal\CompositionValidationPostProcessor; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\SchemaProcessor\PostProcessor\SerializationPostProcessor; use PHPModelGenerator\SchemaProcessor\RenderQueue; use PHPModelGenerator\SchemaProcessor\SchemaProcessor; @@ -27,7 +27,7 @@ class ModelGenerator { /** @var GeneratorConfiguration */ protected $generatorConfiguration; - /** @var PostProcessorInterface[] */ + /** @var PostProcessor[] */ protected $postProcessors = []; /** @@ -48,11 +48,11 @@ public function __construct(GeneratorConfiguration $generatorConfiguration = nul } /** - * @param PostProcessorInterface $postProcessor + * @param PostProcessor $postProcessor * * @return $this */ - public function addPostProcessor(PostProcessorInterface $postProcessor): self + public function addPostProcessor(PostProcessor $postProcessor): self { $this->postProcessors[] = $postProcessor; diff --git a/src/SchemaProcessor/PostProcessor/AdditionalPropertiesAccessorPostProcessor.php b/src/SchemaProcessor/PostProcessor/AdditionalPropertiesAccessorPostProcessor.php index 78eaa43..ca1ddf2 100644 --- a/src/SchemaProcessor/PostProcessor/AdditionalPropertiesAccessorPostProcessor.php +++ b/src/SchemaProcessor/PostProcessor/AdditionalPropertiesAccessorPostProcessor.php @@ -25,7 +25,7 @@ * * @package PHPModelGenerator\SchemaProcessor\PostProcessor */ -class AdditionalPropertiesAccessorPostProcessor implements PostProcessorInterface +class AdditionalPropertiesAccessorPostProcessor extends PostProcessor { /** @var bool */ private $addForModelsWithoutAdditionalPropertiesDefinition; diff --git a/src/SchemaProcessor/PostProcessor/Internal/CompositionValidationPostProcessor.php b/src/SchemaProcessor/PostProcessor/Internal/CompositionValidationPostProcessor.php index c086410..a03ac81 100644 --- a/src/SchemaProcessor/PostProcessor/Internal/CompositionValidationPostProcessor.php +++ b/src/SchemaProcessor/PostProcessor/Internal/CompositionValidationPostProcessor.php @@ -11,7 +11,7 @@ use PHPModelGenerator\Model\SchemaDefinition\JsonSchema; use PHPModelGenerator\Model\Validator\AbstractComposedPropertyValidator; use PHPModelGenerator\SchemaProcessor\Hook\SetterBeforeValidationHookInterface; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\SchemaProcessor\PostProcessor\RenderedMethod; use PHPModelGenerator\Utils\RenderHelper; @@ -25,7 +25,7 @@ * * @package PHPModelGenerator\SchemaProcessor\PostProcessor\Internal */ -class CompositionValidationPostProcessor implements PostProcessorInterface +class CompositionValidationPostProcessor extends PostProcessor { /** * @param Schema $schema diff --git a/src/SchemaProcessor/PostProcessor/PopulatePostProcessor.php b/src/SchemaProcessor/PostProcessor/PopulatePostProcessor.php index 2a23e82..8d0ec2d 100644 --- a/src/SchemaProcessor/PostProcessor/PopulatePostProcessor.php +++ b/src/SchemaProcessor/PostProcessor/PopulatePostProcessor.php @@ -13,7 +13,7 @@ * * @package PHPModelGenerator\SchemaProcessor\PostProcessor */ -class PopulatePostProcessor implements PostProcessorInterface +class PopulatePostProcessor extends PostProcessor { public function process(Schema $schema, GeneratorConfiguration $generatorConfiguration): void { diff --git a/src/SchemaProcessor/PostProcessor/PostProcessor.php b/src/SchemaProcessor/PostProcessor/PostProcessor.php new file mode 100644 index 0000000..37baeae --- /dev/null +++ b/src/SchemaProcessor/PostProcessor/PostProcessor.php @@ -0,0 +1,33 @@ +preProcess(); + } + foreach ($this->jobs as $job) { $job->postProcess($postProcessors, $generatorConfiguration); $job->render($destination, $generatorConfiguration); } + foreach ($postProcessors as $postProcessor) { + $postProcessor->postProcess(); + } + $this->jobs = []; } } \ No newline at end of file diff --git a/tests/Basic/BasicSchemaGenerationTest.php b/tests/Basic/BasicSchemaGenerationTest.php index 370fbfc..a5347b2 100644 --- a/tests/Basic/BasicSchemaGenerationTest.php +++ b/tests/Basic/BasicSchemaGenerationTest.php @@ -13,7 +13,7 @@ use PHPModelGenerator\Model\Schema; use PHPModelGenerator\ModelGenerator; use PHPModelGenerator\SchemaProcessor\Hook\SetterBeforeValidationHookInterface; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTest; /** @@ -66,7 +66,7 @@ public function testGetterAndSetterAreGeneratedForMutableObjects(bool $implicitN public function testSetterLogicIsNotExecutedWhenValueIsIdentical(): void { $this->modifyModelGenerator = function (ModelGenerator $modelGenerator): void { - $modelGenerator->addPostProcessor(new class () implements PostProcessorInterface { + $modelGenerator->addPostProcessor(new class () extends PostProcessor { public function process(Schema $schema, GeneratorConfiguration $generatorConfiguration): void { $schema->addSchemaHook(new class () implements SetterBeforeValidationHookInterface { diff --git a/tests/Basic/SchemaHookTest.php b/tests/Basic/SchemaHookTest.php index be72f16..475fdce 100644 --- a/tests/Basic/SchemaHookTest.php +++ b/tests/Basic/SchemaHookTest.php @@ -15,7 +15,7 @@ use PHPModelGenerator\SchemaProcessor\Hook\SchemaHookInterface; use PHPModelGenerator\SchemaProcessor\Hook\SetterAfterValidationHookInterface; use PHPModelGenerator\SchemaProcessor\Hook\SetterBeforeValidationHookInterface; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTest; /** @@ -184,7 +184,7 @@ public function setterAfterValidationHookDataProvider(): array protected function addSchemaHook(SchemaHookInterface $schemaHook): void { $this->modifyModelGenerator = function (ModelGenerator $modelGenerator) use ($schemaHook): void { - $modelGenerator->addPostProcessor(new class ($schemaHook) implements PostProcessorInterface { + $modelGenerator->addPostProcessor(new class ($schemaHook) extends PostProcessor { private $schemaHook; public function __construct(SchemaHookInterface $schemaHook) diff --git a/tests/JsonSchemaTestSuite/JsonSchemaTestSuiteTest.php b/tests/JsonSchemaTestSuite/JsonSchemaTestSuiteTest.php new file mode 100644 index 0000000..bbfdef3 --- /dev/null +++ b/tests/JsonSchemaTestSuite/JsonSchemaTestSuiteTest.php @@ -0,0 +1,106 @@ +generateClassFromFileTemplate('ObjectTemplate.json', [$schema], null, false, false); + + if (!$valid) { + $this->expectException(ValidationException::class); + } else { + $this->expectNotToPerformAssertions(); + } + + new $className($data); + + $this->fail(); + } + + public function draftDataProvider(): array + { + $drafts = [ + 'draft3', + 'draft3/optional', + 'draft4', + 'draft4/optional', + 'draft6', + 'draft6/optional', + 'draft7', + 'draft7/optional', + ]; + + $tests = []; + + foreach ($drafts as $draft) { + foreach ($this->getFilesForDraft($draft) as $key => $path) { + foreach ($this->setUpDataProviderFromSchemaTestSuiteFile($path) as $testSuiteKey => $test) { + $tests["Draft suite[$draft] $key - $testSuiteKey"] = $test; + } + } + } + + return $tests; + } + + public function getFilesForDraft(string $draft): array + { + $files = []; + + foreach ( + new DirectoryIterator(__DIR__ . '/../../vendor/json-schema/json-schema-test-suite/tests/' . $draft) + as + $item + ) { + if ($item->isFile()) { + $files[$item->getBasename()] = $item->getRealPath(); + } + } + + return $files; + } + + public function setUpDataProviderFromSchemaTestSuiteFile(string $file): array + { + $testFile = json_decode(file_get_contents($file), true); + + $tests = []; + + foreach ($testFile as $test) { + foreach ($test['tests'] as $dataProvider) { + $tests["{$test['description']}: {$dataProvider['description']}"] = [ + 'schema' => json_encode($test['schema']), + 'valid' => $dataProvider['valid'], + 'data' => ['property' => $dataProvider['data']], + ]; + } + } + + return $tests; + } +} diff --git a/tests/PostProcessor/AdditionalPropertiesAccessorPostProcessorTest.php b/tests/PostProcessor/AdditionalPropertiesAccessorPostProcessorTest.php index 9aabf2f..2c6ff16 100644 --- a/tests/PostProcessor/AdditionalPropertiesAccessorPostProcessorTest.php +++ b/tests/PostProcessor/AdditionalPropertiesAccessorPostProcessorTest.php @@ -16,7 +16,7 @@ use PHPModelGenerator\ModelGenerator; use PHPModelGenerator\SchemaProcessor\Hook\SetterBeforeValidationHookInterface; use PHPModelGenerator\SchemaProcessor\PostProcessor\AdditionalPropertiesAccessorPostProcessor; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTest; /** @@ -268,7 +268,7 @@ public function testSetterSchemaHooksAreResolvedInSetAdditionalProperties(): voi $this->modifyModelGenerator = function (ModelGenerator $modelGenerator): void { $modelGenerator ->addPostProcessor(new AdditionalPropertiesAccessorPostProcessor()) - ->addPostProcessor(new class () implements PostProcessorInterface { + ->addPostProcessor(new class () extends PostProcessor { public function process(Schema $schema, GeneratorConfiguration $generatorConfiguration): void { $schema->addSchemaHook(new class () implements SetterBeforeValidationHookInterface { diff --git a/tests/PostProcessor/PopulatePostProcessorTest.php b/tests/PostProcessor/PopulatePostProcessorTest.php index 5494135..10b28ba 100644 --- a/tests/PostProcessor/PopulatePostProcessorTest.php +++ b/tests/PostProcessor/PopulatePostProcessorTest.php @@ -17,7 +17,7 @@ use PHPModelGenerator\SchemaProcessor\Hook\SetterAfterValidationHookInterface; use PHPModelGenerator\SchemaProcessor\Hook\SetterBeforeValidationHookInterface; use PHPModelGenerator\SchemaProcessor\PostProcessor\PopulatePostProcessor; -use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessorInterface; +use PHPModelGenerator\SchemaProcessor\PostProcessor\PostProcessor; use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTest; class PopulatePostProcessorTest extends AbstractPHPModelGeneratorTest @@ -205,7 +205,7 @@ public function testSetterBeforeValidationHookInsidePopulateIsResolved(): void { $this->modifyModelGenerator = function (ModelGenerator $modelGenerator): void { $modelGenerator->addPostProcessor(new PopulatePostProcessor()); - $modelGenerator->addPostProcessor(new class () implements PostProcessorInterface { + $modelGenerator->addPostProcessor(new class () extends PostProcessor { public function process(Schema $schema, GeneratorConfiguration $generatorConfiguration): void { $schema->addSchemaHook(new class () implements SetterBeforeValidationHookInterface { @@ -249,7 +249,7 @@ public function testSetterAfterValidationHookInsidePopulateIsResolved( { $this->modifyModelGenerator = function (ModelGenerator $modelGenerator): void { $modelGenerator->addPostProcessor(new PopulatePostProcessor()); - $modelGenerator->addPostProcessor(new class () implements PostProcessorInterface { + $modelGenerator->addPostProcessor(new class () extends PostProcessor { public function process(Schema $schema, GeneratorConfiguration $generatorConfiguration): void { $schema->addSchemaHook(new class () implements SetterAfterValidationHookInterface { diff --git a/tests/Schema/JsonSchemaTestSuiteTest/ObjectTemplate.json b/tests/Schema/JsonSchemaTestSuiteTest/ObjectTemplate.json new file mode 100644 index 0000000..7cb060c --- /dev/null +++ b/tests/Schema/JsonSchemaTestSuiteTest/ObjectTemplate.json @@ -0,0 +1,6 @@ +{ + "type": "object", + "properties": { + "property": %s + } +} \ No newline at end of file