Failed Conditions
Push — master ( 047620...906c14 )
by Guilherme
08:56
created

ClassMetadataFactory::validateRuntimeMetadata()   B

Complexity

Conditions 11
Paths 7

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 11.353

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 13
c 1
b 0
f 0
nc 7
nop 2
dl 0
loc 25
ccs 12
cts 14
cp 0.8571
crap 11.353
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Mapping;
6
7
use Doctrine\Common\Cache\Cache;
8
use Doctrine\Common\EventManager;
9
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory as PersistenceClassMetadataFactory;
10
use Doctrine\Common\Persistence\Mapping\MappingException as PersistenceMappingException;
11
use Doctrine\Common\Persistence\Mapping\MappingException as CommonMappingException;
0 ignored issues
show
introduced by
Type Doctrine\Common\Persistence\Mapping\MappingException (as CommonMappingException) is not used in this file.
Loading history...
12
use Doctrine\DBAL\Platforms;
13
use Doctrine\DBAL\Platforms\AbstractPlatform;
14
use Doctrine\ORM\EntityManagerInterface;
15
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
16
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs;
17
use Doctrine\ORM\Events;
18
use Doctrine\ORM\Exception\ORMException;
19
use Doctrine\ORM\Mapping\Exception\TableGeneratorNotImplementedYet;
20
use Doctrine\ORM\Mapping\Exception\UnknownGeneratorType;
21
use Doctrine\ORM\Reflection\ReflectionService;
22
use Doctrine\ORM\Reflection\RuntimeReflectionService;
23
use Doctrine\ORM\Sequencing\Planning\CompositeValueGenerationPlan;
24
use Doctrine\ORM\Sequencing\Planning\NoopValueGenerationPlan;
25
use Doctrine\ORM\Sequencing\Planning\SingleValueGenerationPlan;
26
use Doctrine\ORM\Sequencing\Planning\ValueGenerationExecutor;
27
use Doctrine\ORM\Utility\StaticClassNameConverter;
28
use InvalidArgumentException;
29
use ReflectionException;
30
use function array_map;
31
use function array_reverse;
32
use function count;
33
use function in_array;
34
use function reset;
35
use function sprintf;
36
37
/**
38
 * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
39
 * metadata mapping information of a class which describes how a class should be mapped
40
 * to a relational database.
41
 */
42
class ClassMetadataFactory implements PersistenceClassMetadataFactory
43
{
44
    /**
45
     * Salt used by specific Object Manager implementation.
46
     *
47
     * @var string
48
     */
49
    protected $cacheSalt = '$CLASSMETADATA';
50
51
    /** @var bool */
52
    protected $initialized = false;
53
54
    /** @var ReflectionService|null */
55
    protected $reflectionService;
56
57
    /** @var EntityManagerInterface|null */
58
    private $em;
59
60
    /** @var AbstractPlatform */
61
    private $targetPlatform;
62
63
    /** @var Driver\MappingDriver */
64
    private $driver;
65
66
    /** @var EventManager */
67
    private $evm;
68
69
    /** @var Cache|null */
70
    private $cacheDriver;
71
72
    /** @var ClassMetadata[] */
73
    private $loadedMetadata = [];
74
75
    /**
76
     * Sets the entity manager used to build ClassMetadata instances.
77
     */
78 2277
    public function setEntityManager(EntityManagerInterface $em)
79
    {
80 2277
        $this->em = $em;
81 2277
    }
82
83
    /**
84
     * Sets the cache driver used by the factory to cache ClassMetadata instances.
85
     */
86 2275
    public function setCacheDriver(?Cache $cacheDriver = null) : void
87
    {
88 2275
        $this->cacheDriver = $cacheDriver;
89 2275
    }
90
91
    /**
92
     * Gets the cache driver used by the factory to cache ClassMetadata instances.
93
     */
94
    public function getCacheDriver() : ?Cache
95
    {
96
        return $this->cacheDriver;
97
    }
98
99
    /**
100
     * Returns an array of all the loaded metadata currently in memory.
101
     *
102
     * @return ClassMetadata[]
103
     */
104
    public function getLoadedMetadata() : array
105
    {
106
        return $this->loadedMetadata;
107
    }
108
109
    /**
110
     * Sets the reflectionService.
111
     */
112
    public function setReflectionService(ReflectionService $reflectionService) : void
113
    {
114
        $this->reflectionService = $reflectionService;
115
    }
116
117
    /**
118
     * Gets the reflection service associated with this metadata factory.
119
     */
120 1965
    public function getReflectionService() : ReflectionService
121
    {
122 1965
        if ($this->reflectionService === null) {
123 1965
            $this->reflectionService = new RuntimeReflectionService();
124
        }
125
126 1965
        return $this->reflectionService;
127
    }
128
129
    /**
130
     * {@inheritDoc}
131
     */
132 48
    public function isTransient($className) : bool
133
    {
134 48
        if (! $this->initialized) {
135 15
            $this->initialize();
136
        }
137
138 48
        $entityClassName = StaticClassNameConverter::getRealClass($className);
139
140 48
        return $this->getDriver()->isTransient($entityClassName);
141
    }
142
143
    /**
144
     * Checks whether the factory has the metadata for a class loaded already.
145
     *
146
     * @param string $className
147
     *
148
     * @return bool TRUE if the metadata of the class in question is already loaded, FALSE otherwise.
149
     */
150 66
    public function hasMetadataFor($className) : bool
151
    {
152 66
        return isset($this->loadedMetadata[$className]);
153
    }
154
155
    /**
156
     * Sets the metadata descriptor for a specific class.
157
     *
158
     * NOTE: This is only useful in very special cases, like when generating proxy classes.
159
     *
160
     * @param string        $className
161
     * @param ClassMetadata $class
162
     */
163 5
    public function setMetadataFor($className, $class) : void
164
    {
165 5
        $this->loadedMetadata[$className] = $class;
166 5
    }
167
168
    /**
169
     * Forces the factory to load the metadata of all classes known to the underlying
170
     * mapping driver.
171
     *
172
     * @return ClassMetadata[] The ClassMetadata instances of all mapped classes.
173
     *
174
     * @throws InvalidArgumentException
175
     * @throws ReflectionException
176
     * @throws MappingException
177
     * @throws PersistenceMappingException
178
     * @throws ORMException
179
     */
180 56
    public function getAllMetadata() : array
181
    {
182 56
        if (! $this->initialized) {
183 56
            $this->initialize();
184
        }
185
186 56
        $driver   = $this->getDriver();
187 56
        $metadata = [];
188
189 56
        foreach ($driver->getAllClassNames() as $className) {
190 55
            $metadata[] = $this->getMetadataFor($className);
191
        }
192
193 56
        return $metadata;
0 ignored issues
show
introduced by
The expression return $metadata returns an array which contains values of type Doctrine\ORM\Mapping\ClassMetadata which are incompatible with the return type Doctrine\Common\Persistence\Mapping\ClassMetadata mandated by Doctrine\Common\Persiste...ctory::getAllMetadata().
Loading history...
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     *
199
     * @throws ORMException
200
     */
201 453
    protected function initialize() : void
202
    {
203 453
        $this->driver      = $this->em->getConfiguration()->getMetadataDriverImpl();
0 ignored issues
show
Bug introduced by
The method getConfiguration() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

203
        $this->driver      = $this->em->/** @scrutinizer ignore-call */ getConfiguration()->getMetadataDriverImpl();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
204 453
        $this->evm         = $this->em->getEventManager();
205 453
        $this->initialized = true;
206 453
    }
207
208
    /**
209
     * {@inheritdoc}
210
     */
211 198
    protected function getDriver() : Driver\MappingDriver
212
    {
213 198
        return $this->driver;
214
    }
215
216
    /**
217
     * {@inheritdoc}
218
     */
219
    protected function isEntity(ClassMetadata $class) : bool
220
    {
221
        return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false;
222
    }
223
224
    /**
225
     * Gets the class metadata descriptor for a class.
226
     *
227
     * @param string $className The name of the class.
228
     *
229
     * @throws InvalidArgumentException
230
     * @throws PersistenceMappingException
231
     * @throws ORMException
232
     */
233 1970
    public function getMetadataFor($className) : ClassMetadata
234
    {
235 1970
        if (isset($this->loadedMetadata[$className])) {
236 1646
            return $this->loadedMetadata[$className];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->loadedMetadata[$className] returns the type Doctrine\ORM\Mapping\ClassMetadata which is incompatible with the return type mandated by Doctrine\Common\Persiste...ctory::getMetadataFor() of Doctrine\Common\Persistence\Mapping\ClassMetadata.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
237
        }
238
239 1965
        $entityClassName = StaticClassNameConverter::getRealClass($className);
240
241 1965
        if (isset($this->loadedMetadata[$entityClassName])) {
242
            // We do not have the alias name in the map, include it
243 214
            return $this->loadedMetadata[$className] = $this->loadedMetadata[$entityClassName];
244
        }
245
246 1965
        $metadataBuildingContext = $this->newClassMetadataBuildingContext();
247 1965
        $loadingException        = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $loadingException is dead and can be removed.
Loading history...
248
249
        try {
250 1965
            if ($this->cacheDriver) {
251 1859
                $cached = $this->cacheDriver->fetch($entityClassName . $this->cacheSalt);
252
253 1859
                if ($cached instanceof ClassMetadata) {
254 1632
                    $this->loadedMetadata[$entityClassName] = $cached;
255
256 1632
                    $cached->wakeupReflection($metadataBuildingContext->getReflectionService());
257
                } else {
258 1859
                    foreach ($this->loadMetadata($entityClassName, $metadataBuildingContext) as $loadedClass) {
259 267
                        $loadedClassName = $loadedClass->getClassName();
260
261 267
                        $this->cacheDriver->save($loadedClassName . $this->cacheSalt, $loadedClass, null);
262
                    }
263
                }
264
            } else {
265 1957
                $this->loadMetadata($entityClassName, $metadataBuildingContext);
266
            }
267 26
        } catch (PersistenceMappingException $loadingException) {
268 12
            $fallbackMetadataResponse = $this->onNotFoundMetadata($entityClassName, $metadataBuildingContext);
269
270 12
            if (! $fallbackMetadataResponse) {
271 10
                throw $loadingException;
272
            }
273
274 2
            $this->loadedMetadata[$entityClassName] = $fallbackMetadataResponse;
275
        }
276
277 1947
        if ($className !== $entityClassName) {
278
            // We do not have the alias name in the map, include it
279 3
            $this->loadedMetadata[$className] = $this->loadedMetadata[$entityClassName];
280
        }
281
282 1947
        $metadataBuildingContext->validate();
283
284 1947
        return $this->loadedMetadata[$entityClassName];
285
    }
286
287
    /**
288
     * Loads the metadata of the class in question and all it's ancestors whose metadata
289
     * is still not loaded.
290
     *
291
     * Important: The class $name does not necessarily exist at this point here.
292
     * Scenarios in a code-generation setup might have access to XML
293
     * Mapping files without the actual PHP code existing here. That is why the
294
     * {@see Doctrine\ORM\Reflection\ReflectionService} interface
295
     * should be used for reflection.
296
     *
297
     * @param string $name The name of the class for which the metadata should get loaded.
298
     *
299
     * @return ClassMetadata[]
300
     *
301
     * @throws InvalidArgumentException
302
     * @throws ORMException
303
     */
304 387
    protected function loadMetadata(string $name, ClassMetadataBuildingContext $metadataBuildingContext) : array
305
    {
306 387
        if (! $this->initialized) {
307 382
            $this->initialize();
308
        }
309
310 387
        $loaded          = [];
311 387
        $parentClasses   = $this->getParentClasses($name);
312 376
        $parentClasses[] = $name;
313
314
        // Move down the hierarchy of parent classes, starting from the topmost class
315 376
        $parent = null;
316
317 376
        foreach ($parentClasses as $className) {
318 376
            if (isset($this->loadedMetadata[$className])) {
319 71
                $parent = $this->loadedMetadata[$className];
320
321 71
                continue;
322
            }
323
324 376
            $class = $this->doLoadMetadata($className, $parent, $metadataBuildingContext);
325
326 365
            $this->loadedMetadata[$className] = $class;
327
328 365
            $parent   = $class;
329 365
            $loaded[] = $class;
330
        }
331
332 363
        array_map([$this, 'resolveDiscriminatorValue'], $loaded);
333
334 363
        return $loaded;
335
    }
336
337
    /**
338
     * Gets an array of parent classes for the given entity class.
339
     *
340
     * @param string $name
341
     *
342
     * @return string[]
343
     *
344
     * @throws InvalidArgumentException
345
     */
346 387
    protected function getParentClasses($name) : array
347
    {
348
        // Collect parent classes, ignoring transient (not-mapped) classes.
349 387
        $parentClasses = [];
350
351 387
        foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) {
352 104
            if (! $this->getDriver()->isTransient($parentClass)) {
353 99
                $parentClasses[] = $parentClass;
354
            }
355
        }
356
357 376
        return $parentClasses;
358
    }
359
360
    /**
361
     * {@inheritdoc}
362
     */
363 12
    protected function onNotFoundMetadata(
364
        string $className,
365
        ClassMetadataBuildingContext $metadataBuildingContext
366
    ) : ?ClassMetadata {
367 12
        if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) {
368 10
            return null;
369
        }
370
371 2
        $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $metadataBuildingContext, $this->em);
0 ignored issues
show
Bug introduced by
It seems like $this->em can also be of type null; however, parameter $entityManager of Doctrine\ORM\Event\OnCla...ventArgs::__construct() does only seem to accept Doctrine\ORM\EntityManagerInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

371
        $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $metadataBuildingContext, /** @scrutinizer ignore-type */ $this->em);
Loading history...
372
373 2
        $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs);
374
375 2
        return $eventArgs->getFoundMetadata();
376
    }
377
378
    /**
379
     * {@inheritdoc}
380
     *
381
     * @throws MappingException
382
     * @throws ORMException
383
     */
384 375
    protected function doLoadMetadata(
385
        string $className,
386
        ?ClassMetadata $parent,
387
        ClassMetadataBuildingContext $metadataBuildingContext
388
    ) : ?ComponentMetadata {
389
        /** @var ClassMetadata $classMetadata */
390 375
        $classMetadata = $this->driver->loadMetadataForClass($className, $parent, $metadataBuildingContext);
391
392 369
        $this->completeIdentifierGeneratorMappings($classMetadata);
393
394 369
        if ($this->evm->hasListeners(Events::loadClassMetadata)) {
395 6
            $eventArgs = new LoadClassMetadataEventArgs($classMetadata, $this->em);
0 ignored issues
show
Bug introduced by
It seems like $this->em can also be of type null; however, parameter $entityManager of Doctrine\ORM\Event\LoadC...ventArgs::__construct() does only seem to accept Doctrine\ORM\EntityManagerInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

395
            $eventArgs = new LoadClassMetadataEventArgs($classMetadata, /** @scrutinizer ignore-type */ $this->em);
Loading history...
396
397 6
            $this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
398
        }
399
400 369
        $this->buildValueGenerationPlan($classMetadata);
401 369
        $this->validateRuntimeMetadata($classMetadata, $parent);
402
403 364
        return $classMetadata;
404
    }
405
406
    /**
407
     * Validate runtime metadata is correctly defined.
408
     *
409
     * @throws MappingException
410
     */
411 369
    protected function validateRuntimeMetadata(ClassMetadata $class, ?ClassMetadata $parent = null) : void
412
    {
413 369
        if (! $class->getReflectionClass()) {
414
            // only validate if there is a reflection class instance
415
            return;
416
        }
417
418 369
        $class->validateIdentifier();
419 367
        $class->validateAssociations();
420 367
        $class->validateLifecycleCallbacks($this->getReflectionService());
421
422
        // verify inheritance
423 367
        if (! $class->isMappedSuperclass && $class->inheritanceType !== InheritanceType::NONE) {
424 76
            if (! $parent) {
425 75
                if (! $class->discriminatorMap) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class->discriminatorMap of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
426 3
                    throw MappingException::missingDiscriminatorMap($class->getClassName());
427
                }
428
429 72
                if (! $class->discriminatorColumn) {
430 73
                    throw MappingException::missingDiscriminatorColumn($class->getClassName());
431
                }
432
            }
433 329
        } elseif (($class->discriminatorMap || $class->discriminatorColumn) && $class->isMappedSuperclass && $class->isRootEntity()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class->discriminatorMap of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
434
            // second condition is necessary for mapped superclasses in the middle of an inheritance hierarchy
435
            throw MappingException::noInheritanceOnMappedSuperClass($class->getClassName());
436
        }
437 364
    }
438
439
    /**
440
     * {@inheritdoc}
441
     */
442 1965
    protected function newClassMetadataBuildingContext() : ClassMetadataBuildingContext
443
    {
444 1965
        return new ClassMetadataBuildingContext(
445 1965
            $this,
446 1965
            $this->getReflectionService(),
447 1965
            $this->em->getConfiguration()->getNamingStrategy()
448
        );
449
    }
450
451
    /**
452
     * Populates the discriminator value of the given metadata (if not set) by iterating over discriminator
453
     * map classes and looking for a fitting one.
454
     *
455
     * @throws InvalidArgumentException
456
     * @throws ReflectionException
457
     * @throws MappingException
458
     * @throws PersistenceMappingException
459
     */
460 363
    private function resolveDiscriminatorValue(ClassMetadata $metadata) : void
461
    {
462 363
        if ($metadata->discriminatorValue || ! $metadata->discriminatorMap || $metadata->isMappedSuperclass ||
0 ignored issues
show
Bug Best Practice introduced by
The expression $metadata->discriminatorMap of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
463 363
            ! $metadata->getReflectionClass() || $metadata->getReflectionClass()->isAbstract()) {
464 363
            return;
465
        }
466
467
        // minor optimization: avoid loading related metadata when not needed
468 4
        foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) {
469 4
            if ($discriminatorClass === $metadata->getClassName()) {
470 3
                $metadata->discriminatorValue = $discriminatorValue;
471
472 3
                return;
473
            }
474
        }
475
476
        // iterate over discriminator mappings and resolve actual referenced classes according to existing metadata
477 1
        foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) {
478 1
            if ($metadata->getClassName() === $this->getMetadataFor($discriminatorClass)->getClassName()) {
479
                $metadata->discriminatorValue = $discriminatorValue;
480
481
                return;
482
            }
483
        }
484
485 1
        throw MappingException::mappedClassNotPartOfDiscriminatorMap($metadata->getClassName(), $metadata->getRootClassName());
486
    }
487
488
    /**
489
     * Completes the ID generator mapping. If "auto" is specified we choose the generator
490
     * most appropriate for the targeted database platform.
491
     *
492
     * @throws ORMException
493
     */
494 369
    private function completeIdentifierGeneratorMappings(ClassMetadata $class) : void
495
    {
496 369
        foreach ($class->getDeclaredPropertiesIterator() as $property) {
497 367
            if (! $property instanceof FieldMetadata /*&& ! $property instanceof AssociationMetadata*/) {
498 251
                continue;
499
            }
500
501 365
            $this->completeFieldIdentifierGeneratorMapping($property);
502
        }
503 369
    }
504
505 365
    private function completeFieldIdentifierGeneratorMapping(FieldMetadata $field)
506
    {
507 365
        if (! $field->hasValueGenerator()) {
508 280
            return;
509
        }
510
511 292
        $platform  = $this->getTargetPlatform();
512 292
        $class     = $field->getDeclaringClass();
0 ignored issues
show
Unused Code introduced by
The assignment to $class is dead and can be removed.
Loading history...
513 292
        $generator = $field->getValueGenerator();
514
515 292
        if (in_array($generator->getType(), [GeneratorType::AUTO, GeneratorType::IDENTITY], true)) {
516 285
            $generatorType = $platform->prefersSequences() || $platform->usesSequenceEmulatedIdentityColumns()
517
                ? GeneratorType::SEQUENCE
518 285
                : ($platform->prefersIdentityColumns() ? GeneratorType::IDENTITY : GeneratorType::TABLE);
519
520 285
            $generator = new ValueGeneratorMetadata($generatorType, $field->getValueGenerator()->getDefinition());
521
522 285
            $field->setValueGenerator($generator);
523
        }
524
525
        // Validate generator definition and set defaults where needed
526 292
        switch ($generator->getType()) {
527 292
            case GeneratorType::SEQUENCE:
528
                // If there is no sequence definition yet, create a default definition
529 6
                if ($generator->getDefinition()) {
530 6
                    break;
531
                }
532
533
                // @todo guilhermeblanco Move sequence generation to DBAL
534
                $sequencePrefix = $platform->getSequencePrefix($field->getTableName(), $field->getSchemaName());
0 ignored issues
show
Bug introduced by
The method getSchemaName() does not exist on Doctrine\ORM\Mapping\FieldMetadata. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

534
                $sequencePrefix = $platform->getSequencePrefix($field->getTableName(), $field->/** @scrutinizer ignore-call */ getSchemaName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
535
                $idSequenceName = sprintf('%s_%s_seq', $sequencePrefix, $field->getColumnName());
536
                $sequenceName   = $platform->fixSchemaElementName($idSequenceName);
537
538
                $field->setValueGenerator(
539
                    new ValueGeneratorMetadata(
540
                        $generator->getType(),
541
                        [
542
                            'sequenceName'   => $sequenceName,
543
                            'allocationSize' => 1,
544
                        ]
545
                    )
546
                );
547
548
                break;
549
550 286
            case GeneratorType::TABLE:
551
                throw TableGeneratorNotImplementedYet::create();
552
                break;
553
554 286
            case GeneratorType::CUSTOM:
555 285
            case GeneratorType::IDENTITY:
556
            case GeneratorType::NONE:
557 286
                break;
558
559
            default:
560
                throw UnknownGeneratorType::create($generator->getType());
561
        }
562 292
    }
563
564 367
    private function getTargetPlatform() : Platforms\AbstractPlatform
565
    {
566 367
        if (! $this->targetPlatform) {
567 367
            $this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
568
        }
569
570 367
        return $this->targetPlatform;
571
    }
572
573 369
    private function buildValueGenerationPlan(ClassMetadata $class) : void
574
    {
575 369
        $valueGenerationExecutorList = $this->buildValueGenerationExecutorList($class);
576
577 369
        switch (count($valueGenerationExecutorList)) {
578 369
            case 0:
579 92
                $valueGenerationPlan = new NoopValueGenerationPlan();
580 92
                break;
581
582 308
            case 1:
583 303
                $valueGenerationPlan = new SingleValueGenerationPlan($class, reset($valueGenerationExecutorList));
584 303
                break;
585
586
            default:
587 18
                $valueGenerationPlan = new CompositeValueGenerationPlan($class, $valueGenerationExecutorList);
588 18
                break;
589
        }
590
591 369
        $class->setValueGenerationPlan($valueGenerationPlan);
592 369
    }
593
594
    /**
595
     * @return ValueGenerationExecutor[]
596
     */
597 369
    private function buildValueGenerationExecutorList(ClassMetadata $class) : array
598
    {
599 369
        $executors = [];
600
601 369
        foreach ($class->getDeclaredPropertiesIterator() as $property) {
602 367
            $executor = $property->getValueGenerationExecutor($this->getTargetPlatform());
603
604 367
            if ($executor instanceof ValueGenerationExecutor) {
605 308
                $executors[$property->getName()] = $executor;
606
            }
607
        }
608
609 369
        return $executors;
610
    }
611
}
612