bzr branch
http://bzr.ed.am/www/slight
1
by Tim Marston
initial commit |
1 |
<?php |
2 |
/** |
|
3 |
* Flight: An extensible micro-framework. |
|
4 |
* |
|
5 |
* @copyright Copyright (c) 2011, Mike Cao <mike@mikecao.com> |
|
6 |
* @license MIT, http://flightphp.com/license |
|
7 |
*/ |
|
8 |
||
9 |
namespace flight\core; |
|
10 |
||
11 |
/** |
|
12 |
* The Loader class is responsible for loading objects. It maintains |
|
13 |
* a list of reusable class instances and can generate a new class |
|
14 |
* instances with custom initialization parameters. It also performs |
|
15 |
* class autoloading. |
|
16 |
*/ |
|
17 |
class Loader { |
|
18 |
/** |
|
19 |
* Registered classes. |
|
20 |
* |
|
21 |
* @var array |
|
22 |
*/ |
|
23 |
protected $classes = array(); |
|
24 |
||
25 |
/** |
|
26 |
* Class instances. |
|
27 |
* |
|
28 |
* @var array |
|
29 |
*/ |
|
30 |
protected $instances = array(); |
|
31 |
||
32 |
/** |
|
33 |
* Autoload directories. |
|
34 |
* |
|
35 |
* @var array |
|
36 |
*/ |
|
37 |
protected static $dirs = array(); |
|
38 |
||
39 |
/** |
|
40 |
* Registers a class. |
|
41 |
* |
|
42 |
* @param string $name Registry name |
|
43 |
* @param string|callable $class Class name or function to instantiate class |
|
44 |
* @param array $params Class initialization parameters |
|
45 |
* @param callback $callback Function to call after object instantiation |
|
46 |
*/ |
|
47 |
public function register($name, $class, array $params = array(), $callback = null) { |
|
48 |
unset($this->instances[$name]); |
|
49 |
||
50 |
$this->classes[$name] = array($class, $params, $callback); |
|
51 |
} |
|
52 |
||
53 |
/** |
|
54 |
* Unregisters a class. |
|
55 |
* |
|
56 |
* @param string $name Registry name |
|
57 |
*/ |
|
58 |
public function unregister($name) { |
|
59 |
unset($this->classes[$name]); |
|
60 |
} |
|
61 |
||
62 |
/** |
|
63 |
* Loads a registered class. |
|
64 |
* |
|
65 |
* @param string $name Method name |
|
66 |
* @param bool $shared Shared instance |
|
67 |
* @return object Class instance |
|
68 |
*/ |
|
69 |
public function load($name, $shared = true) { |
|
70 |
$obj = null; |
|
71 |
||
72 |
if (isset($this->classes[$name])) { |
|
73 |
list($class, $params, $callback) = $this->classes[$name]; |
|
74 |
||
75 |
$exists = isset($this->instances[$name]); |
|
76 |
||
77 |
if ($shared) { |
|
78 |
$obj = ($exists) ? |
|
79 |
$this->getInstance($name) : |
|
80 |
$this->newInstance($class, $params); |
|
81 |
||
82 |
if (!$exists) { |
|
83 |
$this->instances[$name] = $obj; |
|
84 |
} |
|
85 |
} |
|
86 |
else { |
|
87 |
$obj = $this->newInstance($class, $params); |
|
88 |
} |
|
89 |
||
90 |
if ($callback && (!$shared || !$exists)) { |
|
91 |
$ref = array(&$obj); |
|
92 |
call_user_func_array($callback, $ref); |
|
93 |
} |
|
94 |
} |
|
95 |
||
96 |
return $obj; |
|
97 |
} |
|
98 |
||
99 |
/** |
|
100 |
* Gets a single instance of a class. |
|
101 |
* |
|
102 |
* @param string $name Instance name |
|
103 |
* @return object Class instance |
|
104 |
*/ |
|
105 |
public function getInstance($name) { |
|
106 |
return isset($this->instances[$name]) ? $this->instances[$name] : null; |
|
107 |
} |
|
108 |
||
109 |
/** |
|
110 |
* Gets a new instance of a class. |
|
111 |
* |
|
112 |
* @param string|callable $class Class name or callback function to instantiate class |
|
113 |
* @param array $params Class initialization parameters |
|
114 |
* @return object Class instance |
|
115 |
*/ |
|
116 |
public function newInstance($class, array $params = array()) { |
|
117 |
if (is_callable($class)) { |
|
118 |
return call_user_func_array($class, $params); |
|
119 |
} |
|
120 |
||
121 |
switch (count($params)) { |
|
122 |
case 0: |
|
123 |
return new $class(); |
|
124 |
case 1: |
|
125 |
return new $class($params[0]); |
|
126 |
case 2: |
|
127 |
return new $class($params[0], $params[1]); |
|
128 |
case 3: |
|
129 |
return new $class($params[0], $params[1], $params[2]); |
|
130 |
case 4: |
|
131 |
return new $class($params[0], $params[1], $params[2], $params[3]); |
|
132 |
case 5: |
|
133 |
return new $class($params[0], $params[1], $params[2], $params[3], $params[4]); |
|
134 |
default: |
|
135 |
$refClass = new \ReflectionClass($class); |
|
136 |
return $refClass->newInstanceArgs($params); |
|
137 |
} |
|
138 |
} |
|
139 |
||
140 |
/** |
|
141 |
* Resets the object to the initial state. |
|
142 |
*/ |
|
143 |
public function reset() { |
|
144 |
$this->classes = array(); |
|
145 |
$this->instances = array(); |
|
146 |
} |
|
147 |
||
148 |
/*** Autoloading Functions ***/ |
|
149 |
||
150 |
/** |
|
151 |
* Starts/stops autoloader. |
|
152 |
* |
|
153 |
* @param bool $enabled Enable/disable autoloading |
|
154 |
* @param mixed $dirs Autoload directories |
|
155 |
*/ |
|
156 |
public static function autoload($enabled = true, $dirs = array()) { |
|
157 |
if ($enabled) { |
|
158 |
spl_autoload_register(array(__CLASS__, 'loadClass')); |
|
159 |
} |
|
160 |
else { |
|
161 |
spl_autoload_unregister(array(__CLASS__, 'loadClass')); |
|
162 |
} |
|
163 |
||
164 |
if (!empty($dirs)) { |
|
165 |
self::addDirectory($dirs); |
|
166 |
} |
|
167 |
} |
|
168 |
||
169 |
/** |
|
170 |
* Autoloads classes. |
|
171 |
* |
|
172 |
* @param string $class Class name |
|
173 |
*/ |
|
174 |
public static function loadClass($class) { |
|
175 |
$class_file = str_replace(array('\\', '_'), '/', $class).'.php'; |
|
176 |
||
177 |
foreach (self::$dirs as $dir) { |
|
178 |
$file = $dir.'/'.$class_file; |
|
179 |
if (file_exists($file)) { |
|
180 |
require $file; |
|
181 |
return; |
|
182 |
} |
|
183 |
} |
|
184 |
} |
|
185 |
||
186 |
/** |
|
187 |
* Adds a directory for autoloading classes. |
|
188 |
* |
|
189 |
* @param mixed $dir Directory path |
|
190 |
*/ |
|
191 |
public static function addDirectory($dir) { |
|
192 |
if (is_array($dir) || is_object($dir)) { |
|
193 |
foreach ($dir as $value) { |
|
194 |
self::addDirectory($value); |
|
195 |
} |
|
196 |
} |
|
197 |
else if (is_string($dir)) { |
|
198 |
if (!in_array($dir, self::$dirs)) self::$dirs[] = $dir; |
|
199 |
} |
|
200 |
} |
|
201 |
} |