Completed
Pull Request — master (#50)
by Jonathan
05:13 queued 03:02
created

FileDriver::getGlobalBasename()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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