Loader   B
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 402
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 402
rs 8.295
c 0
b 0
f 0
wmc 42
lcom 1
cbo 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A includeFileAndMap() 0 12 1
A readAutoloadingMapApc() 0 4 1
A writeAutoloadingMapApc() 0 4 1
A setClassMapFile() 0 4 1
A setInclusionsClassMap() 0 4 1
B autoload() 0 57 6
A autoloadExclusions() 0 16 4
A autoloadInclusions() 0 11 2
B autoloadByApcOrFileMap() 0 18 5
B autoloadIncludePath() 0 35 3
A includeFile() 0 14 4
A writeAutoloadingMapFile() 0 13 3
A readAutoloadingMapFile() 0 18 3
A addMapping() 0 10 3
A getAutoloaderClassMap() 0 4 1
A register() 0 6 1
A unregister() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Loader often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Loader, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Koch Framework
5
 * Jens-André Koch © 2005 - onwards.
6
 *
7
 * This file is part of "Koch Framework".
8
 *
9
 * License: GNU/GPL v2 or any later version, see LICENSE file.
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 2 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace Koch\Autoload;
26
27
/**
28
 * Koch Framework - Class for Autoloading of Files by Classname.
29
 *
30
 * This Loader overwrites the Zend Engines _autoload() with our own user defined loading functions.
31
 * The main function of this class is autoload().
32
 * It's registered via spl_autoload_register($load_function).
33
 * Autoload will run, if a file is not found.
34
 * There are several loader-functions, which are called in a chain by autoload().
35
 * The procedure is (1) exclusions, (2) inclusions, (3) mapping (file or apc), (4) include path (psr-0).
36
 *
37
 * Usage:
38
 * 1) include this file
39
 * 2) spl_autoload_register('Koch\Autoload\Loader::autoload');
40
 *
41
 * PHP Manual: __autoload
42
 *
43
 * @link http://www.php.net/manual/en/language.oop5.autoload.php
44
 *
45
 * PHP Manual: spl_autoload_register
46
 * @link http://www.php.net/manual/de/function.spl-autoload-register.php
47
 */
48
class Loader
49
{
50
    /**
51
     * Generated Classmap from File or APC.
52
     *
53
     * @var array
54
     */
55
    private static $autoloaderMap = [];
56
57
    /**
58
     * A manually defined classmap you might set from outside.
59
     *
60
     * @var array
61
     */
62
    public static $inclusionsClassmap = [];
63
64
    /**
65
     * Path to mapfile.
66
     *
67
     * @var string
68
     */
69
    public static $mapfile = '';
70
71
    /**
72
     * Constructor.
73
     *
74
     * Registers the autoload() method in the SPL autoloader stack.
75
     */
76
    public function __construct()
77
    {
78
        spl_autoload_register([$this, 'autoload'], true, true);
79
    }
80
81
    /**
82
     * Autoloads a Class.
83
     *
84
     * @param string $classname The name of the class
85
     *
86
     * @return bool True on successful class loading, false otherwise.
87
     */
88
    public static function autoload($classname)
0 ignored issues
show
Coding Style introduced by
function autoload() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
89
    {
90
        // stop early, if class or interface or trait already loaded
91
        if (class_exists($classname, false) || interface_exists($classname, false)) {
92
            return false;
93
        }
94
95
        // stop early, if trait already loaded (PHP 5.4)
96
        if (function_exists('trait_exists') && trait_exists($classname, false)) {
97
            return false;
98
        }
99
100
        /*
101
         * if the classname is to exclude, then
102
         * 1) stop autoloading immediately by
103
         * returning false, to save any pointless processing
104
         */
105
        if (self::autoloadExclusions($classname)) {
106
            return false;
107
        }
108
109
        /*
110
         * try to load the file by searching the
111
         * 2) hardcoded mapping table
112
         *
113
         * Note: If classname was included, autoloadInclusions returns true.
114
         */
115
116
         return true === self::autoloadInclusions($classname);
117
118
        /*
119
         * try to load the file by searching the
120
         * 3) automatically created mapping table.
121
         *
122
         * Note: the mapping table is loaded from APC or file.
123
         */
124
125
        return true === self::autoloadByApcOrFileMap($classname);
0 ignored issues
show
Unused Code introduced by
/* * try to load the fi...cOrFileMap($classname); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
126
127
        /*
128
         * Try to load the file via include path lookup.
129
         * 5) psr-0 loader
130
         *
131
         * Note: If the file is found, it's added to the mapping file.
132
         * The next time the file is requested, it will be loaded
133
         * via the method above (3)!
134
         */
135
136
        return true === self::autoloadIncludePath($classname);
0 ignored issues
show
Unused Code introduced by
/* * Try to load the fi...ncludePath($classname); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
137
138
        /*
139
         * If classname was not found by any of the above methods, it's an
140
         * 6) Autoloading Fail
141
         */
142
143
        return false;
0 ignored issues
show
Unused Code introduced by
/* * If classname was n... Fail */ return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
144
    }
145
146
    /**
147
     * Excludes a certain classname from the autoloading.
148
     *
149
     * Some libraries have their own autoloaders, like e.g. Doctrine, Smarty.
150
     * In these cases Koch Framework has the first autoloader in the stack,
151
     * but is not responsible for loading.
152
     *
153
     * @param string $classname Classname to check for exclusion.
154
     *
155
     * @return bool true, if the class is to exclude.
156
     */
157
    public static function autoloadExclusions($classname)
0 ignored issues
show
Coding Style introduced by
function autoloadExclusions() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
158
    {
159
        // define parts of classnames for exclusion
160
        foreach (['Smarty_Internal', 'Smarty_', 'PHPUnit', 'PHP_CodeCoverage'] as $classnameToExclude) {
161
            if (false !== strpos($classname, $classnameToExclude)) {
162
                return true;
163
            }
164
        }
165
166
        // exlude Doctrine
167
        if (substr($classname, 0, 8) === 'Doctrine') {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return substr($classname, 0, 8) === 'Doctrine';.
Loading history...
168
            return true;
169
        }
170
171
        return false;
172
    }
173
174
    /**
175
     * Includes a certain classname by using a manually maintained autoloading map.
176
     *
177
     * @param string $classname Classname to check for inclusion.
178
     *
179
     * @return bool if classname was included
180
     */
181
    public static function autoloadInclusions($classname)
0 ignored issues
show
Coding Style introduced by
function autoloadInclusions() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
182
    {
183
        // check if classname is in autoloading map
184
        if (isset(self::$inclusionsClassmap[$classname])) {
185
            include self::$inclusionsClassmap[$classname];
186
187
            return true;
188
        }
189
190
        return false;
191
    }
192
193
    /**
194
     * Loads a file by classname using the autoloader mapping array from file or apc.
195
     *
196
     * @param string $classname The classname to look for in the autoloading map.
197
     *
198
     * @return bool True on file load, otherwise false.
199
     */
200
    public static function autoloadByApcOrFileMap($classname)
0 ignored issues
show
Coding Style introduced by
function autoloadByApcOrFileMap() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
201
    {
202
        if (empty(self::$autoloaderMap)) {
203
            if (defined('APC') and APC  === true) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
204
                self::$autoloaderMap = self::readAutoloadingMapApc();
205
            } else { // load the mapping from file
206
                self::$autoloaderMap = self::readAutoloadingMapFile();
0 ignored issues
show
Documentation Bug introduced by
It seems like self::readAutoloadingMapFile() can be null. However, the property $autoloaderMap is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
207
            }
208
        }
209
210
        if (isset(self::$autoloaderMap[$classname])) {
211
            include_once self::$autoloaderMap[$classname];
212
213
            return true;
214
        }
215
216
        return false;
217
    }
218
219
    /**
220
     * PSR-0 Loader.
221
     *
222
     * - hardcoded namespaceSeparator
223
     * - hardcoded extension
224
     *
225
     * @link https://groups.google.com/group/php-standards/web/psr-0-final-proposal
226
     * @link http://gist.github.com/221634
227
     *
228
     * @param string $classname
229
     *
230
     * @return bool True on success of require, false otherwise.
231
     */
232
    public static function autoloadIncludePath($classname)
0 ignored issues
show
Coding Style introduced by
function autoloadIncludePath() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
233
    {
234
        #echo "Class requested $classname <br>";
235
236
        // trim opening namespace separator
237
        $classname = ltrim($classname, '\\');
238
239
        $filename = '';
240
241
        // determine position of last namespace separator
242
        if (false !== ($lastNsPos = strripos($classname, '\\'))) {
243
            // everything before it, is the namespace
244
            $namespace = substr($classname, 0, $lastNsPos + 1);
245
            // everything after it, is the classname
246
            $classname = substr($classname, $lastNsPos + 1);
247
            // replace every namespace separator with a directory separator
248
            $filename = str_replace('\\', DIRECTORY_SEPARATOR, $namespace);
249
        }
250
251
        // convert underscore
252
        $filename .= str_replace('_', DIRECTORY_SEPARATOR, $classname) . '.php';
253
254
        #echo "$classname => $filename <br>";
255
256
        // searches on include path for the file and returns absolute path
257
        $filename = stream_resolve_include_path($filename);
258
259
        #echo "$classname => $filename => $namespace<br>";
260
261
        if (is_string($filename)) {
262
            return self::includeFileAndMap($filename, $classname);
263
        }
264
265
        return false;
266
    }
267
268
    /**
269
     * Include File (and register it to the autoloading map file).
270
     *
271
     * This procedure ensures, that the autoload mapping array dataset
272
     * is increased stepwise resulting in a decreasing number of autoloading tries.
273
     *
274
     * @param string $filename  The file to be required
275
     * @param string $classname
276
     *
277
     * @return bool True on success of require, false otherwise.
278
     */
279
    public static function includeFileAndMap($filename, $classname)
0 ignored issues
show
Coding Style introduced by
function includeFileAndMap() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
280
    {
281
        $filename = realpath($filename);
282
283
        // conditional include
284
        include_once $filename;
285
286
        // add class and filename to the mapping array
287
        self::addMapping($classname, $filename);
288
289
        return true;
290
    }
291
292
    /**
293
     * Includes a file, if found.
294
     *
295
     * @param string $filename  The file to be included
296
     * @param string $classname (Optional) The classname expected inside this file.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $classname not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
297
     *
298
     * @return bool True on success of include, false otherwise.
299
     */
300
    public static function includeFile($filename, $classname = null)
0 ignored issues
show
Coding Style introduced by
function includeFile() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
301
    {
302
        $filename = realpath($filename);
303
304
        if (is_file($filename)) {
305
            include $filename;
306
307
            if (null === $classname || class_exists($classname, false)) {
308
                return true;
309
            }
310
        }
311
312
        return false;
313
    }
314
315
    /**
316
     * Writes the autoload mapping array into a file.
317
     * The target file is ROOT.'configuration/'.self::$autoloader
318
     * The content to be written is an associative array $array,
319
     * consisting of the old mapping array appended by a new mapping.
320
     *
321
     * @param $array associative array with relation of a classname to a filename
322
     */
323
    public static function writeAutoloadingMapFile($array)
0 ignored issues
show
Coding Style introduced by
function writeAutoloadingMapFile() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
324
    {
325
        if (is_writable(self::$mapfile) === false) {
326
            // create map file first
327
            self::readAutoloadingMapFile();
328
        }
329
330
        if (is_writable(self::$mapfile)) {
331
            return (bool) file_put_contents(self::$mapfile, serialize($array), LOCK_EX);
332
        } else {
333
            throw new \RuntimeException('Autoload cache file not writable: ' . self::$mapfile);
334
        }
335
    }
336
337
    /**
338
     * Reads the content of the autoloading map file and returns it unserialized.
339
     *
340
     * @return array<string> file content of autoload.config file
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
341
     */
342
    public static function readAutoloadingMapFile()
343
    {
344
        // create file, if not existant
345
        if (is_file(self::$mapfile)) {
346
            $file_resource = fopen(self::$mapfile, 'a', false);
0 ignored issues
show
Coding Style introduced by
$file_resource does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
347
            fclose($file_resource);
0 ignored issues
show
Coding Style introduced by
$file_resource does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
348
            unset($file_resource);
0 ignored issues
show
Coding Style introduced by
$file_resource does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
349
350
            return [];
351
        } else { // load map from file
352
            try {
353
                return (array) unserialize(file_get_contents(self::$mapfile));
354
            } catch (\Exception $e) {
355
                // delete mapfile, on unserialization error (error at offset xy)
356
                unlink(self::$mapfile);
357
            }
358
        }
359
    }
360
361
    /**
362
     * Reads the autoload mapping array from APC.
363
     *
364
     * @return array automatically generated classmap
365
     */
366
    public static function readAutoloadingMapApc()
367
    {
368
        return apc_fetch('KF_CLASSMAP');
369
    }
370
371
    /**
372
     * Writes the autoload mapping array to APC.
373
     *
374
     * @return bool automatically generated classmap
375
     * @return bool True if stored.
376
     */
377
    public static function writeAutoloadingMapApc($array)
0 ignored issues
show
Coding Style introduced by
function writeAutoloadingMapApc() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
378
    {
379
        return apc_store('KF_CLASSMAP', $array);
380
    }
381
382
    /**
383
     * Adds a new $classname to $filename mapping to the map array.
384
     * The new map array is written to apc or file.
385
     *
386
     * @param string $class Classname is the lookup key for $filename.
387
     * @param string $file  Filename is the file to load.
388
     *
389
     * @return bool True if added to map.
390
     */
391
    public static function addMapping($class, $file)
0 ignored issues
show
Coding Style introduced by
function addMapping() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
392
    {
393
        self::$autoloaderMap = array_merge((array) self::$autoloaderMap, [$class => $file]);
394
395
        if (defined('APC') and APC === true) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
396
            return self::writeAutoloadingMapApc(self::$autoloaderMap);
397
        }
398
399
        return self::writeAutoloadingMapFile(self::$autoloaderMap);
400
    }
401
402
    /**
403
     * Getter for the autoloader classmap.
404
     *
405
     * @return array autoloader classmap.
406
     */
407
    public static function getAutoloaderClassMap()
408
    {
409
        return self::$autoloaderMap;
410
    }
411
412
    /**
413
     * Setter for the classmap file.
414
     *
415
     * @param string classmap filepath.
416
     */
417
    public static function setClassMapFile($mapfile)
418
    {
419
        self::$mapfile = $mapfile;
420
    }
421
422
    /**
423
     * Setter for the inclusions classmap.
424
     *
425
     * @param array inclusions classmap (classname => file)
426
     */
427
    public static function setInclusionsClassMap(array $classmap)
428
    {
429
        self::$inclusionsClassmap = $classmap;
430
    }
431
432
    /**
433
     * Registers the autoloader.
434
     */
435
    public static function register($mapfile)
436
    {
437
        self::setClassMapFile($mapfile);
438
439
        spl_autoload_register([__CLASS__, 'autoload'], true, true);
440
    }
441
442
    /**
443
     * Unregisters the autoloader.
444
     */
445
    public static function unregister()
446
    {
447
        spl_autoload_unregister([__CLASS__, 'autoload']);
448
    }
449
}
450