Completed
Push — master ( 2edd34...81ce9d )
by Oleg
02:56
created

ReflectionProvider::getPostParams()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 3
nop 0
dl 0
loc 19
ccs 12
cts 12
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace SlayerBirden\DFCodeGeneration\Generator\Tests;
5
6
use Doctrine\Common\Annotations\AnnotationReader;
7
use Doctrine\ORM\Mapping\Column;
8
use Doctrine\ORM\Mapping\GeneratedValue;
9
use Doctrine\ORM\Mapping\Id;
10
use Doctrine\ORM\Mapping\JoinColumn;
11
use Doctrine\ORM\Mapping\ManyToMany;
12
use Doctrine\ORM\Mapping\ManyToOne;
13
use Doctrine\ORM\Mapping\OneToOne;
14
use SlayerBirden\DFCodeGeneration\Generator\BaseNameTrait;
15
use Zend\Code\Reflection\ClassReflection;
16
17
class ReflectionProvider implements EntityProviderInterface
18
{
19
    use BaseNameTrait;
20
    /**
21
     * @var string
22
     */
23
    private $entityClassName;
24
    private $relations = [
25
        ManyToOne::class,
26
        ManyToMany::class,
27
        OneToOne::class,
28
    ];
29
    /**
30
     * @var ValueProviderInterface
31
     */
32
    private $valueProvider;
33
    /**
34
     * @var array
35
     */
36
    private $spec = [];
37
    /**
38
     * @var array
39
     */
40
    private $params = [];
41
    /**
42
     * @var IdHandlerInterface
43
     */
44
    private $idHandler;
45
    /**
46
     * @var bool|null
47
     */
48
    private $hasUnique;
49
    /**
50
     * @var string|null
51
     */
52
    private $idName;
53
54 9
    public function __construct(
55
        string $entityClassName,
56
        ValueProviderInterface $valueProvider,
57
        IdHandlerInterface $idHandler
58
    ) {
59 9
        $this->entityClassName = $entityClassName;
60 9
        $this->valueProvider = $valueProvider;
61 9
        $this->idHandler = $idHandler;
62 9
    }
63
64
    /**
65
     * @return array
66
     * @throws \Doctrine\Common\Annotations\AnnotationException
67
     * @throws \ReflectionException
68
     */
69 1
    public function getEntitySpec(): array
70
    {
71 1
        if (empty($this->spec)) {
72 1
            $reflectionClassName = new ClassReflection($this->entityClassName);
73 1
            foreach ($reflectionClassName->getProperties() as $property) {
74 1
                $columnType = '';
75 1
                foreach ($this->relations as $type) {
76
                    /** @var ManyToMany|OneToOne|ManyToOne $annotation */
77 1
                    $annotation = (new AnnotationReader())
78 1
                        ->getPropertyAnnotation($property, $type);
79 1
                    if ($annotation) {
80 1
                        $ref = new ClassReflection($annotation);
81 1
                        $columnType = strtolower($ref->getShortName());
82 1
                        $target = $annotation->targetEntity;
83
                        /** @var JoinColumn $joinColumn */
84 1
                        $joinColumn = (new AnnotationReader())
85 1
                            ->getPropertyAnnotation($property, JoinColumn::class);
86 1
                        if ($joinColumn) {
87 1
                            $nullable = $joinColumn->nullable;
88 1
                            $referenceColumn = $joinColumn->referencedColumnName;
89
                        } else {
90 1
                            $nullable = true;
91
                        }
92 1
                        break;
93
                    }
94
                }
95
96 1
                if (empty($columnType)) {
97
                    /** @var Column $column */
98 1
                    $column = (new AnnotationReader())
99 1
                        ->getPropertyAnnotation($property, Column::class);
100 1
                    $columnType = $column->type;
101 1
                    $nullable = $column->nullable;
102
                }
103
104
                $spec = [
105 1
                    'name' => $property->getName(),
106 1
                    'type' => $columnType,
107 1
                    'nullable' => $nullable ?? false,
108
                    'reference' => null,
109
                ];
110 1
                if (isset($target)) {
111 1
                    $spec['reference'] = [
112 1
                        'entity' => $target,
113 1
                        'ref_column_key' => $referenceColumn ?? 'id',
114
                    ];
115
                }
116 1
                $this->spec[] = $spec;
117
            }
118
        }
119
120 1
        return $this->spec;
121
    }
122
123
    /**
124
     * @return array
125
     * @throws \Doctrine\Common\Annotations\AnnotationException
126
     * @throws \ReflectionException
127
     */
128 1
    public function getPostParams(): array
129
    {
130 1
        $params = $this->getParams();
131
132 1
        $postParams = [];
133
134 1
        $reflectionClassName = new ClassReflection($this->entityClassName);
135 1
        foreach ($reflectionClassName->getProperties() as $property) {
136 1
            $key = $property->getName();
137
            /** @var GeneratedValue $generated */
138 1
            $generated = (new AnnotationReader())
139 1
                ->getPropertyAnnotation($property, GeneratedValue::class);
140 1
            if (!empty($generated)) {
141 1
                continue;
142
            }
143 1
            $postParams[$key] = $params[$key];
144
        }
145
146 1
        return $postParams;
147
    }
148
149
    /**
150
     * @return string
151
     * @throws \ReflectionException
152
     */
153 1
    public function getShortName(): string
154
    {
155 1
        return strtolower($this->getBaseName());
156
    }
157
158
    /**
159
     * Immutable
160
     * @return mixed
161
     * @throws \Doctrine\Common\Annotations\AnnotationException
162
     * @throws \ReflectionException
163
     */
164 1
    public function getId()
165
    {
166 1
        $params = $this->getParams();
167 1
        return $params[$this->getIdName()];
168
    }
169
170
    /**
171
     * Immutable
172
     * @return string
173
     */
174 1
    public function getEntityClassName(): string
175
    {
176 1
        return $this->entityClassName;
177
    }
178
179
    /**
180
     * Immutable
181
     * @return bool
182
     * @throws \Doctrine\Common\Annotations\AnnotationException
183
     * @throws \ReflectionException
184
     */
185 1
    public function hasUnique(): bool
186
    {
187 1
        if ($this->hasUnique === null) {
188 1
            $reflectionClassName = new ClassReflection($this->entityClassName);
189 1
            foreach ($reflectionClassName->getProperties() as $property) {
190
                /** @var Column $column */
191 1
                $column = (new AnnotationReader())
192 1
                    ->getPropertyAnnotation($property, Column::class);
193 1
                if ($column->unique) {
194 1
                    $this->hasUnique = true;
195 1
                    break;
196
                }
197
            }
198
        }
199
200 1
        return $this->hasUnique;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->hasUnique could return the type null which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
201
    }
202
203
    /**
204
     * Immutable
205
     * @return array
206
     * @throws \Doctrine\Common\Annotations\AnnotationException
207
     * @throws \ReflectionException
208
     */
209 3
    public function getParams(): array
210
    {
211 3
        if (empty($this->params)) {
212 3
            $reflectionClassName = new ClassReflection($this->entityClassName);
213 3
            foreach ($reflectionClassName->getProperties() as $property) {
214 3
                $key = $property->getName();
215
                /** @var GeneratedValue $generated */
216 3
                $generated = (new AnnotationReader())
217 3
                    ->getPropertyAnnotation($property, GeneratedValue::class);
218 3
                foreach ($this->relations as $type) {
219
                    /** @var ManyToMany|OneToOne|ManyToOne $annotation */
220 3
                    $annotation = (new AnnotationReader())
221 3
                        ->getPropertyAnnotation($property, $type);
222 3
                    if ($annotation) {
223 3
                        $target = $annotation->targetEntity;
224 3
                        $this->params[$key] = $this->idHandler->getId($target);
225 3
                        continue 2;
226
                    }
227
                }
228
                /** @var Column $column */
229 3
                $column = (new AnnotationReader())
230 3
                    ->getPropertyAnnotation($property, Column::class);
231 3
                $this->params[$key] = $this->valueProvider->getValue($column->type, !empty($generated));
232
            }
233
        }
234
235 3
        return $this->params;
236
    }
237
238
    /**
239
     * @return string
240
     * @throws \Doctrine\Common\Annotations\AnnotationException
241
     * @throws \ReflectionException
242
     */
243 2
    public function getIdName(): string
244
    {
245 2
        if ($this->idName === null) {
246 2
            $reflectionClassName = new ClassReflection($this->entityClassName);
247 2
            foreach ($reflectionClassName->getProperties() as $property) {
248
                /** @var Id $id */
249 2
                $id = (new AnnotationReader())
250 2
                    ->getPropertyAnnotation($property, Id::class);
251 2
                if (!empty($id)) {
252 2
                    $this->idName = $property->getName();
253 2
                    break;
254
                }
255
            }
256
        }
257
258 2
        return $this->idName;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->idName could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
259
    }
260
}
261