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