1 | <?php |
||
14 | class Generator |
||
15 | { |
||
16 | /** |
||
17 | * @var BuilderFactory |
||
18 | */ |
||
19 | private $factory; |
||
20 | |||
21 | /** |
||
22 | * @var PrettyPrinterAbstract |
||
23 | */ |
||
24 | private $printer; |
||
25 | |||
26 | /** |
||
27 | * @var System |
||
28 | */ |
||
29 | private $system; |
||
30 | |||
31 | 2 | public function __construct( |
|
40 | |||
41 | 1 | public function generate(ObjectSchema $schema, string $className, string $baseClass = ''): array |
|
42 | { |
||
43 | 1 | $classes = []; |
|
44 | |||
45 | 1 | $className = new Name($className); |
|
46 | // Start the class AST definition |
||
47 | 1 | $namespace = $this->factory->namespace($className->slice(0, -1)->toString()); |
|
48 | 1 | $class = $this->factory->class($className->getLast()); |
|
49 | |||
50 | 1 | if ($baseClass) { |
|
51 | 1 | $baseClassName = new Name($baseClass); |
|
52 | // Import the base class with a "use" statement |
||
53 | 1 | $namespace->addStmt($this->factory->use($baseClassName)); |
|
54 | // Make the class extend the base class |
||
55 | 1 | $class->extend($baseClassName->getLast()); |
|
56 | } |
||
57 | |||
58 | 1 | foreach ($schema->properties() as $name => $property) { |
|
59 | 1 | $typeHint = $property->phpType(); |
|
60 | |||
61 | 1 | if ($property->isObject()) { |
|
62 | // Create a new class for this property |
||
63 | 1 | $nextClass = Name::concat($className, ucfirst($name)); |
|
64 | 1 | $typeHint = '\\' . $nextClass->toString(); |
|
65 | 1 | $classes = array_merge($classes, $this->generate( |
|
66 | 1 | $property, |
|
|
|||
67 | 1 | $nextClass->toString(), |
|
68 | 1 | $baseClass |
|
69 | )); |
||
70 | 1 | } elseif ($property->isArray() && $property->hasItems() && $property->items()->isObject()) { |
|
71 | // Create a new class for this array of properties |
||
72 | 1 | $nextClass = Name::concat($className, ucfirst(singular($name))); |
|
73 | 1 | $typeHint = '\\' . $nextClass->toString() . '[]'; |
|
74 | 1 | $classes = array_merge($classes, $this->generate( |
|
75 | 1 | $property->items(), |
|
76 | 1 | $nextClass->toString(), |
|
77 | 1 | $baseClass |
|
78 | )); |
||
79 | 1 | } elseif (!$schema->isRequired($name) && !$property->isNull()) { |
|
80 | 1 | $typeHint = "$typeHint|null"; |
|
81 | } |
||
82 | |||
83 | // Add a property declaration to the class |
||
84 | 1 | $class->addStmt( |
|
85 | 1 | $this->factory->property($name) |
|
86 | 1 | ->makePublic() |
|
87 | 1 | ->setDocComment("/**\n * @var $typeHint\n */") |
|
88 | ); |
||
89 | } |
||
90 | |||
91 | // Add the class declaration to the namespace |
||
92 | 1 | $namespace->addStmt($class); |
|
93 | |||
94 | 1 | $classes[$className->toString()] = $namespace->getNode(); |
|
95 | |||
96 | 1 | return $classes; |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @param Ns[] $classes |
||
101 | * @return string[] |
||
102 | */ |
||
103 | 1 | public function write(array $classes, string $rootDirectory, string $rootNamespace = ''): array |
|
126 | |||
127 | 2 | protected function defaultBuilder(): BuilderFactory |
|
132 | |||
133 | 2 | protected function defaultPrinter(): PrettyPrinterAbstract |
|
139 | |||
140 | 1 | protected function defaultSystem(): System |
|
144 | |||
145 | 1 | private function classNode(array $stmts): Cls |
|
159 | } |
||
160 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.