Skip to content

Commit dea347a

Browse files
committed
Instead of a source directory the generateModels method now accepts a SchemaProvider which provides all JSON Schema files.
Available providers are: RecursiveDirectoryProvider (replacement for the previous behaviour) and the OpenAPIv3Provider
1 parent 7bebdc2 commit dea347a

File tree

12 files changed

+219
-64
lines changed

12 files changed

+219
-64
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ $generator = new Generator(
6262

6363
$generator
6464
->generateModelDirectory(__DIR__ . '/result');
65-
->generateModels(__DIR__ . '/schema', __DIR__ . '/result');
65+
->generateModels(new RecursiveDirectoryProvider(__DIR__ . '/schema'), __DIR__ . '/result');
6666
```
6767

6868
The generator will check the given source directory recursive and convert all found *.json files to models. All JSON-Schema files inside the source directory must provide a schema of an object.

docs/source/complexTypes/object.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ If the given main object in a JSON-Schema file contains a `$id` the id will be u
6666
Naming of nested classes
6767
^^^^^^^^^^^^^^^^^^^^^^^^
6868

69-
Nested classes are prefixed with the parent class. If an object `Person` has a nested object `car` the class for car will be named **Person_Car**.
70-
71-
For the class name of a nested class the `$id` property of the nested object is used. If the id property isn't present the property key combined with a uniqid will be used.
69+
For the class name of a nested class the `$id` property of the nested object is used. If the id property isn't present the property key will be prefixed with the parent class. If an object `Person` has a nested object `car` without a `$id` the class for car will be named **Person_Car**.
7270

7371
Property Name Normalization
7472
^^^^^^^^^^^^^^^^^^^^^^^^^^^

docs/source/generic/namespaces.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Your model generation code inside `generateModels.php` now could look like:
3434
3535
$generator
3636
->generateModelDirectory(__DIR__ . '/build')
37-
->generateModels(__DIR__ . '/Models', __DIR__ . '/build');
37+
->generateModels(new RecursiveDirectoryProvider(__DIR__ . '/Models'), __DIR__ . '/build');
3838
3939
The generated main classes will be:
4040

docs/source/gettingStarted.rst

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,18 @@ The base object for generating models is the *Generator*. After you have created
2121
.. code-block:: php
2222
2323
(new Generator())
24-
->generateModels(__DIR__ . '/schema', __DIR__ . '/result');
24+
->generateModels(new RecursiveDirectoryProvider(__DIR__ . '/schema'), __DIR__ . '/result');
25+
26+
The first parameter of the *generateModels* method must be a class implementing the *SchemaProviderInterface*. The provider fetches the JSON schema files and provides them for the generator. The following providers are available:
27+
28+
=========================== ===========
29+
Provider Description
30+
=========================== ===========
31+
RecursiveDirectoryProvider Fetches all *.json files from the given source directory. Each file must contain a JSON Schema object definition on the top level
32+
OpenAPIv3Provider Fetches all objects defined in the #/components/schemas section of an Open API v3 spec file
33+
=========================== ===========
34+
35+
The second parameter must point to an existing and empty directory. This directory will contain the generated PHP classes after the generator is finished.
2536

2637
As an optional parameter you can set up a *GeneratorConfiguration* object to configure your Generator and/or use the method *generateModelDirectory* to generate your model directory (will generate the directory if it doesn't exist; if it exists, all contained files and folders will be removed for a clean generation process):
2738

@@ -35,7 +46,7 @@ As an optional parameter you can set up a *GeneratorConfiguration* object to con
3546
3647
$generator
3748
->generateModelDirectory(__DIR__ . '/result');
38-
->generateModels(__DIR__ . '/schema', __DIR__ . '/result');
49+
->generateModels(new RecursiveDirectoryProvider(__DIR__ . '/schema'), __DIR__ . '/result');
3950
4051
The generator will check the given source directory recursive and convert all found \*.json files to models. All JSON-Schema files inside the source directory must provide a schema of an object.
4152

src/ModelGenerator.php

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
use PHPModelGenerator\Model\GeneratorConfiguration;
1212
use PHPModelGenerator\SchemaProcessor\RenderQueue;
1313
use PHPModelGenerator\SchemaProcessor\SchemaProcessor;
14+
use PHPModelGenerator\SchemaProvider\SchemaProviderInterface;
1415
use RecursiveDirectoryIterator;
1516
use RecursiveIteratorIterator;
16-
use RecursiveRegexIterator;
17-
use RegexIterator;
1817

1918
/**
2019
* Class ModelGenerator
@@ -64,8 +63,8 @@ public function generateModelDirectory(string $modelPath, int $directoryMode = 0
6463
/**
6564
* Generate models from JSON-Schema files. Returns an array of generated file names on success.
6665
*
67-
* @param string $source The directory with the JSON-Schema files
68-
* @param string $destination The directory where to put the generated PHP models
66+
* @param SchemaProviderInterface $schemaProvider The provider used to fetch the JSON schemas to process
67+
* @param string $destination The directory where to put the generated PHP models
6968
*
7069
* @return array
7170
*
@@ -75,21 +74,22 @@ public function generateModelDirectory(string $modelPath, int $directoryMode = 0
7574
* @throws FileSystemException Will be thrown if a file system error occurred
7675
* @throws RenderException Will be thrown if a class can't be rendered correctly
7776
*/
78-
public function generateModels(string $source, string $destination): array
77+
public function generateModels(SchemaProviderInterface $schemaProvider, string $destination): array
7978
{
80-
if (!is_dir($source)) {
81-
throw new FileSystemException("Source directory '$source' doesn't exist");
82-
}
83-
8479
if (!is_dir($destination) || count(scandir($destination)) > 2) {
8580
throw new FileSystemException("Destination directory '$destination' doesn't exist or is not empty");
8681
}
8782

8883
$renderQueue = new RenderQueue();
89-
$schemaProcessor = new SchemaProcessor($source, $destination, $this->generatorConfiguration, $renderQueue);
90-
91-
foreach ($this->getSchemaFiles($source) as $jsonSchemaFile) {
92-
$schemaProcessor->process($jsonSchemaFile);
84+
$schemaProcessor = new SchemaProcessor(
85+
$schemaProvider->getBaseDirectory(),
86+
$destination,
87+
$this->generatorConfiguration,
88+
$renderQueue
89+
);
90+
91+
foreach ($schemaProvider->getSchemas() as [$filePath, $jsonSchema]) {
92+
$schemaProcessor->process($jsonSchema, $filePath);
9393
}
9494

9595
// render all collected classes
@@ -104,24 +104,4 @@ public function generateModels(string $source, string $destination): array
104104

105105
return $schemaProcessor->getGeneratedFiles();
106106
}
107-
108-
/**
109-
* Get all json files from a given directory
110-
*
111-
* @param string $directory
112-
*
113-
* @return array
114-
*/
115-
protected function getSchemaFiles(string $directory) : array
116-
{
117-
$directory = new RecursiveDirectoryIterator($directory);
118-
$iterator = new RecursiveIteratorIterator($directory);
119-
$files = [];
120-
121-
foreach (new RegexIterator($iterator, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH) as $file) {
122-
$files[] = $file[0];
123-
}
124-
125-
return $files;
126-
}
127107
}

src/SchemaProcessor/SchemaProcessor.php

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SchemaProcessor
2525
/** @var RenderQueue */
2626
protected $renderQueue;
2727
/** @var string */
28-
protected $source;
28+
protected $baseSource;
2929
/** @var string */
3030
protected $destination;
3131

@@ -42,18 +42,18 @@ class SchemaProcessor
4242
/**
4343
* SchemaProcessor constructor.
4444
*
45-
* @param string $source
45+
* @param string $baseSource
4646
* @param string $destination
4747
* @param GeneratorConfiguration $generatorConfiguration
4848
* @param RenderQueue $renderQueue
4949
*/
5050
public function __construct(
51-
string $source,
51+
string $baseSource,
5252
string $destination,
5353
GeneratorConfiguration $generatorConfiguration,
5454
RenderQueue $renderQueue
5555
) {
56-
$this->source = $source;
56+
$this->baseSource = $baseSource;
5757
$this->destination = $destination;
5858
$this->generatorConfiguration = $generatorConfiguration;
5959
$this->renderQueue = $renderQueue;
@@ -62,30 +62,25 @@ public function __construct(
6262
/**
6363
* Process a given json schema file
6464
*
65-
* @param string $jsonSchemaFile
65+
* @param array $jsonSchema
66+
* @param string $sourcePath
6667
*
6768
* @throws SchemaException
6869
*/
69-
public function process(string $jsonSchemaFile): void
70+
public function process(array $jsonSchema, string $sourcePath): void
7071
{
71-
$jsonSchema = file_get_contents($jsonSchemaFile);
72-
73-
if (!$jsonSchema || !($decodedJsonSchema = json_decode($jsonSchema, true))) {
74-
throw new SchemaException("Invalid JSON-Schema file $jsonSchemaFile");
75-
}
76-
77-
$this->setCurrentClassPath($jsonSchemaFile);
72+
$this->setCurrentClassPath($sourcePath);
7873
$this->currentClassName = $this->generatorConfiguration->getClassNameGenerator()->getClassName(
79-
str_ireplace('.json', '', basename($jsonSchemaFile)),
80-
$decodedJsonSchema,
74+
str_ireplace('.json', '', basename($sourcePath)),
75+
$jsonSchema,
8176
false
8277
);
8378

8479
$this->processSchema(
85-
$decodedJsonSchema,
80+
$jsonSchema,
8681
$this->currentClassPath,
8782
$this->currentClassName,
88-
new SchemaDefinitionDictionary(dirname($jsonSchemaFile)),
83+
new SchemaDefinitionDictionary(dirname($sourcePath)),
8984
true
9085
);
9186
}
@@ -205,7 +200,7 @@ public function generateClassFile(
205200
*/
206201
protected function setCurrentClassPath(string $jsonSchemaFile): void
207202
{
208-
$path = str_replace($this->source, '', dirname($jsonSchemaFile));
203+
$path = str_replace($this->baseSource, '', dirname($jsonSchemaFile));
209204
$pieces = array_map(
210205
function ($directory) {
211206
return ucfirst($directory);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PHPModelGenerator\SchemaProvider;
6+
7+
use PHPModelGenerator\Exception\SchemaException;
8+
9+
/**
10+
* Class OpenAPIv3Provider
11+
*
12+
* @package PHPModelGenerator\SchemaProvider
13+
*/
14+
class OpenAPIv3Provider implements SchemaProviderInterface
15+
{
16+
/** @var array */
17+
private $openAPIv3Spec;
18+
/** @var string */
19+
private $sourceFile;
20+
21+
/**
22+
* OpenAPIv3Provider constructor.
23+
*
24+
* @param string $sourceFile
25+
*
26+
* @throws SchemaException
27+
*/
28+
public function __construct(string $sourceFile)
29+
{
30+
$this->sourceFile = $sourceFile;
31+
$jsonSchema = file_get_contents($sourceFile);
32+
33+
if (!$jsonSchema || !($this->openAPIv3Spec = json_decode($jsonSchema, true))) {
34+
throw new SchemaException("Invalid JSON-Schema file $sourceFile");
35+
}
36+
37+
if (!isset($this->openAPIv3Spec['components']['schemas'])) {
38+
throw new SchemaException("Open API v3 spec file $sourceFile doesn't contain any schemas to process");
39+
}
40+
}
41+
42+
/**
43+
* @inheritDoc
44+
*/
45+
public function getSchemas(): iterable
46+
{
47+
foreach ($this->openAPIv3Spec['components']['schemas'] as $schemaKey => $schema) {
48+
// use the key of the current schema as $id if no $id is specified
49+
if (!isset($schema['$id'])) {
50+
$schema['$id'] = $schemaKey;
51+
}
52+
53+
yield [$this->sourceFile, $schema];
54+
}
55+
}
56+
57+
/**
58+
* @inheritDoc
59+
*/
60+
public function getBaseDirectory(): string
61+
{
62+
return dirname($this->sourceFile);
63+
}
64+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PHPModelGenerator\SchemaProvider;
6+
7+
use PHPModelGenerator\Exception\FileSystemException;
8+
use PHPModelGenerator\Exception\SchemaException;
9+
use RecursiveDirectoryIterator;
10+
use RecursiveIteratorIterator;
11+
use RecursiveRegexIterator;
12+
use RegexIterator;
13+
14+
/**
15+
* Class RecursiveDirectoryProvider
16+
*
17+
* @package PHPModelGenerator\SchemaProvider
18+
*/
19+
class RecursiveDirectoryProvider implements SchemaProviderInterface
20+
{
21+
/** @var string */
22+
private $sourceDirectory;
23+
24+
/**
25+
* RecursiveDirectoryProvider constructor.
26+
*
27+
* @param string $sourceDirectory
28+
*
29+
* @throws FileSystemException
30+
*/
31+
public function __construct(string $sourceDirectory)
32+
{
33+
if (!is_dir($sourceDirectory)) {
34+
throw new FileSystemException("Source directory '$sourceDirectory' doesn't exist");
35+
}
36+
37+
$this->sourceDirectory = $sourceDirectory;
38+
}
39+
40+
/**
41+
* @inheritDoc
42+
*
43+
* @throws SchemaException
44+
*/
45+
public function getSchemas(): iterable
46+
{
47+
$directory = new RecursiveDirectoryIterator($this->sourceDirectory);
48+
$iterator = new RecursiveIteratorIterator($directory);
49+
50+
foreach (new RegexIterator($iterator, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH) as $file) {
51+
$jsonSchema = file_get_contents($file[0]);
52+
53+
if (!$jsonSchema || !($decodedJsonSchema = json_decode($jsonSchema, true))) {
54+
throw new SchemaException("Invalid JSON-Schema file {$file[0]}");
55+
}
56+
57+
yield [$file[0], $decodedJsonSchema];
58+
}
59+
}
60+
61+
/**
62+
* @inheritDoc
63+
*/
64+
public function getBaseDirectory(): string
65+
{
66+
return $this->sourceDirectory;
67+
}
68+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PHPModelGenerator\SchemaProvider;
6+
7+
/**
8+
* Interface SchemaProviderInterface
9+
*
10+
* @package PHPModelGenerator\SchemaProvider
11+
*/
12+
interface SchemaProviderInterface
13+
{
14+
/**
15+
* Provide an iterable containing all schemas which should be processed.
16+
* Each entry must be represented by a data tuple [string $sourceFile, array $jsonSchema] where $sourceFile contains
17+
* the full file path of the file which contains the JSON schema (used for namespacing) and $jsonSchema must contain
18+
* the decoded schema.
19+
*
20+
* @return iterable
21+
*/
22+
public function getSchemas(): iterable;
23+
24+
/**
25+
* Get the base directory of the provider
26+
*
27+
* @return string
28+
*/
29+
public function getBaseDirectory(): string;
30+
}

0 commit comments

Comments
 (0)