Failed Conditions
Push — master ( e747f7...5b15a6 )
by Guilherme
19:57
created

Mapping/Factory/AbstractClassMetadataFactory.php (3 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Mapping\Factory;
6
7
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
8
use Doctrine\ORM\Configuration\MetadataConfiguration;
9
use Doctrine\ORM\Mapping\ClassMetadata;
10
use Doctrine\ORM\Mapping\ClassMetadataBuildingContext;
11
use Doctrine\ORM\Mapping\Driver\MappingDriver;
12
use Doctrine\ORM\Mapping\Factory\Strategy\ConditionalFileWriterClassMetadataGeneratorStrategy;
13
use Doctrine\ORM\Reflection\ReflectionService;
14
use Doctrine\ORM\Utility\StaticClassNameConverter;
15
use InvalidArgumentException;
16
use function array_reverse;
17
18
/**
19
 * AbstractClassMetadataFactory is the base of ClassMetadata object creation that contain all the metadata mapping
20
 * information of a class which describes how a class should be mapped to a relational database.
21
 */
22
abstract class AbstractClassMetadataFactory implements ClassMetadataFactory
23
{
24
    /**
25
     * Never autogenerate a class metadata and rely that it was generated by some process before deployment.
26
     *
27
     * @deprecated please use @see \Doctrine\ORM\Mapping\Factory\AbstractClassMetadataFactory::AUTOGENERATE_FILE_NOT_EXISTS
28
     */
29
    public const AUTOGENERATE_NEVER = 0;
30
31
    /**
32
     * Always generates a new class metadata in every request. This is only sane during development.
33
     *
34
     * @deprecated please use @see \Doctrine\ORM\Mapping\Factory\AbstractClassMetadataFactory::AUTOGENERATE_FILE_NOT_EXISTS
35
     */
36
    public const AUTOGENERATE_ALWAYS = 1;
37
38
    /**
39
     * Autogenerate the class metadata when the file does not exist.
40
     * This strategy causes a file exists call whenever any metadata is used the first time in a request.
41
     */
42
    public const AUTOGENERATE_FILE_NOT_EXISTS = 2;
43
44
    /** @var ClassMetadataDefinitionFactory */
45
    protected $definitionFactory;
46
47
    /** @var MappingDriver */
48
    protected $mappingDriver;
49
50
    /** @var ClassMetadataDefinition[] */
51
    private $definitions = [];
52
53
    /** @var ClassMetadata[] */
54
    private $loaded = [];
55
56
    public function __construct(MetadataConfiguration $configuration)
57
    {
58
        $mappingDriver = $configuration->getMappingDriver();
59
        $resolver      = $configuration->getResolver();
60
        //$autoGenerate      = $configuration->getAutoGenerate();
61
        $generator         = new ClassMetadataGenerator($mappingDriver);
62
        $generatorStrategy = new ConditionalFileWriterClassMetadataGeneratorStrategy($generator);
63
        $definitionFactory = new ClassMetadataDefinitionFactory($resolver, $generatorStrategy);
64
65
        $this->mappingDriver     = $mappingDriver;
66
        $this->definitionFactory = $definitionFactory;
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     *
72
     * @throws InvalidArgumentException
73
     */
74
    public function getAllMetadata() : array
75
    {
76
        $metadata = [];
77
78
        foreach ($this->mappingDriver->getAllClassNames() as $className) {
79
            $metadata[] = $this->getMetadataFor($className);
80
        }
81
82
        return $metadata;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function getMetadataFor($className)
89
    {
90
        $entityClassName = StaticClassNameConverter::getRealClass($className);
91
92
        if (isset($this->loaded[$entityClassName])) {
93
            return $this->loaded[$entityClassName];
94
        }
95
96
        $metadataBuildingContext = new ClassMetadataBuildingContext($this);
0 ignored issues
show
The call to Doctrine\ORM\Mapping\Cla...gContext::__construct() has too few arguments starting with reflectionService. ( Ignorable by Annotation )

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

96
        $metadataBuildingContext = /** @scrutinizer ignore-call */ new ClassMetadataBuildingContext($this);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
$this of type Doctrine\ORM\Mapping\Fac...actClassMetadataFactory is incompatible with the type Doctrine\ORM\Mapping\AbstractClassMetadataFactory expected by parameter $classMetadataFactory of Doctrine\ORM\Mapping\Cla...gContext::__construct(). ( Ignorable by Annotation )

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

96
        $metadataBuildingContext = new ClassMetadataBuildingContext(/** @scrutinizer ignore-type */ $this);
Loading history...
97
        $parentClassNameList     = $this->getParentClassNameList($entityClassName);
98
        $parentClassNameList[]   = $entityClassName;
99
        $parent                  = null;
100
101
        foreach ($parentClassNameList as $parentClassName) {
102
            if (isset($this->loaded[$parentClassName])) {
103
                $parent = $this->loaded[$parentClassName];
104
105
                continue;
106
            }
107
108
            $definition = $this->getOrCreateClassMetadataDefinition($parentClassName, $parent);
0 ignored issues
show
The call to Doctrine\ORM\Mapping\Fac...assMetadataDefinition() has too few arguments starting with metadataBuildingContext. ( Ignorable by Annotation )

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

108
            /** @scrutinizer ignore-call */ 
109
            $definition = $this->getOrCreateClassMetadataDefinition($parentClassName, $parent);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
109
110
            $parent = $this->loaded[$parentClassName] = $this->createClassMetadata($definition);
111
        }
112
113
        $metadataBuildingContext->validate();
114
115
        return $this->loaded[$entityClassName];
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function hasMetadataFor($className) : bool
122
    {
123
        return isset($this->loaded[$className]);
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function setMetadataFor($className, $class) : void
130
    {
131
        $this->loaded[$className] = $class;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function isTransient($className) : bool
138
    {
139
        $entityClassName = StaticClassNameConverter::getRealClass($className);
140
141
        return $this->mappingDriver->isTransient($entityClassName);
142
    }
143
144
    protected function createClassMetadata(ClassMetadataDefinition $definition) : ClassMetadata
145
    {
146
        /** @var ClassMetadata $classMetadata */
147
        $metadataFqcn  = $definition->metadataClassName;
148
        $classMetadata = new $metadataFqcn($definition->parentClassMetadata);
149
150
        $classMetadata->wakeupReflection($this->getReflectionService());
151
152
        return $classMetadata;
153
    }
154
155
    /**
156
     * Create a class metadata definition for the given class name.
157
     */
158
    private function getOrCreateClassMetadataDefinition(
159
        string $className,
160
        ?ClassMetadata $parent,
161
        ClassMetadataBuildingContext $metadataBuildingContext
162
    ) : ClassMetadataDefinition {
163
        if (! isset($this->definitions[$className])) {
164
            $this->definitions[$className] = $this->definitionFactory->build($className, $parent, $metadataBuildingContext);
165
        }
166
167
        return $this->definitions[$className];
168
    }
169
170
    /**
171
     * @return string[]
172
     *
173
     * @throws InvalidArgumentException
174
     */
175
    private function getParentClassNameList(string $className) : array
176
    {
177
        $reflectionService   = $this->getReflectionService();
178
        $parentClassNameList = [];
179
180
        foreach (array_reverse($reflectionService->getParentClasses($className)) as $parentClassName) {
181
            if ($this->mappingDriver->isTransient($parentClassName)) {
182
                continue;
183
            }
184
185
            $parentClassNameList[] = $parentClassName;
186
        }
187
188
        return $parentClassNameList;
189
    }
190
191
    abstract protected function getReflectionService() : ReflectionService;
192
}
193