Completed
Push — master ( 2081ad...89b45c )
by Pol
01:11
created

DynamicObjectsTrait::__get()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

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