Completed
Push — master ( 9fcaad...45d746 )
by Pol
01:37
created

DynamicObjectsTrait::doDynamicRequest()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 10
cts 10
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 6
nop 3
crap 5
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|array $names
30
     *   The property name or an array of property names.
31
     * @param mixed $value
32
     *   The property value.
33
     * @param bool $memoize
34
     *   Memoize parameter.
35
     */
36 5 View Code Duplication
    public static function addDynamicProperty($names, $value, $memoize = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
37
    {
38 5
        if (!is_array($names)) {
39 5
            $names = [$names];
40
        }
41
42 5
        foreach ($names as $property) {
43 5
            static::$dynamicProperties[get_called_class()][$property] = [
44 5
                'name' => $property,
45 5
                'factory' => $value,
46 5
                'memoize' => $memoize,
47
            ];
48
        }
49 5
    }
50
51
    /**
52
     * Add a dynamic method.
53
     *
54
     * @param string|array $names
55
     *   The method name or an array of method names.
56
     * @param \Closure $func
57
     *   The method.
58
     * @param bool $memoize
59
     *   Memoize parameter.
60
     * @param bool $static
61
     *   Static flag parameter.
62
     */
63 5 View Code Duplication
    public static function addDynamicMethod($names, \Closure $func, $memoize = false, $static = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
64
    {
65 5
        if (!is_array($names)) {
66 5
            $names = [$names];
67
        }
68
69 5
        foreach ($names as $method) {
70 5
            static::$dynamicMethods[get_called_class()][$method] = [
71 5
                'name' => $method,
72 5
                'factory' => $func,
73 5
                'memoize' => $memoize,
74 5
                'static' => $static,
75
            ];
76
        }
77 5
    }
78
79
    /**
80
     * Check if a dynamic property exists.
81
     *
82
     * @param string $name
83
     *   The property name.
84
     * @return bool
85
     *   True if the property exists, false otherwise.
86
     */
87 8
    public static function hasDynamicProperty($name)
88
    {
89 8
        return isset(static::$dynamicProperties[get_called_class()][$name]);
90
    }
91
92
    /**
93
     * Check if a dynamic method exists.
94
     *
95
     * @param string $name
96
     *   The property name.
97
     * @return bool
98
     *   True if the property exists, false otherwise.
99
     */
100 7
    public static function hasDynamicMethod($name)
101
    {
102 7
        return isset(static::$dynamicMethods[get_called_class()][$name]);
103
    }
104
105
    /**
106
     * Get a dynamic property.
107
     *
108
     * @param $name
109
     *   The property name.
110
     * @return mixed|null
111
     *   The property value if it exists, null otherwise.
112
     */
113 4
    public static function getDynamicProperty($name)
114
    {
115 4
        if (static::hasDynamicProperty($name)) {
116 3
            return static::$dynamicProperties[get_called_class()][$name];
117
        }
118
119 1
        return null;
120
    }
121
122
    /**
123
     * Get a dynamic method.
124
     *
125
     * @param $name
126
     *   The method name.
127
     * @return array|null
128
     *   The method data if it exists, null otherwise.
129
     */
130 4
    public static function getDynamicMethod($name)
131
    {
132 4
        return (static::hasDynamicMethod($name)) ?
133 4
            static::$dynamicMethods[get_called_class()][$name] : null;
134
    }
135
136
    /**
137
     * Clear dynamic properties.
138
     */
139 1
    public static function clearDynamicProperties()
140
    {
141 1
        static::$dynamicProperties[get_called_class()] = array();
142 1
    }
143
144
    /**
145
     * Clear dynamic methods.
146
     */
147 1
    public static function clearDynamicMethods()
148
    {
149 1
        static::$dynamicMethods[get_called_class()] = array();
150 1
    }
151
152
    /**
153
     * Remove a dynamic property.
154
     *
155
     * @param string $name
156
     *   The property name.
157
     */
158 1
    public static function removeDynamicProperty($name)
159
    {
160 1
        unset(static::$dynamicProperties[get_called_class()][$name]);
161 1
    }
162
163
    /**
164
     * Remove a dynamic method.
165
     *
166
     * @param string $name
167
     *   The method name.
168
     */
169 1
    public static function removeDynamicMethod($name)
170
    {
171 1
        unset(static::$dynamicMethods[get_called_class()][$name]);
172 1
    }
173
174
    /**
175
     * Execute a closure.
176
     *
177
     * @param \Closure $func
178
     *   The closure.
179
     * @param array $parameters
180
     *   The closure's parameters.
181
     * @param bool $memoize
182
     *   The memoize parameter.
183
     *
184
     * @return mixed|null
185
     *   The return of the closure.
186
     *
187
     * @throws \Psr\SimpleCache\InvalidArgumentException
188
     */
189 5
    public function doDynamicRequest(\Closure $func, array $parameters = [], $memoize = false)
190
    {
191 5
        if (!class_exists('\drupol\Memoize\Memoize') || false === $memoize) {
192 5
            $memoize = false;
193
        }
194
195 5
        if (true === $memoize) {
196 2
            return $this->memoize($func, $parameters);
197
        }
198
199 5
        $class = get_called_class();
200 5
        $reflexion = new \ReflectionClass($class);
201
202 5
        if (!$reflexion->isAnonymous()) {
203 5
            $func = $func->bindTo($this, $class);
204
        }
205
206 5
        return call_user_func_array($func, $parameters);
207
    }
208
209
    /**
210
     * Extend the dynamic object.
211
     *
212
     * @param mixed $extensions
213
     *   A file that returns a callable or a callable.
214
     *
215
     * @return $this
216
     *
217
     * @throws \InvalidArgumentException
218
     */
219 1
    public function extend($extensions = null)
220
    {
221 1
        if (is_string($extensions) && file_exists($extensions)) {
222 1
            $extensions = include $extensions;
223
        }
224
225 1
        if (is_callable($extensions)) {
226 1
            call_user_func($extensions, $this);
227
228 1
            return $this;
229
        }
230
231 1
        if (is_null($extensions)) {
232 1
            return $this;
233
        }
234
235 1
        throw new \InvalidArgumentException(
236 1
            'DynamicObjectsTrait::extend() requires a callable or a file that returns one.'
237
        );
238
    }
239
240
    /**
241
     * @param $method
242
     * @param array $parameters
243
     *
244
     * @return mixed
245
     * @throws \Psr\SimpleCache\InvalidArgumentException
246
     */
247 4
    public function __call($method, array $parameters = array())
248
    {
249 4
        if ($data = static::getDynamicMethod($method)) {
250 3
            return $this->doDynamicRequest($data['factory'], $parameters, $data['memoize']);
251
        }
252
253 1
        throw new \BadMethodCallException(sprintf('Undefined method: %s().', $method));
254
    }
255
256
    /**
257
     * @param $method
258
     * @param array $parameters
259
     *
260
     * @return mixed
261
     * @throws \Psr\SimpleCache\InvalidArgumentException
262
     */
263 2
    public static function __callStatic($method, array $parameters = array())
264
    {
265 2
        $instance = new static();
266
267 2
        if ($data = static::getDynamicMethod($method)) {
268 1
            if (true == $data['static']) {
269 1
                return $instance->doDynamicRequest($data['factory'], $parameters, $data['memoize']);
270
            }
271
        }
272
273 1
        throw new \BadMethodCallException(sprintf('Undefined static method: %s().', $method));
274
    }
275
276
    /**
277
     * {inheritdoc}
278
     */
279 4
    public function __get($property)
280
    {
281 4
        if ($data = static::getDynamicProperty($property)) {
282 3
            $return = $data['factory'];
283
284 3
            if (is_callable($data['factory'])) {
285 2
                $return = $this->doDynamicRequest($data['factory'], [], $data['memoize']);
286
            }
287
288 3
            return $return;
289
        }
290
291 1
        throw new \DomainException(sprintf('Undefined property: %s.', $property));
292
    }
293
294
    /**
295
     * {inheritdoc}
296
     */
297 3
    public function __set($property, $value)
298
    {
299 3
        if (static::hasDynamicProperty($property)) {
300 1
            static::addDynamicProperty($property, $value);
301
        }
302 3
    }
303
}
304