FileDriver::getGlobalBasename()   A
last analyzed

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