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.
Passed
Pull Request — master (#92)
by Ross
14:47
created

UsesPHPMetaDataTrait::getReflectionClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Traits;
4
5
use Doctrine\Common\Util\Debug;
6
use Doctrine\Common\Util\Inflector;
7
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Doctrine\ORM\Mapping\ClassMetadata as DoctrineClassMetaData;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
11
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\UsesPHPMetaDataInterface;
12
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
13
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
14
15
trait UsesPHPMetaDataTrait
16
{
17
18
    /**
19
     * @var \ts\Reflection\ReflectionClass
20
     */
21
    private static $reflectionClass;
22
23
    /**
24
     * @var ClassMetadata
25
     */
26
    private static $metaData;
27
28
    /**
29
     * @var string
30
     */
31
    private static $singular;
32
33
    /**
34
     * @var string
35
     */
36
    private static $plural;
37
38
    /**
39
     * @var array
40
     */
41
    private static $setters;
42
43
    /**
44
     * @var array
45
     */
46
    private static $getters;
47
48
    /**
49
     * Loads the class and property meta data in the class
50
     *
51
     * This is the method called by Doctrine to load the meta data
52
     *
53
     * @param DoctrineClassMetaData $metadata
54
     *
55
     * @throws DoctrineStaticMetaException
56
     * @SuppressWarnings(PHPMD.StaticAccess)
57
     */
58 58
    public static function loadMetadata(DoctrineClassMetaData $metadata): void
59
    {
60
        try {
61 58
            static::$metaData        = $metadata;
0 ignored issues
show
Bug introduced by
Since $metaData is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $metaData to at least protected.
Loading history...
62 58
            $builder                 = new ClassMetadataBuilder($metadata);
63 58
            static::$reflectionClass = $metadata->getReflectionClass();
0 ignored issues
show
Documentation Bug introduced by
It seems like $metadata->getReflectionClass() of type ReflectionClass is incompatible with the declared type ts\Reflection\ReflectionClass of property $reflectionClass.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Bug introduced by
Since $reflectionClass is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $reflectionClass to at least protected.
Loading history...
64 58
            static::loadPropertyDoctrineMetaData($builder);
65 58
            static::loadClassDoctrineMetaData($builder);
66 58
            static::setChangeTrackingPolicy($builder);
67
        } catch (\Exception $e) {
68
            throw new DoctrineStaticMetaException(
69
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
70
                $e->getCode(),
71
                $e
72
            );
73
        }
74 58
    }
75
76
    /**
77
     * This method will reflect on the entity class and pull out all the methods that begin with
78
     * UsesPHPMetaDataInterface::METHOD_PREFIX_GET_PROPERTY_DOCTRINE_META
79
     *
80
     * Once it has an array of methods, it calls them all, passing in the $builder
81
     *
82
     * @param ClassMetadataBuilder $builder
83
     *
84
     * @throws DoctrineStaticMetaException
85
     * @SuppressWarnings(PHPMD.StaticAccess)
86
     */
87 58
    protected static function loadPropertyDoctrineMetaData(ClassMetadataBuilder $builder): void
88
    {
89 58
        $methodName = '__no_method__';
90
        try {
91 58
            $staticMethods = static::getStaticMethods();
92
            //now loop through and call them
93 58
            foreach ($staticMethods as $method) {
94 58
                $methodName = $method->getName();
95 58
                if (0 === stripos(
96 58
                    $methodName,
97 58
                    UsesPHPMetaDataInterface::METHOD_PREFIX_GET_PROPERTY_DOCTRINE_META
98
                )
99
                ) {
100 58
                    static::$methodName($builder);
101
                }
102
            }
103
        } catch (\Exception $e) {
104
            $reflectionClass = static::getReflectionClass();
105
            throw new DoctrineStaticMetaException(
106
                'Exception in ' . __METHOD__ . 'for '
107
                . $reflectionClass->getName() . "::$methodName\n\n"
108
                . $e->getMessage()
109
            );
110
        }
111 58
    }
112
113
    /**
114
     * Get an array of all static methods implemented by the current class
115
     *
116
     * Merges trait methods
117
     * Filters out this trait
118
     *
119
     * @return array|\ReflectionMethod[]
120
     * @throws \ReflectionException
121
     */
122 75
    protected static function getStaticMethods(): array
123
    {
124 75
        $reflectionClass = static::getReflectionClass();
125 75
        $staticMethods = $reflectionClass->getMethods(
126 75
            \ReflectionMethod::IS_STATIC
127
        );
128
        // get static methods from traits
129 75
        $traits = $reflectionClass->getTraits();
130 75
        foreach ($traits as $trait) {
131 75
            if ($trait->getShortName() === 'UsesPHPMetaData') {
132
                continue;
133
            }
134 75
            $traitStaticMethods = $trait->getMethods(
135 75
                \ReflectionMethod::IS_STATIC
136
            );
137 75
            array_merge(
138 75
                $staticMethods,
139 75
                $traitStaticMethods
140
            );
141
        }
142
143 75
        return $staticMethods;
144
    }
145
146
    /**
147
     * Get class level meta data, eg table name, custom repository
148
     *
149
     * @param ClassMetadataBuilder $builder
150
     *
151
     * @SuppressWarnings(PHPMD.StaticAccess)
152
     */
153 58
    protected static function loadClassDoctrineMetaData(ClassMetadataBuilder $builder): void
154
    {
155 58
        $tableName = MappingHelper::getTableNameForEntityFqn(static::class);
156 58
        $builder->setTable($tableName);
157 58
        static::setCustomRepositoryClass($builder);
158 58
    }
159
160
    /**
161
     * Setting the change policy to be Notify - best performance
162
     *
163
     * @see http://doctrine-orm.readthedocs.io/en/latest/reference/change-tracking-policies.html
164
     *
165
     * @param ClassMetadataBuilder $builder
166
     */
167 58
    public static function setChangeTrackingPolicy(ClassMetadataBuilder $builder): void
168
    {
169 58
        $builder->setChangeTrackingPolicyNotify();
170 58
    }
171
172
    /**
173
     * Get the property name the Entity is mapped by when plural
174
     *
175
     * Override it in your entity class if you are using an Entity class name that doesn't pluralize nicely
176
     *
177
     * @return string
178
     * @throws DoctrineStaticMetaException
179
     * @SuppressWarnings(PHPMD.StaticAccess)
180
     */
181 9
    public static function getPlural(): string
182
    {
183
        try {
184 9
            if (null === static::$plural) {
0 ignored issues
show
introduced by
The condition static::plural is always false. If static::plural can have other possible types, add them to src/Entity/Traits/UsesPHPMetaDataTrait.php:34
Loading history...
Bug introduced by
Since $plural is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $plural to at least protected.
Loading history...
185 9
                $singular       = static::getSingular();
186 9
                static::$plural = Inflector::pluralize($singular);
187
            }
188
189 9
            return static::$plural;
190
        } catch (\Exception $e) {
191
            throw new DoctrineStaticMetaException(
192
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
193
                $e->getCode(),
194
                $e
195
            );
196
        }
197
    }
198
199
    /**
200
     * Get the property the name the Entity is mapped by when singular
201
     *
202
     * @return string
203
     * @throws DoctrineStaticMetaException
204
     * @SuppressWarnings(PHPMD.StaticAccess)
205
     */
206 10
    public static function getSingular(): string
207
    {
208
        try {
209 10
            if (null === static::$singular) {
0 ignored issues
show
Bug introduced by
Since $singular is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $singular to at least protected.
Loading history...
introduced by
The condition static::singular is always false. If static::singular can have other possible types, add them to src/Entity/Traits/UsesPHPMetaDataTrait.php:29
Loading history...
210 9
                $reflectionClass = static::getReflectionClass();
211
212 9
                $shortName         = $reflectionClass->getShortName();
213 9
                $singularShortName = Inflector::singularize($shortName);
214
215 9
                $namespaceName   = $reflectionClass->getNamespaceName();
216 9
                $namespaceParts  = \explode(AbstractGenerator::ENTITIES_FOLDER_NAME, $namespaceName);
217 9
                $entityNamespace = \array_pop($namespaceParts);
218
219 9
                $namespacedShortName = \preg_replace(
220 9
                    '/\\\\/',
221 9
                    '',
222 9
                    $entityNamespace . $singularShortName
223
                );
224
225 9
                static::$singular = \lcfirst($namespacedShortName);
226
            }
227
228 10
            return static::$singular;
229
        } catch (\Exception $e) {
230
            throw new DoctrineStaticMetaException(
231
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
232
                $e->getCode(),
233
                $e
234
            );
235
        }
236
    }
237
238
    /**
239
     * Which field is being used for ID - will normally be `id` as implemented by
240
     * \EdmondsCommerce\DoctrineStaticMeta\Fields\Traits\IdField
241
     *
242
     * @return string
243
     * @SuppressWarnings(PHPMD.StaticAccess)
244
     */
245 2
    public static function getIdField(): string
246
    {
247 2
        return 'id';
248
    }
249
250
    /**
251
     * In the class itself, we need to specify the repository class name
252
     *
253
     * @param ClassMetadataBuilder $builder
254
     *
255
     * @return mixed
256
     */
257
    abstract protected static function setCustomRepositoryClass(ClassMetadataBuilder $builder);
258
259
    /**
260
     * Get an array of setters by name
261
     *
262
     * @return array|string[]
263
     */
264 2
    public function getSetters(): array
265
    {
266 2
        if (null !== static::$setters) {
0 ignored issues
show
Bug introduced by
Since $setters is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $setters to at least protected.
Loading history...
introduced by
The condition static::setters is always true. If static::setters can have other possible types, add them to src/Entity/Traits/UsesPHPMetaDataTrait.php:39
Loading history...
267 1
            return static::$setters;
268
        }
269
        $skip            = [
270 2
            'setChangeTrackingPolicy' => true,
271
        ];
272 2
        static::$setters = [];
273 2
        $reflectionClass = static::getReflectionClass();
274 2
        foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
275 2
            $methodName = $method->getName();
276 2
            if (isset($skip[$methodName])) {
277 2
                continue;
278
            }
279 2
            if (\ts\stringStartsWith($methodName, 'set')) {
280 2
                static::$setters[] = $methodName;
281 2
                continue;
282
            }
283 2
            if (\ts\stringStartsWith($methodName, 'add')) {
284 1
                static::$setters[] = $methodName;
285 2
                continue;
286
            }
287
        }
288
289 2
        return static::$setters;
290
    }
291
292
    /**
293
     * Get the short name (without fully qualified namespace) of the current Entity
294
     *
295
     * @return string
296
     */
297 2
    public function getShortName(): string
298
    {
299 2
        $reflectionClass = static::getReflectionClass();
300 2
        return $reflectionClass->getShortName();
301
    }
302
303
    /**
304
     * @return string
305
     * @SuppressWarnings(PHPMD.StaticAccess)
306
     * @SuppressWarnings(PHPMD.ElseExpression)
307
     */
308 4
    public function __toString(): string
309
    {
310 4
        $dump          = [];
311 4
        $metaData = static::$metaData;
0 ignored issues
show
Bug introduced by
Since $metaData is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $metaData to at least protected.
Loading history...
312 4
        if ($metaData === null) {
313 1
            return 'Could not get metadata for ' . get_class($this);
314
        }
315 3
        $fieldMappings = static::$metaData->fieldMappings;
316 3
        foreach ($this->getGetters() as $getter) {
317 3
            $got       = $this->$getter();
318 3
            $fieldName = \lcfirst(\substr($getter, 3));
319 3
            if (isset($fieldMappings[$fieldName])
320 3
                && 'decimal' === $fieldMappings[$fieldName]['type']
321
            ) {
322 1
                $value = (float) $got;
323 3
            } elseif ($got instanceof \Doctrine\ORM\Proxy\Proxy) {
324
                $value = 'Proxy class ';
325 3
            } elseif (\is_object($got) && method_exists($got, '__toString')) {
326
                $value = $got->__toString();
327
            } else {
328 3
                $value = Debug::export($got, 2);
329
            }
330 3
            $dump[$getter] = $value;
331
        }
332
333 3
        return (string)print_r($dump, true);
334
    }
335
336
    /**
337
     * Get an array of getters by name
338
     * [];
339
     *
340
     * @return array|string[]
341
     */
342 4
    public function getGetters(): array
343
    {
344 4
        if (null !== static::$getters) {
0 ignored issues
show
Bug introduced by
Since $getters is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $getters to at least protected.
Loading history...
introduced by
The condition static::getters is always true. If static::getters can have other possible types, add them to src/Entity/Traits/UsesPHPMetaDataTrait.php:44
Loading history...
345 3
            return static::$getters;
346
        }
347
        $skip = [
348 4
            'getPlural'    => true,
349
            'getSingular'  => true,
350
            'getSetters'   => true,
351
            'getGetters'   => true,
352
            'getIdField'   => true,
353
            'getShortName' => true,
354
        ];
355
356 4
        static::$getters = [];
357 4
        $reflectionClass = static::getReflectionClass();
358 4
        foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
359 4
            $methodName = $method->getName();
360 4
            if (isset($skip[$methodName])) {
361 4
                continue;
362
            }
363 4
            if (\ts\stringStartsWith($methodName, 'get')) {
364 4
                static::$getters[] = $methodName;
365 4
                continue;
366
            }
367 4
            if (\ts\stringStartsWith($methodName, 'is')) {
368 3
                static::$getters[] = $methodName;
369 3
                continue;
370
            }
371 4
            if (\ts\stringStartsWith($methodName, 'has')) {
372
                static::$getters[] = $methodName;
373 4
                continue;
374
            }
375
        }
376
377 4
        return static::$getters;
378
    }
379
380
    /**
381
     * Find and run all init methods
382
     * - defined in relationship traits and generally to init ArrayCollection properties
383
     *
384
     * @throws \ReflectionException
385
     */
386 76
    protected function runInitMethods(): void
387
    {
388 76
        $reflectionClass = static::getReflectionClass();
389 76
        $methods = $reflectionClass->getMethods(\ReflectionMethod::IS_PRIVATE);
390 76
        foreach ($methods as $method) {
391 76
            if ($method instanceof \ReflectionMethod) {
392 76
                $method = $method->getName();
393
            }
394 76
            if (\ts\stringContains($method, UsesPHPMetaDataInterface::METHOD_PREFIX_INIT)
395 76
                && \ts\stringStartsWith($method, UsesPHPMetaDataInterface::METHOD_PREFIX_INIT)
396
            ) {
397 76
                $this->$method();
398
            }
399
        }
400 76
    }
401
402
    /**
403
     * This is used to ensure that the reflection class exists. Not there is no return type because this could be either
404
     * the native Reflection class or the type safe one
405
     *
406
     * @return \ts\Reflection\ReflectionClass
407
     * @throws \ReflectionException
408
     */
409 86
    private static function getReflectionClass()
410
    {
411 86
        if (!static::$reflectionClass instanceof \ReflectionClass) {
0 ignored issues
show
Bug introduced by
Since $reflectionClass is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $reflectionClass to at least protected.
Loading history...
introduced by
static::reflectionClass is never a sub-type of ReflectionClass. If static::reflectionClass can have other possible types, add them to src/Entity/Traits/UsesPHPMetaDataTrait.php:19.
Loading history...
412 38
            static::$reflectionClass = new \ts\Reflection\ReflectionClass(static::class);
413
        }
414
415 86
        return static::$reflectionClass;
416
    }
417
}
418