Skip to content

Commit 3b10a5e

Browse files
committed
* Extended array type hints to contain the value of each element (eg. string[]). Especially useful for object auto completion
* Added root node to SchemaDefinitionDictionary to be aple to process references to whole files * Implemented "null" or no provided value for optional enums * Extended DocBlocks of generated getter/setter methods * Fixed external path references for model-files which aren't located in the root directory of the generation process * Renamed Generator to avoid collisions with built-in Generator * Added a public method to generate/clean-up the model directory for a generation process * Removed unused file
1 parent ba6dc2c commit 3b10a5e

24 files changed

+270
-80
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ The base object for generating models is the *Generator*. After you have created
2727
->generateModels(__DIR__ . '/schema', __DIR__ . '/result');
2828
```
2929

30-
As an optional parameter you can set up a *GeneratorConfiguration* object to configure your Generator:
30+
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):
3131

3232
```php
3333
$generator = new Generator(
@@ -36,7 +36,9 @@ $generator = new Generator(
3636
->setImmutable(true)
3737
);
3838

39-
$generator->generateModels(__DIR__ . '/schema', __DIR__ . '/result');
39+
$generator
40+
->generateModelDirectory(__DIR__ . '/result');
41+
->generateModels(__DIR__ . '/schema', __DIR__ . '/result');
4042
```
4143

4244
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.

src/Model/Property/Property.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPModelGenerator\Model\Validator;
99
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
1010
use PHPModelGenerator\PropertyProcessor\Decorator\PropertyDecoratorInterface;
11+
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHintDecoratorInterface;
1112

1213
/**
1314
* Class Property
@@ -37,6 +38,8 @@ class Property implements PropertyInterface
3738
protected $schema;
3839
/** @var PropertyDecoratorInterface[] */
3940
public $decorators = [];
41+
/** @var TypeHintDecoratorInterface[] */
42+
public $typeHintDecorators = [];
4043

4144
/**
4245
* Property constructor.
@@ -85,6 +88,30 @@ public function setType(string $type): PropertyInterface
8588
return $this;
8689
}
8790

91+
/**
92+
* @inheritdoc
93+
*/
94+
public function getTypeHint(): string
95+
{
96+
$input = $this->type ?: 'mixed';
97+
98+
foreach ($this->typeHintDecorators as $decorator) {
99+
$input = $decorator->decorate($input);
100+
}
101+
102+
return $input;
103+
}
104+
105+
/**
106+
* @inheritdoc
107+
*/
108+
public function addTypeHintDecorator(TypeHintDecoratorInterface $typeHintDecorator): PropertyInterface
109+
{
110+
$this->typeHintDecorators[] = $typeHintDecorator;
111+
112+
return $this;
113+
}
114+
88115
/**
89116
* @inheritdoc
90117
*/

src/Model/Property/PropertyInterface.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPModelGenerator\Model\Validator;
99
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
1010
use PHPModelGenerator\PropertyProcessor\Decorator\PropertyDecoratorInterface;
11+
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHintDecoratorInterface;
1112

1213
/**
1314
* Interface PropertyInterface
@@ -38,6 +39,18 @@ public function getType(): string;
3839
*/
3940
public function setType(string $type): PropertyInterface;
4041

42+
/**
43+
* @return string
44+
*/
45+
public function getTypeHint(): string;
46+
47+
/**
48+
* @param TypeHintDecoratorInterface $typeHintDecorator
49+
*
50+
* @return PropertyInterface
51+
*/
52+
public function addTypeHintDecorator(TypeHintDecoratorInterface $typeHintDecorator): PropertyInterface;
53+
4154
/**
4255
* Get a description for the property. If no description is available an empty string will be returned
4356
*

src/Model/Property/PropertyProxy.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPModelGenerator\Model\Schema;
99
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
1010
use PHPModelGenerator\PropertyProcessor\Decorator\PropertyDecoratorInterface;
11+
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHintDecoratorInterface;
1112

1213
/**
1314
* Class PropertyProxy
@@ -75,6 +76,22 @@ public function setType(string $type): PropertyInterface
7576
return $this->getProperty()->setType($type);
7677
}
7778

79+
/**
80+
* @inheritdoc
81+
*/
82+
public function getTypeHint(): string
83+
{
84+
return $this->getProperty()->getTypeHint();
85+
}
86+
87+
/**
88+
* @inheritdoc
89+
*/
90+
public function addTypeHintDecorator(TypeHintDecoratorInterface $typeHintDecorator): PropertyInterface
91+
{
92+
return $this->getProperty()->addTypeHintDecorator($typeHintDecorator);
93+
}
94+
7895
/**
7996
* @inheritdoc
8097
*/

src/Model/SchemaDefinition/SchemaDefinitionDictionary.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public function setUpDefinitionDictionary(
4545
SchemaProcessor $schemaProcessor,
4646
Schema $schema
4747
): void {
48+
// attach the root node to the definition dictionary
49+
$this->addDefinition('#', new SchemaDefinition($propertyData, $schemaProcessor, $schema));
50+
4851
foreach ($propertyData as $key => $propertyEntry) {
4952
if (!is_array($propertyEntry)) {
5053
continue;
@@ -115,8 +118,13 @@ public function getDefinition(string $key, SchemaProcessor $schemaProcessor, arr
115118
$key = array_shift($path);
116119
}
117120

118-
if (!isset($this[$key]) && strstr($key, '#', true)) {
119-
[$jsonSchemaFile, $externalKey] = explode('#', $key);
121+
if (!isset($this[$key])) {
122+
if (strstr($key, '#', true)) {
123+
[$jsonSchemaFile, $externalKey] = explode('#', $key);
124+
} else {
125+
$jsonSchemaFile = $key;
126+
$externalKey = '';
127+
}
120128

121129
if (array_key_exists($jsonSchemaFile, $this->parsedExternalFileSchemas)) {
122130
return $this->parsedExternalFileSchemas[$jsonSchemaFile]->getSchemaDictionary()->getDefinition(
@@ -155,7 +163,7 @@ protected function parseExternalFile(
155163
: $this->sourceDirectory . '/' . $jsonSchemaFile;
156164

157165
if (!filter_var($jsonSchemaFilePath, FILTER_VALIDATE_URL) && !is_file($jsonSchemaFilePath)) {
158-
throw new SchemaException("Reference to non existing JSON-Schema file $path");
166+
throw new SchemaException("Reference to non existing JSON-Schema file $jsonSchemaFilePath");
159167
}
160168

161169
$jsonSchema = file_get_contents($jsonSchemaFilePath);

src/Generator.php renamed to src/ModelGenerator.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PHPModelGenerator;
66

7+
use FilesystemIterator;
78
use PHPModelGenerator\Exception\FileSystemException;
89
use PHPModelGenerator\Exception\RenderException;
910
use PHPModelGenerator\Exception\SchemaException;
@@ -16,11 +17,11 @@
1617
use RegexIterator;
1718

1819
/**
19-
* Class Generator
20+
* Class ModelGenerator
2021
*
2122
* @package PHPModelGenerator
2223
*/
23-
class Generator
24+
class ModelGenerator
2425
{
2526
/** @var GeneratorConfiguration */
2627
protected $generatorConfiguration;
@@ -35,6 +36,32 @@ public function __construct(GeneratorConfiguration $generatorConfiguration = nul
3536
$this->generatorConfiguration = $generatorConfiguration ?? new GeneratorConfiguration();
3637
}
3738

39+
/**
40+
* Create an directory to store the models in. If the directory already exists and contains files all files will be
41+
* removed to provide an empty directory for model generation.
42+
*
43+
* @param string $modelPath The absolute path to the directory
44+
* @param int $directoryMode The mode to create the directory with
45+
*
46+
* @return ModelGenerator
47+
*/
48+
public function generateModelDirectory(string $modelPath, int $directoryMode = 0777): self
49+
{
50+
if (!is_dir($modelPath)) {
51+
mkdir($modelPath, $directoryMode, true);
52+
}
53+
54+
$di = new RecursiveDirectoryIterator($modelPath, FilesystemIterator::SKIP_DOTS);
55+
56+
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
57+
58+
foreach ($ri as $file ) {
59+
$file->isDir() ? rmdir($file) : unlink($file);
60+
}
61+
62+
return $this;
63+
}
64+
3865
/**
3966
* Generate models from JSON-Schema files. Returns an array of generated file names on success.
4067
*
@@ -63,7 +90,7 @@ public function generateModels(string $source, string $destination): array
6390
$schemaProcessor = new SchemaProcessor($source, $destination, $this->generatorConfiguration, $renderProxy);
6491

6592
foreach ($this->getSchemaFiles($source) as $jsonSchemaFile) {
66-
$schemaProcessor->process($jsonSchemaFile, $source);
93+
$schemaProcessor->process($jsonSchemaFile);
6794
}
6895

6996
// render all collected classes

src/PropertyProcessor/ComposedValue/AbstractComposedPropertiesProcessor.php

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\Decorator;
6+
7+
use PHPModelGenerator\Model\Property\PropertyInterface;
8+
9+
/**
10+
* Class ArrayTypeHintDecorator
11+
*
12+
* @package PHPModelGenerator\PropertyProcessor\Decorator
13+
*/
14+
class ArrayTypeHintDecorator implements TypeHintDecoratorInterface
15+
{
16+
/** @var PropertyInterface */
17+
protected $nestedProperty;
18+
19+
/**
20+
* ArrayTypeHintDecorator constructor.
21+
*
22+
* @param PropertyInterface $nestedProperty
23+
*/
24+
public function __construct(PropertyInterface $nestedProperty)
25+
{
26+
$this->nestedProperty = $nestedProperty;
27+
}
28+
29+
/**
30+
* @inheritdoc
31+
*/
32+
public function decorate(string $input): string
33+
{
34+
return "{$this->nestedProperty->getTypeHint()}[]";
35+
}
36+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\Decorator;
6+
7+
/**
8+
* Interface TypeHintDecoratorInterface
9+
*
10+
* @package PHPModelGenerator\PropertyProcessor\Decorator
11+
*/
12+
interface TypeHintDecoratorInterface
13+
{
14+
/**
15+
* Decorate a given string
16+
*
17+
* @param string $input The input getting decorated
18+
*
19+
* @return string
20+
*/
21+
public function decorate(string $input): string;
22+
}

src/PropertyProcessor/Property/AbstractPropertyProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ protected function addEnumValidator(PropertyInterface $property, array $allowedV
7979
$property->addValidator(
8080
new PropertyValidator(
8181
'!in_array($value, ' .
82-
preg_replace('(\d+\s=>)', '', var_export(array_values($allowedValues), true)) .
82+
preg_replace('(\d+\s=>)', '', var_export(array_merge([null], array_values($allowedValues)), true)) .
8383
', true)',
8484
InvalidArgumentException::class,
8585
"Invalid value for {$property->getName()} declined by enum constraint"

0 commit comments

Comments
 (0)