GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#154)
by joseph
26:39
created

setDtoGetterAndSetterForEntityProperty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 34
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 2.0381

Importance

Changes 0
Metric Value
cc 2
eloc 26
nc 2
nop 3
dl 0
loc 34
ccs 26
cts 33
cp 0.7879
crap 2.0381
rs 9.504
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Creation\Process\Src\Entity\DataTransferObjects;
4
5
use Doctrine\Common\Collections\Collection;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Creation\Process\ProcessInterface;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Filesystem\File;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\ReflectionHelper;
11
use EdmondsCommerce\DoctrineStaticMeta\DoctrineStaticMeta;
12
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Interfaces\PrimaryKey\IdFieldInterface;
13
14
class CreateDtoBodyProcess implements ProcessInterface
15
{
16
    /**
17
     * @var DoctrineStaticMeta
18
     */
19
    private $dsm;
20
    /**
21
     * @var ReflectionHelper
22
     */
23
    private $reflectionHelper;
24
25
    /**
26
     * @var array
27
     */
28
    private $properties = [];
29
30
    /**
31
     * @var array
32
     */
33
    private $setters = [];
34
35
    /**
36
     * @var array
37
     */
38
    private $getters = [];
39
    /**
40
     * @var CodeHelper
41
     */
42
    private $codeHelper;
43
    /**
44
     * @var string
45
     */
46
    private $entityFqn;
47
    /**
48
     * @var NamespaceHelper
49
     */
50
    private $namespaceHelper;
51
52 1
    public function __construct(
53
        ReflectionHelper $reflectionHelper,
54
        CodeHelper $codeHelper,
55
        NamespaceHelper $namespaceHelper
56
    ) {
57 1
        $this->reflectionHelper = $reflectionHelper;
58 1
        $this->codeHelper       = $codeHelper;
59 1
        $this->namespaceHelper  = $namespaceHelper;
60 1
    }
61
62 1
    public function setEntityFqn(string $entityFqn)
63
    {
64 1
        $this->entityFqn = $entityFqn;
65 1
        if (false === \ts\stringContains($entityFqn, '\\Entities\\')) {
66
            throw new \RuntimeException(
67
                'This does not look like an Entity FQN: ' . $entityFqn
68
            );
69
        }
70 1
        $this->dsm = new DoctrineStaticMeta($entityFqn);
71
72 1
        return $this;
73
    }
74
75 1
    public function run(File\FindReplace $findReplace): void
76
    {
77 1
        $this->buildArraysOfCode();
78 1
        $this->updateFileContents($findReplace);
79 1
    }
80
81 1
    private function buildArraysOfCode()
82
    {
83 1
        foreach ($this->dsm->getSetters() as $getterName => $setterName) {
84 1
            if ('getId' === $getterName) {
85 1
                continue;
86
            }
87 1
            $trait    = $this->reflectionHelper->getTraitImplementingMethod(
88 1
                $this->dsm->getReflectionClass(),
89 1
                $setterName
90
            );
91 1
            $setter   = $trait->getMethod($setterName);
92 1
            $property = $trait->getProperties(\ReflectionProperty::IS_PRIVATE)[0]->getName();
93 1
            $type     = $this->getPropertyTypeFromSetter($setter);
94 1
            $this->setProperty($property, $type);
95 1
            $this->setGetterFromPropertyAndType($getterName, $property, $type);
96 1
            $this->setSetterFromPropertyAndType($setterName, $property, $type);
97 1
            $this->addIssetMethodsForProperty($property, $type);
98
        }
99 1
    }
100
101 1
    private function getPropertyTypeFromSetter(\ReflectionMethod $setter): string
102
    {
103
        /**
104
         * @var \ReflectionParameter $param
105
         */
106 1
        $param = current($setter->getParameters());
107 1
        $type  = $param->getType();
108 1
        if (null !== $type) {
109 1
            $type = $type->getName();
110 1
            if (!\in_array($type, ['string', 'bool', 'int', 'float'], true)) {
111 1
                $type = "\\$type";
112
            }
113 1
            if ($param->allowsNull()) {
114 1
                $type = "?$type";
115
            }
116
        }
117
118 1
        return (string)$type;
119
    }
120
121 1
    private function setProperty(string $property, string $type): void
122
    {
123 1
        $defaultValue = $this->getDefaultValueCodeForProperty($property);
124 1
        $type         = $this->getPropertyVarType($type);
125 1
        $type         = $this->makeIdTypesNullable($property, $type);
126
127 1
        $code = '';
128 1
        $code .= "\n" . '    /**';
129 1
        $code .= ('' !== $type) ? "\n" . '     * @var ' . $type : '';
130 1
        $code .= "\n" . '     */';
131 1
        $code .= "\n" . '    private $' . $property . ' = ' . $defaultValue . ';';
132
133 1
        $this->properties[] = $code;
134 1
    }
135
136 1
    private function getDefaultValueCodeForProperty(
137
        string $property
138
    ) {
139 1
        $defaultValueConst = 'DEFAULT_' . $this->codeHelper->consty($property);
140 1
        $fullValueString   = $this->entityFqn . '::' . $defaultValueConst;
141 1
        if (\defined($fullValueString)) {
142 1
            return $this->dsm->getShortName() . '::' . $defaultValueConst;
143
        }
144
145 1
        return 'null';
146
    }
147
148 1
    private function getPropertyVarType(string $type): string
149
    {
150 1
        if (false === \ts\stringContains($type, '\\Entity\\Interfaces\\')) {
151 1
            return $type;
152
        }
153 1
        $types = [];
154 1
        if (0 === strpos($type, '?')) {
155
            $types[] = 'null';
156
            $type    = substr($type, 1);
157
        }
158 1
        $types[] = $type;
159 1
        $types[] = $this->namespaceHelper->getEntityDtoFqnFromEntityFqn(
160 1
            $this->namespaceHelper->getEntityFqnFromEntityInterfaceFqn($type)
161
        );
162
163 1
        return implode('|', $types);
164
    }
165
166 1
    private function makeIdTypesNullable(string $property, string $type): string
167
    {
168 1
        if (IdFieldInterface::PROP_ID === $property && 0 !== strpos($type, '?')) {
169
            $type = "?$type";
170
        }
171
172 1
        return $type;
173
    }
174
175
    /**
176
     * @SuppressWarnings(PHPMD.ElseExpression)
177
     * @param string $getterName
178
     * @param string $property
179
     * @param string $type
180
     */
181 1
    private function setGetterFromPropertyAndType(
182
        string $getterName,
183
        string $property,
184
        string $type
185
    ) {
186 1
        $type            = $this->makeIdTypesNullable($property, $type);
187 1
        $code            = '';
188 1
        $code            .= "\n    public function $getterName()" . (('' !== $type) ? ": $type" : '');
189 1
        $code            .= "\n    {";
190 1
        $code            .= $this->getGetterBody($property, $type);
191 1
        $code            .= "\n    }\n";
192 1
        $this->getters[] = $code;
193 1
    }
194
195 1
    private function getGetterBody(
196
        string $property,
197
        string $type
198
    ) {
199 1
        if ('\\' . Collection::class === $type) {
200 1
            return "\n        return \$this->$property ?? \$this->$property = new ArrayCollection();";
201
        }
202 1
        if (\ts\stringContains($type, '\\Entity\\Interfaces\\')) {
203 1
            $getterCode = '';
204 1
            $getterCode .= "\n        if(null === \$this->$property){";
205 1
            $getterCode .= "\n            return \$this->$property;";
206 1
            $getterCode .= "\n        }";
207 1
            if (0 === strpos($type, '?')) {
208
                $type = substr($type, 1);
209
            }
210 1
            $getterCode .= "\n        if(\$this->$property instanceof $type){";
211 1
            $getterCode .= "\n            return \$this->$property;";
212 1
            $getterCode .= "\n        }";
213 1
            $getterCode .= "\n        throw new \RuntimeException(";
214 1
            $getterCode .= "\n            '\$this->$property is not an Entity, but is '. \get_class(\$this->$property)";
215 1
            $getterCode .= "\n        );";
216
217 1
            return $getterCode;
218
        }
219
220 1
        return "\n        return \$this->$property;";
221
    }
222
223 1
    private function setSetterFromPropertyAndType(
224
        string $setterName,
225
        string $property,
226
        string $type
227
    ) {
228 1
        $code            = '';
229 1
        $code            .= "\n    public function $setterName($type \$$property): self ";
230 1
        $code            .= "\n    {";
231 1
        $code            .= "\n        \$this->$property = \$$property;";
232 1
        $code            .= "\n        return \$this;";
233 1
        $code            .= "\n    }\n";
234 1
        $this->setters[] = $code;
235 1
        if (\ts\stringContains($type, '\\Entity\\Interfaces\\')) {
236 1
            $this->setDtoGetterAndSetterForEntityProperty($setterName, $property, $type);
237
        }
238 1
    }
239
240 1
    private function setDtoGetterAndSetterForEntityProperty(
241
        string $setterName,
242
        string $property,
243
        string $entityInterfaceFqn
244
    ) {
245 1
        $dtoFqn          = $this->namespaceHelper->getEntityDtoFqnFromEntityFqn(
246 1
            $this->namespaceHelper->getEntityFqnFromEntityInterfaceFqn($entityInterfaceFqn)
247
        );
248 1
        $setterCode      = '';
249 1
        $setterCode      .= "\n    public function ${setterName}Dto($dtoFqn \$$property): self ";
250 1
        $setterCode      .= "\n    {";
251 1
        $setterCode      .= "\n        \$this->$property = \$$property;";
252 1
        $setterCode      .= "\n        return \$this;";
253 1
        $setterCode      .= "\n    }\n";
254 1
        $this->setters[] = $setterCode;
255
256 1
        $getterName = 'get' . substr($setterName, 3);
257 1
        $getterCode = '';
258 1
        $getterCode .= "\n    public function $getterName" . "Dto(): $dtoFqn";
259 1
        $getterCode .= "\n    {";
260 1
        $getterCode .= "\n        if(null === \$this->$property){";
261 1
        $getterCode .= "\n            return \$this->$property;";
262 1
        $getterCode .= "\n        }";
263 1
        if (0 === strpos($dtoFqn, '?')) {
264
            $dtoFqn = substr($dtoFqn, 1);
265
        }
266 1
        $getterCode      .= "\n        if(\$this->$property instanceof $dtoFqn){";
267 1
        $getterCode      .= "\n            return \$this->$property;";
268 1
        $getterCode      .= "\n        }";
269 1
        $getterCode      .= "\n        throw new \RuntimeException(";
270 1
        $getterCode      .= "\n            '\$this->$property is not a DTO, but is '. \get_class(\$this->$property)";
271 1
        $getterCode      .= "\n        );";
272 1
        $getterCode      .= "\n    }\n";
273 1
        $this->getters[] = $getterCode;
274 1
    }
275
276 1
    private function addIssetMethodsForProperty(string $property, string $type): void
277
    {
278 1
        if (false === \ts\stringContains($type, '\\Entity\\Interfaces\\')) {
279 1
            return;
280
        }
281 1
        $methodName      = 'isset' . ucfirst($property) . 'AsDto';
282 1
        $getterCodeDto   = '';
283 1
        $getterCodeDto   .= "\n    public function $methodName(): bool";
284 1
        $getterCodeDto   .= "\n    {";
285 1
        $getterCodeDto   .= "\n        return \$this->$property instanceof DataTransferObjectInterface;";
286 1
        $getterCodeDto   .= "\n    }\n";
287 1
        $this->getters[] = $getterCodeDto;
288
289 1
        $methodName       = 'isset' . ucfirst($property) . 'AsEntity';
290 1
        $getterCodeEntity = '';
291 1
        $getterCodeEntity .= "\n    public function $methodName(): bool";
292 1
        $getterCodeEntity .= "\n    {";
293 1
        $getterCodeEntity .= "\n        return \$this->$property instanceof EntityInterface;";
294 1
        $getterCodeEntity .= "\n    }\n";
295 1
        $this->getters[]  = $getterCodeEntity;
296 1
    }
297
298 1
    private function updateFileContents(
299
        File\FindReplace $findReplace
300
    ) {
301 1
        sort($this->properties, SORT_STRING);
302 1
        sort($this->getters, SORT_STRING);
303 1
        sort($this->setters, SORT_STRING);
304
305 1
        $body = implode("\n", $this->properties) .
306 1
                "\n\n" .
307 1
                implode("\n", $this->getters) .
308 1
                "\n" .
309 1
                implode("\n", $this->setters);
310
311 1
        $findReplace->findReplaceRegex('%{(.+)}%s', "{\n\$1\n$body\n}");
312 1
    }
313
}
314