1 <?php
2
3 namespace Docolight\Support;
4
5 use RuntimeException;
6 use Docolight\Container\Container;
7
8 /**
9 * The Facade design pattern is often used when a system is very complex or difficult to understand because the system has a large number of interdependent classes or its source code is unavailable.
10 * This pattern hides the complexities of the larger system and provides a simpler interface to the client.
11 * It typically involves a single wrapper class which contains a set of members required by client.
12 * These members access the system on behalf of the facade client and hide the implementation details.
13 *
14 * @author Krisan Alfa Timur <krisanalfa@docotel.co.id>
15 */
16 abstract class Facade
17 {
18 /**
19 * The application instance being facaded.
20 *
21 * @var \Docolight\Container\Container
22 */
23 protected static $container;
24
25 /**
26 * The resolved object instances.
27 *
28 * @var array
29 */
30 protected static $instances;
31
32 /**
33 * Get the root object behind the facade.
34 *
35 * @return mixed
36 */
37 public static function root()
38 {
39 return static::resolve(static::accessor());
40 }
41
42 /**
43 * Get the registered name of the component.
44 *
45 * @return string
46 *
47 * @throws \RuntimeException
48 */
49 protected static function accessor()
50 {
51 throw new RuntimeException('Facade does not implement accessor method.');
52 }
53
54 /**
55 * Resolve the facade root instance from the container.
56 *
57 * @param string $name
58 *
59 * @return mixed
60 */
61 protected static function resolve($name)
62 {
63 if (is_object($name)) {
64 return $name;
65 }
66
67 if (isset(static::$instances[$name])) {
68 return static::$instances[$name];
69 }
70
71 return static::$instances[$name] = static::$container[$name];
72 }
73
74 /**
75 * Clear a resolved facade instance.
76 *
77 * @param string $name
78 */
79 public static function clear($name)
80 {
81 unset(static::$instances[$name]);
82 }
83
84 /**
85 * Clear all of the resolved instances.
86 */
87 public static function clears()
88 {
89 static::$instances = array();
90 }
91
92 /**
93 * Get the application instance behind the facade.
94 *
95 * @return \Docolight\Container\Container
96 *
97 * @throws \RuntimeException
98 */
99 public static function container()
100 {
101 $container = static::$container;
102
103 if (!$container instanceof Container) {
104 throw new RuntimeException('Container not set!');
105 }
106
107 return static::$container;
108 }
109
110 /**
111 * Set the application instance.
112 *
113 * @param \Docolight\Container\Container $container
114 */
115 public static function set(Container $container)
116 {
117 static::$container = $container;
118 }
119
120 /**
121 * Handle dynamic, static calls to the object.
122 *
123 * @param string $method
124 * @param array $args
125 *
126 * @return mixed
127 */
128 public static function __callStatic($method, $args)
129 {
130 $instance = static::root();
131
132 switch (count($args)) {
133 case 0:
134 return $instance->$method();
135
136 case 1:
137 return $instance->$method($args[0]);
138
139 case 2:
140 return $instance->$method($args[0], $args[1]);
141
142 case 3:
143 return $instance->$method($args[0], $args[1], $args[2]);
144
145 case 4:
146 return $instance->$method($args[0], $args[1], $args[2], $args[3]);
147
148 default:
149 return call_user_func_array([$instance, $method], $args);
150 }
151 }
152 }
153