Passed
Pull Request — 1.3.x (#71)
by Grégoire
02:39
created

FileDriver   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Test Coverage

Coverage 88%

Importance

Changes 0
Metric Value
wmc 20
eloc 42
dl 0
loc 172
rs 10
c 0
b 0
f 0
ccs 44
cts 50
cp 0.88

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getAllClassNames() 0 13 3
A setGlobalBasename() 0 3 1
A initialize() 0 16 4
A setLocator() 0 3 1
A getElement() 0 18 4
A getGlobalBasename() 0 3 1
A getLocator() 0 3 1
A __construct() 0 6 2
A isTransient() 0 11 3
1
<?php
2
3
namespace Doctrine\Persistence\Mapping\Driver;
4
5
use Doctrine\Persistence\Mapping\ClassMetadata;
6
use Doctrine\Persistence\Mapping\MappingException;
7
use function array_keys;
8
use function array_merge;
9
use function array_unique;
10
use function is_file;
11
use function str_replace;
12
13
/**
14
 * Base driver for file-based metadata drivers.
15
 *
16
 * A file driver operates in a mode where it loads the mapping files of individual
17
 * classes on demand. This requires the user to adhere to the convention of 1 mapping
18
 * file per class and the file names of the mapping files must correspond to the full
19
 * class name, including namespace, with the namespace delimiters '\', replaced by dots '.'.
20
 */
21
abstract class FileDriver implements MappingDriver
22
{
23
    /** @var FileLocator */
24
    protected $locator;
25
26
    /** @var ClassMetadata[]|null */
27
    protected $classCache;
28
29
    /** @var string|null */
30
    protected $globalBasename;
31
32
    /**
33
     * Initializes a new FileDriver that looks in the given path(s) for mapping
34
     * documents and operates in the specified operating mode.
35
     *
36
     * @param string|string[]|FileLocator $locator       A FileLocator or one/multiple paths
37
     *                                                where mapping documents can be found.
38
     * @param string|null                 $fileExtension
39
     */
40 12
    public function __construct($locator, $fileExtension = null)
41
    {
42 12
        if ($locator instanceof FileLocator) {
43 9
            $this->locator = $locator;
44
        } else {
45 3
            $this->locator = new DefaultFileLocator((array) $locator, $fileExtension);
46
        }
47 12
    }
48
49
    /**
50
     * Sets the global basename.
51
     *
52
     * @param string $file
53
     *
54
     * @return void
55
     */
56 6
    public function setGlobalBasename($file)
57
    {
58 6
        $this->globalBasename = $file;
59 6
    }
60
61
    /**
62
     * Retrieves the global basename.
63
     *
64
     * @return string|null
65
     */
66 1
    public function getGlobalBasename()
67
    {
68 1
        return $this->globalBasename;
69
    }
70
71
    /**
72
     * Gets the element of schema meta data for the class from the mapping file.
73
     * This will lazily load the mapping file if it is not loaded yet.
74
     *
75
     * @param string $className
76
     *
77
     * @return ClassMetadata The element of schema meta data.
78
     *
79
     * @throws MappingException
80
     */
81 4
    public function getElement($className)
82
    {
83 4
        if ($this->classCache === null) {
84 4
            $this->initialize();
85
        }
86
87 4
        if (isset($this->classCache[$className])) {
88 2
            return $this->classCache[$className];
89
        }
90
91 3
        $result = $this->loadMappingFile($this->locator->findMappingFile($className));
92 3
        if (! isset($result[$className])) {
93
            throw MappingException::invalidMappingFile($className, str_replace('\\', '.', $className) . $this->locator->getFileExtension());
94
        }
95
96 3
        $this->classCache[$className] = $result[$className];
97
98 3
        return $result[$className];
99
    }
100
101
    /**
102
     * {@inheritDoc}
103
     */
104 3
    public function isTransient($className)
105
    {
106 3
        if ($this->classCache === null) {
107 3
            $this->initialize();
108
        }
109
110 3
        if (isset($this->classCache[$className])) {
111 1
            return false;
112
        }
113
114 3
        return ! $this->locator->fileExists($className);
115
    }
116
117
    /**
118
     * {@inheritDoc}
119
     */
120 4
    public function getAllClassNames()
121
    {
122 4
        if ($this->classCache === null) {
123 3
            $this->initialize();
124
        }
125
126 4
        if (! $this->classCache) {
127 1
            return (array) $this->locator->getAllClassNames($this->globalBasename);
128
        }
129
130 3
        return array_unique(array_merge(
131 3
            array_keys($this->classCache),
132 3
            (array) $this->locator->getAllClassNames($this->globalBasename)
133
        ));
134
    }
135
136
    /**
137
     * Loads a mapping file with the given name and returns a map
138
     * from class/entity names to their corresponding file driver elements.
139
     *
140
     * @param string $file The mapping file to load.
141
     *
142
     * @return ClassMetadata[]
143
     */
144
    abstract protected function loadMappingFile($file);
145
146
    /**
147
     * Initializes the class cache from all the global files.
148
     *
149
     * Using this feature adds a substantial performance hit to file drivers as
150
     * more metadata has to be loaded into memory than might actually be
151
     * necessary. This may not be relevant to scenarios where caching of
152
     * metadata is in place, however hits very hard in scenarios where no
153
     * caching is used.
154
     *
155
     * @return void
156
     */
157 10
    protected function initialize()
158
    {
159 10
        $this->classCache = [];
160 10
        if ($this->globalBasename === null) {
161 5
            return;
162
        }
163
164 5
        foreach ($this->locator->getPaths() as $path) {
165 5
            $file = $path . '/' . $this->globalBasename . $this->locator->getFileExtension();
166 5
            if (! is_file($file)) {
167
                continue;
168
            }
169
170 5
            $this->classCache = array_merge(
171 5
                $this->classCache,
172 5
                $this->loadMappingFile($file)
173
            );
174
        }
175 5
    }
176
177
    /**
178
     * Retrieves the locator used to discover mapping files by className.
179
     *
180
     * @return FileLocator
181
     */
182
    public function getLocator()
183
    {
184
        return $this->locator;
185
    }
186
187
    /**
188
     * Sets the locator used to discover mapping files by className.
189
     */
190
    public function setLocator(FileLocator $locator)
191
    {
192
        $this->locator = $locator;
193
    }
194
}
195