1: <?php
2: namespace Genetsis;
3:
4: /**
5: * Genetsis ID library Autoload Class
6: *
7: * @package Genetsis
8: * @copyright Copyright (c) 2014 Genetsis
9: * @version 2.0
10: */
11:
12: class AutoloaderClass
13: {
14: /**
15: * An associative array where the key is a namespace prefix and the value
16: * is an array of base directories for classes in that namespace.
17: *
18: * @var array
19: */
20: protected static $prefixes = array();
21:
22: /**
23: * Set namespace to autoload class
24: */
25: public static function init()
26: {
27: self::addNamespace('Genetsis', dirname(__FILE__));
28: self::addNamespace('Genetsis\core', dirname(__FILE__) . '/core');
29: self::requireFile(dirname(__FILE__) . '/../config/Config.php');
30: self::register();
31: }
32:
33: /**
34: * Adds a base directory for a namespace prefix.
35: *
36: * @param string $prefix The namespace prefix.
37: * @param string $base_dir A base directory for class files in the
38: * namespace.
39: * @param bool $prepend If true, prepend the base directory to the stack
40: * instead of appending it; this causes it to be searched first rather
41: * than last.
42: * @return void
43: */
44: public static function addNamespace($prefix, $base_dir, $prepend = false)
45: {
46: // normalize namespace prefix
47: $prefix = trim($prefix, '\\') . '\\';
48:
49: // normalize the base directory with a trailing separator
50: $base_dir = rtrim($base_dir, '/') . DIRECTORY_SEPARATOR;
51: $base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
52:
53: // initialize the namespace prefix array
54: if (isset(self::$prefixes[$prefix]) === false) {
55: self::$prefixes[$prefix] = array();
56: }
57:
58: // retain the base directory for the namespace prefix
59: if ($prepend) {
60: array_unshift(self::$prefixes[$prefix], $base_dir);
61: } else {
62: array_push(self::$prefixes[$prefix], $base_dir);
63: }
64: }
65:
66: /**
67: * If a file exists, require it from the file system.
68: *
69: * @param string $file The file to require.
70: * @return bool True if the file exists, false if not.
71: */
72: protected static function requireFile($file)
73: {
74: if (file_exists($file)) {
75: require $file;
76: return true;
77: }
78: return false;
79: }
80:
81: /**
82: * Register loader with SPL autoloader stack.
83: *
84: * @return void
85: */
86: public static function register()
87: {
88: spl_autoload_register(__NAMESPACE__ . '\AutoloaderClass::loadClass');
89: }
90:
91: /**
92: * Loads the class file for a given class name.
93: *
94: * @param string $class The fully-qualified class name.
95: * @return mixed The mapped file name on success, or boolean false on
96: * failure.
97: */
98: public static function loadClass($class)
99: {
100: // the current namespace prefix
101: $prefix = $class;
102:
103: // work backwards through the namespace names of the fully-qualified
104: // class name to find a mapped file name
105: while (false !== $pos = strrpos($prefix, '\\')) {
106:
107: // retain the trailing namespace separator in the prefix
108: $prefix = substr($class, 0, $pos + 1);
109:
110: // the rest is the relative class name
111: $relative_class = substr($class, $pos + 1);
112:
113: // try to load a mapped file for the prefix and relative class
114: $mapped_file = self::loadMappedFile($prefix, $relative_class);
115: if ($mapped_file) {
116: return $mapped_file;
117: }
118:
119: // remove the trailing namespace separator for the next iteration
120: // of strrpos()
121: $prefix = rtrim($prefix, '\\');
122: }
123:
124: // never found a mapped file
125: return false;
126: }
127:
128: /**
129: * Load the mapped file for a namespace prefix and relative class.
130: *
131: * @param string $prefix The namespace prefix.
132: * @param string $relative_class The relative class name.
133: * @return mixed Boolean false if no mapped file can be loaded, or the
134: * name of the mapped file that was loaded.
135: */
136: protected static function loadMappedFile($prefix, $relative_class)
137: {
138: // are there any base directories for this namespace prefix?
139: if (isset(self::$prefixes[$prefix]) === false) {
140: return false;
141: }
142:
143: // look through base directories for this namespace prefix
144: foreach (self::$prefixes[$prefix] as $base_dir) {
145:
146: // replace the namespace prefix with the base directory,
147: // replace namespace separators with directory separators
148: // in the relative class name, append with .php
149: $file = $base_dir
150: . str_replace('\\', DIRECTORY_SEPARATOR, $relative_class)
151: . '.php';
152: $file = $base_dir
153: . str_replace('\\', '/', $relative_class)
154: . '.php';
155:
156: // if the mapped file exists, require it
157: if (self::requireFile($file)) {
158: // yes, we're done
159: return $file;
160: }
161: }
162:
163: // never found it
164: return false;
165: }
166: }
167:
168: