~ballot/wordpress/openstack-objectstorage-breaking-insight

« back to all changes in this revision

Viewing changes to vendor/composer/ClassLoader.php

  • Committer: Jacek Nykis
  • Date: 2015-02-11 15:35:31 UTC
  • Revision ID: jacek.nykis@canonical.com-20150211153531-hmy6zi0ov2qfkl0b
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
/*
 
4
 * This file is part of Composer.
 
5
 *
 
6
 * (c) Nils Adermann <naderman@naderman.de>
 
7
 *     Jordi Boggiano <j.boggiano@seld.be>
 
8
 *
 
9
 * For the full copyright and license information, please view the LICENSE
 
10
 * file that was distributed with this source code.
 
11
 */
 
12
 
 
13
namespace Composer\Autoload;
 
14
 
 
15
/**
 
16
 * ClassLoader implements a PSR-0 class loader
 
17
 *
 
18
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
 
19
 *
 
20
 *     $loader = new \Composer\Autoload\ClassLoader();
 
21
 *
 
22
 *     // register classes with namespaces
 
23
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 
24
 *     $loader->add('Symfony',           __DIR__.'/framework');
 
25
 *
 
26
 *     // activate the autoloader
 
27
 *     $loader->register();
 
28
 *
 
29
 *     // to enable searching the include path (eg. for PEAR packages)
 
30
 *     $loader->setUseIncludePath(true);
 
31
 *
 
32
 * In this example, if you try to use a class in the Symfony\Component
 
33
 * namespace or one of its children (Symfony\Component\Console for instance),
 
34
 * the autoloader will first look for the class under the component/
 
35
 * directory, and it will then fallback to the framework/ directory if not
 
36
 * found before giving up.
 
37
 *
 
38
 * This class is loosely based on the Symfony UniversalClassLoader.
 
39
 *
 
40
 * @author Fabien Potencier <fabien@symfony.com>
 
41
 * @author Jordi Boggiano <j.boggiano@seld.be>
 
42
 */
 
43
class ClassLoader
 
44
{
 
45
    // PSR-4
 
46
    private $prefixLengthsPsr4 = array();
 
47
    private $prefixDirsPsr4 = array();
 
48
    private $fallbackDirsPsr4 = array();
 
49
 
 
50
    // PSR-0
 
51
    private $prefixesPsr0 = array();
 
52
    private $fallbackDirsPsr0 = array();
 
53
 
 
54
    private $useIncludePath = false;
 
55
    private $classMap = array();
 
56
 
 
57
    private $classMapAuthoritative = false;
 
58
 
 
59
    public function getPrefixes()
 
60
    {
 
61
        if (!empty($this->prefixesPsr0)) {
 
62
            return call_user_func_array('array_merge', $this->prefixesPsr0);
 
63
        }
 
64
 
 
65
        return array();
 
66
    }
 
67
 
 
68
    public function getPrefixesPsr4()
 
69
    {
 
70
        return $this->prefixDirsPsr4;
 
71
    }
 
72
 
 
73
    public function getFallbackDirs()
 
74
    {
 
75
        return $this->fallbackDirsPsr0;
 
76
    }
 
77
 
 
78
    public function getFallbackDirsPsr4()
 
79
    {
 
80
        return $this->fallbackDirsPsr4;
 
81
    }
 
82
 
 
83
    public function getClassMap()
 
84
    {
 
85
        return $this->classMap;
 
86
    }
 
87
 
 
88
    /**
 
89
     * @param array $classMap Class to filename map
 
90
     */
 
91
    public function addClassMap(array $classMap)
 
92
    {
 
93
        if ($this->classMap) {
 
94
            $this->classMap = array_merge($this->classMap, $classMap);
 
95
        } else {
 
96
            $this->classMap = $classMap;
 
97
        }
 
98
    }
 
99
 
 
100
    /**
 
101
     * Registers a set of PSR-0 directories for a given prefix, either
 
102
     * appending or prepending to the ones previously set for this prefix.
 
103
     *
 
104
     * @param string       $prefix  The prefix
 
105
     * @param array|string $paths   The PSR-0 root directories
 
106
     * @param bool         $prepend Whether to prepend the directories
 
107
     */
 
108
    public function add($prefix, $paths, $prepend = false)
 
109
    {
 
110
        if (!$prefix) {
 
111
            if ($prepend) {
 
112
                $this->fallbackDirsPsr0 = array_merge(
 
113
                    (array) $paths,
 
114
                    $this->fallbackDirsPsr0
 
115
                );
 
116
            } else {
 
117
                $this->fallbackDirsPsr0 = array_merge(
 
118
                    $this->fallbackDirsPsr0,
 
119
                    (array) $paths
 
120
                );
 
121
            }
 
122
 
 
123
            return;
 
124
        }
 
125
 
 
126
        $first = $prefix[0];
 
127
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
 
128
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
 
129
 
 
130
            return;
 
131
        }
 
132
        if ($prepend) {
 
133
            $this->prefixesPsr0[$first][$prefix] = array_merge(
 
134
                (array) $paths,
 
135
                $this->prefixesPsr0[$first][$prefix]
 
136
            );
 
137
        } else {
 
138
            $this->prefixesPsr0[$first][$prefix] = array_merge(
 
139
                $this->prefixesPsr0[$first][$prefix],
 
140
                (array) $paths
 
141
            );
 
142
        }
 
143
    }
 
144
 
 
145
    /**
 
146
     * Registers a set of PSR-4 directories for a given namespace, either
 
147
     * appending or prepending to the ones previously set for this namespace.
 
148
     *
 
149
     * @param string       $prefix  The prefix/namespace, with trailing '\\'
 
150
     * @param array|string $paths   The PSR-0 base directories
 
151
     * @param bool         $prepend Whether to prepend the directories
 
152
     *
 
153
     * @throws \InvalidArgumentException
 
154
     */
 
155
    public function addPsr4($prefix, $paths, $prepend = false)
 
156
    {
 
157
        if (!$prefix) {
 
158
            // Register directories for the root namespace.
 
159
            if ($prepend) {
 
160
                $this->fallbackDirsPsr4 = array_merge(
 
161
                    (array) $paths,
 
162
                    $this->fallbackDirsPsr4
 
163
                );
 
164
            } else {
 
165
                $this->fallbackDirsPsr4 = array_merge(
 
166
                    $this->fallbackDirsPsr4,
 
167
                    (array) $paths
 
168
                );
 
169
            }
 
170
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
 
171
            // Register directories for a new namespace.
 
172
            $length = strlen($prefix);
 
173
            if ('\\' !== $prefix[$length - 1]) {
 
174
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
 
175
            }
 
176
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
 
177
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
 
178
        } elseif ($prepend) {
 
179
            // Prepend directories for an already registered namespace.
 
180
            $this->prefixDirsPsr4[$prefix] = array_merge(
 
181
                (array) $paths,
 
182
                $this->prefixDirsPsr4[$prefix]
 
183
            );
 
184
        } else {
 
185
            // Append directories for an already registered namespace.
 
186
            $this->prefixDirsPsr4[$prefix] = array_merge(
 
187
                $this->prefixDirsPsr4[$prefix],
 
188
                (array) $paths
 
189
            );
 
190
        }
 
191
    }
 
192
 
 
193
    /**
 
194
     * Registers a set of PSR-0 directories for a given prefix,
 
195
     * replacing any others previously set for this prefix.
 
196
     *
 
197
     * @param string       $prefix The prefix
 
198
     * @param array|string $paths  The PSR-0 base directories
 
199
     */
 
200
    public function set($prefix, $paths)
 
201
    {
 
202
        if (!$prefix) {
 
203
            $this->fallbackDirsPsr0 = (array) $paths;
 
204
        } else {
 
205
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
 
206
        }
 
207
    }
 
208
 
 
209
    /**
 
210
     * Registers a set of PSR-4 directories for a given namespace,
 
211
     * replacing any others previously set for this namespace.
 
212
     *
 
213
     * @param string       $prefix The prefix/namespace, with trailing '\\'
 
214
     * @param array|string $paths  The PSR-4 base directories
 
215
     *
 
216
     * @throws \InvalidArgumentException
 
217
     */
 
218
    public function setPsr4($prefix, $paths)
 
219
    {
 
220
        if (!$prefix) {
 
221
            $this->fallbackDirsPsr4 = (array) $paths;
 
222
        } else {
 
223
            $length = strlen($prefix);
 
224
            if ('\\' !== $prefix[$length - 1]) {
 
225
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
 
226
            }
 
227
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
 
228
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
 
229
        }
 
230
    }
 
231
 
 
232
    /**
 
233
     * Turns on searching the include path for class files.
 
234
     *
 
235
     * @param bool $useIncludePath
 
236
     */
 
237
    public function setUseIncludePath($useIncludePath)
 
238
    {
 
239
        $this->useIncludePath = $useIncludePath;
 
240
    }
 
241
 
 
242
    /**
 
243
     * Can be used to check if the autoloader uses the include path to check
 
244
     * for classes.
 
245
     *
 
246
     * @return bool
 
247
     */
 
248
    public function getUseIncludePath()
 
249
    {
 
250
        return $this->useIncludePath;
 
251
    }
 
252
 
 
253
    /**
 
254
     * Turns off searching the prefix and fallback directories for classes
 
255
     * that have not been registered with the class map.
 
256
     *
 
257
     * @param bool $classMapAuthoritative
 
258
     */
 
259
    public function setClassMapAuthoritative($classMapAuthoritative)
 
260
    {
 
261
        $this->classMapAuthoritative = $classMapAuthoritative;
 
262
    }
 
263
 
 
264
    /**
 
265
     * Should class lookup fail if not found in the current class map?
 
266
     *
 
267
     * @return bool
 
268
     */
 
269
    public function isClassMapAuthoritative()
 
270
    {
 
271
        return $this->classMapAuthoritative;
 
272
    }
 
273
 
 
274
    /**
 
275
     * Registers this instance as an autoloader.
 
276
     *
 
277
     * @param bool $prepend Whether to prepend the autoloader or not
 
278
     */
 
279
    public function register($prepend = false)
 
280
    {
 
281
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
 
282
    }
 
283
 
 
284
    /**
 
285
     * Unregisters this instance as an autoloader.
 
286
     */
 
287
    public function unregister()
 
288
    {
 
289
        spl_autoload_unregister(array($this, 'loadClass'));
 
290
    }
 
291
 
 
292
    /**
 
293
     * Loads the given class or interface.
 
294
     *
 
295
     * @param  string    $class The name of the class
 
296
     * @return bool|null True if loaded, null otherwise
 
297
     */
 
298
    public function loadClass($class)
 
299
    {
 
300
        if ($file = $this->findFile($class)) {
 
301
            includeFile($file);
 
302
 
 
303
            return true;
 
304
        }
 
305
    }
 
306
 
 
307
    /**
 
308
     * Finds the path to the file where the class is defined.
 
309
     *
 
310
     * @param string $class The name of the class
 
311
     *
 
312
     * @return string|false The path if found, false otherwise
 
313
     */
 
314
    public function findFile($class)
 
315
    {
 
316
        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
 
317
        if ('\\' == $class[0]) {
 
318
            $class = substr($class, 1);
 
319
        }
 
320
 
 
321
        // class map lookup
 
322
        if (isset($this->classMap[$class])) {
 
323
            return $this->classMap[$class];
 
324
        }
 
325
        if ($this->classMapAuthoritative) {
 
326
            return false;
 
327
        }
 
328
 
 
329
        $file = $this->findFileWithExtension($class, '.php');
 
330
 
 
331
        // Search for Hack files if we are running on HHVM
 
332
        if ($file === null && defined('HHVM_VERSION')) {
 
333
            $file = $this->findFileWithExtension($class, '.hh');
 
334
        }
 
335
 
 
336
        if ($file === null) {
 
337
            // Remember that this class does not exist.
 
338
            return $this->classMap[$class] = false;
 
339
        }
 
340
 
 
341
        return $file;
 
342
    }
 
343
 
 
344
    private function findFileWithExtension($class, $ext)
 
345
    {
 
346
        // PSR-4 lookup
 
347
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
 
348
 
 
349
        $first = $class[0];
 
350
        if (isset($this->prefixLengthsPsr4[$first])) {
 
351
            foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
 
352
                if (0 === strpos($class, $prefix)) {
 
353
                    foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
 
354
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
 
355
                            return $file;
 
356
                        }
 
357
                    }
 
358
                }
 
359
            }
 
360
        }
 
361
 
 
362
        // PSR-4 fallback dirs
 
363
        foreach ($this->fallbackDirsPsr4 as $dir) {
 
364
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
 
365
                return $file;
 
366
            }
 
367
        }
 
368
 
 
369
        // PSR-0 lookup
 
370
        if (false !== $pos = strrpos($class, '\\')) {
 
371
            // namespaced class name
 
372
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
 
373
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
 
374
        } else {
 
375
            // PEAR-like class name
 
376
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
 
377
        }
 
378
 
 
379
        if (isset($this->prefixesPsr0[$first])) {
 
380
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
 
381
                if (0 === strpos($class, $prefix)) {
 
382
                    foreach ($dirs as $dir) {
 
383
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
 
384
                            return $file;
 
385
                        }
 
386
                    }
 
387
                }
 
388
            }
 
389
        }
 
390
 
 
391
        // PSR-0 fallback dirs
 
392
        foreach ($this->fallbackDirsPsr0 as $dir) {
 
393
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
 
394
                return $file;
 
395
            }
 
396
        }
 
397
 
 
398
        // PSR-0 include paths.
 
399
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
 
400
            return $file;
 
401
        }
 
402
    }
 
403
}
 
404
 
 
405
/**
 
406
 * Scope isolated include.
 
407
 *
 
408
 * Prevents access to $this/self from included files.
 
409
 */
 
410
function includeFile($file)
 
411
{
 
412
    include $file;
 
413
}