Completed
Push — master ( e0b5a6...df082d )
by Pol
06:14
created

DynamicObjectsTrait::extend()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.1755

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 7
cts 9
cp 0.7778
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 4
nop 1
crap 4.1755
1
<?php
2
3
namespace drupol\DynamicObjects;
4
5
use drupol\Memoize\MemoizeTrait;
6
7
/**
8
 * Trait DynamicObjectsTrait.
9
 *
10
 * @package drupol\DynamicObjects
11
 */
12
trait DynamicObjectsTrait
13
{
14
    use MemoizeTrait;
15
16
    /**
17
     * @var array
18
     */
19
    protected static $dynamicMethods = array();
20
21
    /**
22
     * @var array
23
     */
24
    protected static $dynamicProperties = array();
25
26
    /**
27
     * Add a dynamic property.
28
     *
29
     * @param string $name
30
     *   The property name.
31
     * @param mixed $value
32
     *   The property value.
33
     * @param bool $memoize
34
     *   Memoize parameter.
35
     */
36 5
    public static function addDynamicProperty($name, $value, $memoize = false)
37
    {
38 5
        static::$dynamicProperties[get_called_class()][$name] = [
39 5
            'name' => $name,
40 5
            'factory' => $value,
41 5
            'memoize' => $memoize,
42
        ];
43 5
    }
44
45
    /**
46
     * Add a dynamic method.
47
     *
48
     * @param $name
49
     *   The method name.
50
     * @param \Closure $func
51
     *   The method.
52
     * @param bool $memoize
53
     *   Memoize parameter.
54
     * @param bool $static
55
     *   Static flag parameter.
56
     */
57 5
    public static function addDynamicMethod($name, \Closure $func, $memoize = false, $static = false)
58
    {
59 5
        static::$dynamicMethods[get_called_class()][$name] = [
60 5
            'name' => $name,
61 5
            'factory' => $func,
62 5
            'memoize' => $memoize,
63 5
            'static' => $static,
64
        ];
65 5
    }
66
67
    /**
68
     * Check if a dynamic property exists.
69
     *
70
     * @param string $name
71
     *   The property name.
72
     * @return bool
73
     *   True if the property exists, false otherwise.
74
     */
75 8
    public static function hasDynamicProperty($name)
76
    {
77 8
        return isset(static::$dynamicProperties[get_called_class()][$name]);
78
    }
79
80
    /**
81
     * Check if a dynamic method exists.
82
     *
83
     * @param string $name
84
     *   The property name.
85
     * @return bool
86
     *   True if the property exists, false otherwise.
87
     */
88 7
    public static function hasDynamicMethod($name)
89
    {
90 7
        return isset(static::$dynamicMethods[get_called_class()][$name]);
91
    }
92
93
    /**
94
     * Get a dynamic property.
95
     *
96
     * @param $name
97
     *   The property name.
98
     * @return mixed|null
99
     *   The property value if it exists, null otherwise.
100
     */
101 4
    public static function getDynamicProperty($name)
102
    {
103 4
        if (static::hasDynamicProperty($name)) {
104 3
            return static::$dynamicProperties[get_called_class()][$name];
105
        }
106
107 1
        return null;
108
    }
109
110
    /**
111
     * Get a dynamic method.
112
     *
113
     * @param $name
114
     *   The method name.
115
     * @return array|null
116
     *   The method data if it exists, null otherwise.
117
     */
118 4
    public static function getDynamicMethod($name)
119
    {
120 4
        return (static::hasDynamicMethod($name)) ?
121 4
            static::$dynamicMethods[get_called_class()][$name] : null;
122
    }
123
124
    /**
125
     * Clear dynamic properties.
126
     */
127 1
    public static function clearDynamicProperties()
128
    {
129 1
        static::$dynamicProperties[get_called_class()] = array();
130 1
    }
131
132
    /**
133
     * Clear dynamic methods.
134
     */
135 1
    public static function clearDynamicMethods()
136
    {
137 1
        static::$dynamicMethods[get_called_class()] = array();
138 1
    }
139
140
    /**
141
     * Remove a dynamic property.
142
     *
143
     * @param string $name
144
     *   The property name.
145
     */
146 1
    public static function removeDynamicProperty($name)
147
    {
148 1
        unset(static::$dynamicProperties[get_called_class()][$name]);
149 1
    }
150
151
    /**
152
     * Remove a dynamic method.
153
     *
154
     * @param string $name
155
     *   The method name.
156
     */
157 1
    public static function removeDynamicMethod($name)
158
    {
159 1
        unset(static::$dynamicMethods[get_called_class()][$name]);
160 1
    }
161
162
    /**
163
     * Execute a closure.
164
     *
165
     * @param \Closure $func
166
     *   The closure.
167
     * @param array $parameters
168
     *   The closure's parameters.
169
     * @param bool $memoize
170
     *   The memoize parameter.
171
     *
172
     * @return mixed|null
173
     *   The return of the closure.
174
     *
175
     * @throws \Psr\SimpleCache\InvalidArgumentException
176
     */
177 5
    public function doDynamicRequest(\Closure $func, array $parameters = [], $memoize = false)
178
    {
179 5
        if (!class_exists('\drupol\Memoize\Memoize') || false === $memoize) {
180 5
            $memoize = false;
181 5
        }
182
183 5
        if (true === $memoize) {
184 2
            return $this->memoize($func, $parameters);
185
        }
186
187 5
        return call_user_func_array($func->bindTo($this, get_called_class()), $parameters);
188
    }
189
190
    /**
191
     * Extend the dynamic object.
192
     *
193
     * @param $extensions
194
     *   A file that returns a callable or a callable.
195
     *
196
     * @return $this
197
     *
198
     * @throws \InvalidArgumentException
199
     */
200 1
    public function extend($extensions)
201
    {
202 1
        if (is_string($extensions) && file_exists($extensions)) {
203 1
            $extensions = include $extensions;
204 1
        }
205
206 1
        if (is_callable($extensions)) {
207 1
            call_user_func($extensions, $this);
208
209 1
            return $this;
210
        }
211
212
        throw new \InvalidArgumentException(
213
            'DynamicObjectsTrait::extend() requires a callable or a file that returns one.'
214
        );
215
    }
216
217
    /**
218
     * @param $method
219
     * @param array $parameters
220
     *
221
     * @return mixed
222
     * @throws \Psr\SimpleCache\InvalidArgumentException
223
     */
224 4
    public function __call($method, array $parameters = array())
225
    {
226 4
        if ($data = static::getDynamicMethod($method)) {
227 3
            return $this->doDynamicRequest($data['factory'], $parameters, $data['memoize']);
228
        }
229
230 1
        throw new \BadMethodCallException(sprintf('Undefined method: %s().', $method));
231
    }
232
233
    /**
234
     * @param $method
235
     * @param array $parameters
236
     *
237
     * @return mixed
238
     * @throws \Psr\SimpleCache\InvalidArgumentException
239
     */
240 2
    public static function __callStatic($method, array $parameters = array())
241
    {
242 2
        $instance = new static();
243
244 2
        if ($data = static::getDynamicMethod($method)) {
245 1
            if (true == $data['static']) {
246 1
                return $instance->doDynamicRequest($data['factory'], $parameters, $data['memoize']);
247
            }
248
        }
249
250 1
        throw new \BadMethodCallException(sprintf('Undefined static method: %s().', $method));
251
    }
252
253
    /**
254
     * {inheritdoc}
255
     */
256 4
    public function __get($property)
257
    {
258 4
        if ($data = static::getDynamicProperty($property)) {
259 3
            $return = $data['factory'];
260
261 3
            if (is_callable($data['factory'])) {
262 2
                $return = $this->doDynamicRequest($data['factory'], [], $data['memoize']);
263 2
            }
264
265 3
            return $return;
266
        }
267
268 1
        throw new \DomainException(sprintf('Undefined property: %s.', $property));
269
    }
270
271
    /**
272
     * {inheritdoc}
273
     */
274 3
    public function __set($property, $value)
275
    {
276 3
        if (static::hasDynamicProperty($property)) {
277 1
            static::addDynamicProperty($property, $value);
278 1
        }
279 3
    }
280
}
281