PluginProbe
ShiftController Employee Shift Scheduling / 4.9.76
ShiftController Employee Shift Scheduling v4.9.76
4.9.97 4.9.96 4.9.95 4.9.74 4.9.75 4.9.76 4.9.77 4.9.78 4.9.84 4.9.85 4.9.87 4.9.91 4.9.92 trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.2.4 All 38 releases
shiftcontroller / hc3 / dic.php

dic.php in ShiftController Employee Shift Scheduling 4.9.76, at hc3/dic.php

258 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if (! defined('ABSPATH')) exit; // Exit if accessed directly
2 /**
3 * Dependency Injector Container Class
4 *
5 */
6 interface HC3_IDic
7 {
8 public function bind( $entity, $interface = NULL, $singleton = TRUE );
9 public function make( $interface, $wrap = TRUE );
10 }
11
12 class HC3_Dic implements HC3_IDic
13 {
14 protected $bind = array();
15 protected $singletons = array();
16
17 public function __construct()
18 {
19 $this->bind( $this, get_class($this) );
20 }
21
22 /**
23 * Binds a concrete implementation to the interface.
24 * The below is not true as of 2017/03/21, this chain implementation appeared to be mind breaking, so hard to follow
25 * If several implementations are bound to one interface, it will return the latest one added.
26 * Then in implementations code they can refer to their own interface, but their own implementation will
27 * be skipped to avoid circular reference. So it is used like a decorator chain, each implementation can
28 * refer to an optional parent object of their own interface.
29 *
30 * @param string|object $entity A class name or object that implements an interface.
31 * @param string $interface Optional. An interface to be implemented. If omitted,
32 * it will require loading the class file to analyze which
33 * may add an overhead.
34 * @param bool $singleton Optional. If true then makes the returning object a singleton.
35 *
36 * @return object|NULL
37 */
38 public function bind( $entity, $interface = NULL, $singleton = TRUE )
39 {
40 if( $interface === NULL ){
41 $interface = is_object($entity) ? get_class($entity) : $entity;
42
43 // $interfaces = class_implements( $interface );
44 // echo "'$interface' IMPLEMENTS";
45 // _print_r( $interfaces );
46 // if( $interfaces ){
47 // echo "'$interface' IMPLEMENTS ";
48 // $interface = array_shift( $interfaces );
49 // echo "'$interface'<br>";
50 // }
51 }
52
53 $interface = strtolower( $interface );
54 // if( is_object($entity) )
55 // echo "BINDING '" . get_class($entity) . "' AS '" . $interface . "'<br>";
56 // else
57 // echo "BINDING '" . $entity . "' AS '" . $interface . "'<br>";
58
59 // echo "int = '$interface'<br>";
60
61 if( ! is_object($entity) ){
62 $entity = strtolower( $entity );
63 }
64
65 $this->bind[ $interface ] = $entity;
66
67 if( $singleton ){
68 $this->singletons[ $interface ] = $interface;
69 }
70
71 return $this;
72 }
73
74 /**
75 * Returns a concrete implementation of the interface with their dependencies injected in constructor.
76 * Dependencies can be either type-hinted by class/interface name like HC3_Module_ClassName $obj
77 * or var name hinted, the var name defines the class name, like this $HC3_Module_ClassName
78 Returns a concrete implementation of the interface with their dependencies injected in constructor.
79 *
80 * @return object|NULL A concrete implementation of the interface.
81 */
82 public function make( $interface, $wrap = TRUE )
83 {
84 $hooks = NULL;
85 if( array_key_exists('hc3_hooks', $this->bind) ){
86 $hooks = $this->bind['hc3_hooks'];
87 }
88 else {
89 $wrap = FALSE;
90 }
91 if( 'hc3_hooks' == $interface ){
92 $wrap = FALSE;
93 }
94
95 $interface = strtolower( $interface );
96
97 // echo "WANT '$interface'<br>";
98 // echo 'GOTSKIP';
99 // _print_r( $skip );
100
101 // _print_r( array_keys($this->bind) );
102
103 $bind_index = 0;
104 // binded
105 if( array_key_exists($interface, $this->bind) ){
106 // echo "INT '$interface' BOUND<br>";
107 $thisone = $this->bind[$interface];
108
109 if( is_object($thisone) ){
110 if( $wrap ){
111 $return = $hooks->wrap($thisone);
112 return $return;
113 }
114 return $thisone;
115 }
116 else {
117 if( ! $thisone ){
118 if( class_exists($interface) ){
119 $thisone = $interface;
120 }
121 }
122 $classname = $thisone;
123 }
124 }
125 else {
126 $classname = $interface;
127
128 // try to use a default implementation
129 // if( substr($classname, -1) == '_' ){
130 // $classname = substr($classname, 0, -1);
131 // }
132
133 $this->singletons[$interface] = $interface;
134 }
135
136 // echo "REAL '$classname'<br>";
137 // _print_r( $classname );
138 if( ! strlen($classname) ){
139 $return = NULL;
140 return $return;
141 }
142
143 $class = new ReflectionClass( $classname );
144 $constructor = $class->getConstructor();
145
146 $dependencies = array();
147
148 if( isset($constructor) ){
149 $need_args = $constructor->getParameters();
150 foreach( $need_args as $need_arg ){
151 $is_optional = $need_arg->isOptional();
152 $wrap_this = FALSE;
153
154 $arg_name = $need_arg->getName();
155 $arg_name = strtolower( $arg_name );
156
157 $need_classname = NULL;
158
159 try {
160 if( method_exists($need_arg, 'getType') ){
161 // $need_class = $need_arg->getType() && !$need_arg->getType()->isBuiltin() ? new ReflectionClass($need_arg->getType()->getName()) : NULL;
162 $argType = $need_arg->getType();
163 if( (! $argType) OR $argType->isBuiltin() ){
164 $argClass = NULL;
165 }
166 else {
167 if( method_exists($argType, 'getName') ){
168 $argClassName = $argType->getName();
169 }
170 else {
171 $argClassName = '' . $argType;
172 }
173 $argClass = new ReflectionClass( $argClassName );
174 }
175 $need_class = $argClass;
176 }
177 else {
178 $need_class = $need_arg->getClass();
179 }
180 }
181 catch( ReflectionException $e ){
182 $need_class = NULL;
183 }
184
185 if( $need_class ){
186 $need_classname = $need_class->getName();
187 }
188
189 if( ! $need_class ){
190 if( ! $is_optional ){
191 $need_classname = $arg_name;
192 $wrap_this = TRUE;
193 // echo "NOW NEED CLASSNAME = '$need_classname'<br>";
194 }
195 }
196
197 if( $is_optional && (! $need_classname) ){
198 continue;
199 }
200
201 if( (! $need_classname) && (! $is_optional) ){
202 echo "DIC: class/varname is unknown for '$arg_name' argument of '$classname'!<br>";
203 exit;
204 }
205
206 if( $need_classname ){
207 $need_classname = strtolower( $need_classname );
208
209 if( ! array_key_exists($need_classname, $this->bind) ){
210 // if( $is_optional ){
211 // continue;
212 // }
213 // else {
214 // echo "DIC: class '$need_classname' is not registered while trying to use it as a dependency for '$classname'<br>";
215 // exit;
216 // }
217 }
218 $dependencies[] = array( $need_classname, $wrap_this );
219 }
220 }
221 }
222
223 if( $dependencies ){
224 $args = array();
225
226 foreach( $dependencies as $dep ){
227 list( $dep, $wrap_this ) = $dep;
228 if( ! is_object($dep) ){
229 $dep = $this->make($dep, $wrap_this);
230 }
231 $args[] = $dep;
232 }
233 $class = new ReflectionClass($classname);
234 $return = $class->newInstanceArgs($args);
235 }
236 else {
237 $return = new $classname;
238 }
239
240 if( isset($this->singletons[$interface]) ){
241 // echo 'REBIND ' . $interface . ' AS ' . get_class($return) . '<br>';
242 // echo 'BIND INDEX = ' . $bind_index . '<br>';
243 // _print_r( $this->bind[$interface] );
244 // $this->bind( $return, $interface );
245 $this->bind[ $interface ] = $return;
246 }
247
248 if( $wrap ){
249 $return = $hooks->wrap($return);
250 }
251 else {
252 // echo "NO WRAP FOR " . get_class($return) . "<br>\n";
253 }
254
255 return $return;
256 }
257 }
258