Completed
Push — master ( 686466...ec002f )
by Pol
12:43
created

DynamicObjectsTrait::convertToAnonymous()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 23
Code Lines 13

Duplication

Lines 8
Ratio 34.78 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 0
Metric Value
dl 8
loc 23
ccs 7
cts 7
cp 1
c 0
b 0
f 0
rs 8.5906
cc 5
eloc 13
nc 8
nop 1
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
     * Convert an object into an anonymous object.
28
     *
29
     * @param $object
30
     *
31
     * @return DynamicObject
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use anonymous//src/DynamicObjectsTrait.php$0.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
32
     */
33
    public static function convertToAnonymous($object)
34
    {
35
        $reflexion = new \ReflectionClass($object);
36 5
        $class = new class extends DynamicObject {
37
        };
38 5
39 5 View Code Duplication
        foreach ($reflexion->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
40 5
            $method->setAccessible(true);
41 5
            $class::addDynamicMethod($method->name, $method->getClosure($object));
42
        }
43 5
44 View Code Duplication
        foreach ($reflexion->getMethods(\ReflectionMethod::IS_PROTECTED || \ReflectionMethod::IS_PRIVATE) as $method) {
45
            $method->setAccessible(false);
46
            $class::addDynamicMethod($method->name, $method->getClosure($object));
47
        }
48
49
        foreach ($reflexion->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
50
            $property->setAccessible(true);
51
            $class::addDynamicProperty($property->name, $property->getValue($object));
52
        }
53
54
        return $class;
55 4
    }
56
57 4
    /**
58 4
     * Add a dynamic property.
59 4
     *
60 4
     * @param string $name
61
     *   The property name.
62 4
     * @param mixed $value
63
     *   The property value.
64
     * @param bool $memoize
65
     *   Memoize parameter.
66
     */
67
    public static function addDynamicProperty($name, $value, $memoize = false)
68
    {
69
        static::$dynamicProperties[get_called_class()][$name] = [
70
          'name' => $name,
71
          'factory' => $value,
72 8
          'memoize' => $memoize,
73
        ];
74 8
    }
75
76
    /**
77
     * Add a dynamic method.
78
     *
79
     * @param $name
80
     *   The method name.
81
     * @param \Closure $func
82
     *   The method.
83
     * @param bool $memoize
84
     *   Memoize parameter.
85 6
     */
86
    public static function addDynamicMethod($name, \Closure $func, $memoize = false)
87 6
    {
88
        static::$dynamicMethods[get_called_class()][$name] = [
89
          'name' => $name,
90
          'factory' => $func,
91
          'memoize' => $memoize,
92
        ];
93
    }
94
95
    /**
96
     * Check if a dynamic property exists.
97
     *
98 4
     * @param string $name
99
     *   The property name.
100 4
     * @return bool
101 3
     *   True if the property exists, false otherwise.
102
     */
103
    public static function hasDynamicProperty($name)
104 1
    {
105
        return isset(static::$dynamicProperties[get_called_class()][$name]);
106
    }
107
108
    /**
109
     * Check if a dynamic method exists.
110
     *
111
     * @param string $name
112
     *   The property name.
113
     * @return bool
114
     *   True if the property exists, false otherwise.
115 2
     */
116
    public static function hasDynamicMethod($name)
117 2
    {
118 2
        return isset(static::$dynamicMethods[get_called_class()][$name]);
119
    }
120
121
    /**
122
     * Get a dynamic property.
123
     *
124 1
     * @param $name
125
     *   The property name.
126 1
     * @return mixed|null
127 1
     *   The property value if it exists, null otherwise.
128
     */
129
    public static function getDynamicProperty($name)
130
    {
131
        if (static::hasDynamicProperty($name)) {
132 1
            return static::$dynamicProperties[get_called_class()][$name];
133
        }
134 1
135 1
        return null;
136
    }
137
138
    /**
139
     * Get a dynamic method.
140
     *
141
     * @param $name
142
     *   The method name.
143 1
     * @return mixed|null
144
     *   The method if it exists, null otherwise.
145 1
     */
146 1
    public static function getDynamicMethod($name)
147
    {
148
        return ( static::hasDynamicMethod($name) ) ?
149
          static::$dynamicMethods[get_called_class()][$name] : null;
150
    }
151
152
    /**
153
     * Clear dynamic properties.
154 1
     */
155
    public static function clearDynamicProperties()
156 1
    {
157 1
        static::$dynamicProperties[get_called_class()] = array();
158
    }
159
160
    /**
161
     * Clear dynamic methods.
162
     */
163
    public static function clearDynamicMethods()
164
    {
165
        static::$dynamicMethods[get_called_class()] = array();
166
    }
167
168
    /**
169
     * Remove a dynamic property.
170
     *
171
     * @param string $name
172
     *   The property name.
173
     */
174 4
    public static function removeDynamicProperty($name)
175
    {
176 4
        unset(static::$dynamicProperties[get_called_class()][$name]);
177 4
    }
178
179
    /**
180 4
     * Remove a dynamic method.
181 2
     *
182
     * @param string $name
183
     *   The method name.
184 4
     */
185
    public static function removeDynamicMethod($name)
186
    {
187
        unset(static::$dynamicMethods[get_called_class()][$name]);
188
    }
189
190
    /**
191
     * Execute a closure.
192
     *
193
     * @param \Closure $func
194 3
     *   The closure.
195
     * @param array $parameters
196 3
     *   The closure's parameters.
197 2
     * @param bool $memoize
198 2
     *   The memoize parameter.
199
     *
200
     * @return mixed|null
201 1
     *   The return of the closure.
202
     *
203
     * @throws \Psr\SimpleCache\InvalidArgumentException
204
     */
205
    public function doDynamicRequest(\Closure $func, array $parameters = [], $memoize = false)
206
    {
207 4
        if (!class_exists('\drupol\Memoize\Memoize') || false === $memoize) {
208
            $memoize = false;
209 4
        }
210 3
211
        if (true === $memoize) {
212 3
            return $this->memoize($func, $parameters);
213 3
        }
214 2
215
        return call_user_func_array($func, $parameters);
216
    }
217 3
218
    /**
219
     * @param $method
220 1
     * @param array $parameters
221
     *
222
     * @return mixed
223
     * @throws \Psr\SimpleCache\InvalidArgumentException
224
     */
225
    public function __call($method, array $parameters = array())
226 3
    {
227
        if (static::hasDynamicMethod($method)) {
228 3
            $data = static::getDynamicMethod($method);
229 1
            return $this->doDynamicRequest($data['factory'], $parameters, $data['memoize']);
230
        }
231 3
232
        throw new \BadMethodCallException(sprintf('Undefined method: %s().', $method));
233
    }
234
235
    /**
236
     * {inheritdoc}
237
     */
238
    public function __get($property)
239
    {
240
        if (static::hasDynamicProperty($property)) {
241
            $data = static::getDynamicProperty($property);
242
243
            $return = $data['factory'];
244
            if (is_callable($data['factory'])) {
245
                $return = $this->doDynamicRequest($data['factory'], [], $data['memoize']);
246
            }
247
248
            return $return;
249
        }
250
251
        throw new \DomainException(sprintf('Undefined property: %s.', $property));
252
    }
253
254
    /**
255
     * {inheritdoc}
256
     */
257
    public function __set($property, $value)
258
    {
259
        if (static::hasDynamicProperty($property)) {
260
            static::addDynamicProperty($property, $value);
261
        }
262
    }
263
}
264