Failed Conditions
Pull Request — 1.3.x (#71)
by Grégoire
02:19
created

SymfonyFileLocator   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Test Coverage

Coverage 86.96%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 27
eloc 62
c 1
b 0
f 0
dl 0
loc 202
ccs 60
cts 69
cp 0.8696
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setFileExtension() 0 3 1
B getAllClassNames() 0 40 8
A addNamespacePrefixes() 0 4 1
A fileExists() 0 26 6
A getNamespacePrefixes() 0 3 1
A getFileExtension() 0 3 1
A findMappingFile() 0 25 6
A __construct() 0 10 2
A getPaths() 0 3 1
1
<?php
2
3
namespace Doctrine\Persistence\Mapping\Driver;
4
5
use Doctrine\Persistence\Mapping\MappingException;
6
use InvalidArgumentException;
7
use RecursiveDirectoryIterator;
8
use RecursiveIteratorIterator;
9
use const DIRECTORY_SEPARATOR;
10
use function array_keys;
11
use function array_merge;
12
use function class_exists;
13
use function is_dir;
14
use function is_file;
15
use function realpath;
16
use function str_replace;
17
use function strlen;
18
use function strpos;
19
use function strrpos;
20
use function strtr;
21
use function substr;
22
23
/**
24
 * The Symfony File Locator makes a simplifying assumptions compared
25
 * to the DefaultFileLocator. By assuming paths only contain entities of a certain
26
 * namespace the mapping files consists of the short classname only.
27
 */
28
class SymfonyFileLocator implements FileLocator
29
{
30
    /**
31
     * The paths where to look for mapping files.
32
     *
33
     * @var string[]
34
     */
35
    protected $paths = [];
36
37
    /**
38
     * A map of mapping directory path to namespace prefix used to expand class shortnames.
39
     *
40
     * @var string[]
41
     */
42
    protected $prefixes = [];
43
44
    /**
45
     * File extension that is searched for.
46
     *
47
     * @var string|null
48
     */
49
    protected $fileExtension;
50
51
    /**
52
     * Represents PHP namespace delimiters when looking for files
53
     *
54
     * @var string
55
     */
56
    private $nsSeparator;
57
58
    /**
59
     * @param string[]    $prefixes
60
     * @param string|null $fileExtension
61
     * @param string      $nsSeparator   String which would be used when converting FQCN to filename and vice versa. Should not be empty
62
     */
63 14
    public function __construct(array $prefixes, $fileExtension = null, $nsSeparator = '.')
64
    {
65 14
        $this->addNamespacePrefixes($prefixes);
66 14
        $this->fileExtension = $fileExtension;
67
68 14
        if (empty($nsSeparator)) {
69 1
            throw new InvalidArgumentException('Namespace separator should not be empty');
70
        }
71
72 13
        $this->nsSeparator = (string) $nsSeparator;
73 13
    }
74
75
    /**
76
     * Adds Namespace Prefixes.
77
     *
78
     * @param string[] $prefixes
79
     *
80
     * @return void
81
     */
82 14
    public function addNamespacePrefixes(array $prefixes)
83
    {
84 14
        $this->prefixes = array_merge($this->prefixes, $prefixes);
85 14
        $this->paths    = array_merge($this->paths, array_keys($prefixes));
86 14
    }
87
88
    /**
89
     * Gets Namespace Prefixes.
90
     *
91
     * @return string[]
92
     */
93 1
    public function getNamespacePrefixes()
94
    {
95 1
        return $this->prefixes;
96
    }
97
98
    /**
99
     * {@inheritDoc}
100
     */
101 1
    public function getPaths()
102
    {
103 1
        return $this->paths;
104
    }
105
106
    /**
107
     * {@inheritDoc}
108
     */
109 1
    public function getFileExtension()
110
    {
111 1
        return $this->fileExtension;
112
    }
113
114
    /**
115
     * Sets the file extension used to look for mapping files under.
116
     *
117
     * @param string $fileExtension The file extension to set.
118
     *
119
     * @return void
120
     */
121 1
    public function setFileExtension($fileExtension)
122
    {
123 1
        $this->fileExtension = $fileExtension;
124 1
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129 1
    public function fileExists($className)
130
    {
131 1
        $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension;
132 1
        foreach ($this->paths as $path) {
133 1
            if (! isset($this->prefixes[$path])) {
134
                // global namespace class
135
                if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) {
136
                    return true;
137
                }
138
139
                continue;
140
            }
141
142 1
            $prefix = $this->prefixes[$path];
143
144 1
            if (strpos($className, $prefix . '\\') !== 0) {
145
                continue;
146
            }
147
148 1
            $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension;
149 1
            if (is_file($filename)) {
150 1
                return true;
151
            }
152
        }
153
154 1
        return false;
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160 3
    public function getAllClassNames($globalBasename = null)
161
    {
162 3
        $classes = [];
163
164 3
        if ($this->paths) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->paths 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...
165 3
            foreach ((array) $this->paths as $path) {
166 3
                if (! is_dir($path)) {
167
                    throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
168
                }
169
170 3
                $iterator = new RecursiveIteratorIterator(
171 3
                    new RecursiveDirectoryIterator($path),
172 3
                    RecursiveIteratorIterator::LEAVES_ONLY
173
                );
174
175 3
                foreach ($iterator as $file) {
176 3
                    $fileName = $file->getBasename($this->fileExtension);
177
178 3
                    if ($fileName === $file->getBasename() || $fileName === $globalBasename) {
179 3
                        continue;
180
                    }
181
182
                    // NOTE: All files found here means classes are not transient!
183 3
                    if (isset($this->prefixes[$path])) {
184
                        // Calculate namespace suffix for given prefix as a relative path from basepath to file path
185 3
                        $nsSuffix = strtr(
186 3
                            substr(realpath($file->getPath()), strlen(realpath($path))),
187 3
                            $this->nsSeparator,
188 3
                            '\\'
189
                        );
190
191 3
                        $classes[] = $this->prefixes[$path] . str_replace(DIRECTORY_SEPARATOR, '\\', $nsSuffix) . '\\' . str_replace($this->nsSeparator, '\\', $fileName);
192
                    } else {
193 3
                        $classes[] = str_replace($this->nsSeparator, '\\', $fileName);
194
                    }
195
                }
196
            }
197
        }
198
199 3
        return $classes;
200
    }
201
202
    /**
203
     * {@inheritDoc}
204
     */
205 6
    public function findMappingFile($className)
206
    {
207 6
        $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension;
208 6
        foreach ($this->paths as $path) {
209 6
            if (! isset($this->prefixes[$path])) {
210
                if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) {
211
                    return $path . DIRECTORY_SEPARATOR . $defaultFileName;
212
                }
213
214
                continue;
215
            }
216
217 6
            $prefix = $this->prefixes[$path];
218
219 6
            if (strpos($className, $prefix . '\\') !== 0) {
220
                continue;
221
            }
222
223 6
            $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension;
224 6
            if (is_file($filename)) {
225 6
                return $filename;
226
            }
227
        }
228
229 1
        throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1) . $this->fileExtension);
230
    }
231
}
232
233
class_exists(\Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator::class);
234