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 (#99)
by joseph
29:16 queued 26:52
created

UsesPHPMetaDataTrait::getPlural()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4.125

Importance

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