Completed
Push — master ( 0b45c6...853a0b )
by Pol
01:19
created

DynamicObjectsTrait::__get()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 17
cts 17
cp 1
rs 8.439
c 0
b 0
f 0
cc 6
eloc 15
nc 7
nop 1
crap 6
1
<?php
2
3
namespace drupol\DynamicObjects;
4
5
/**
6
 * Trait DynamicObjectsTrait.
7
 *
8
 * @package drupol\DynamicObjects
9
 */
10
trait DynamicObjectsTrait
11
{
12
    /**
13
     * @var array
14
     */
15
    protected static $dynamicMethods = array();
16
17
    /**
18
     * @var array
19
     */
20
    protected static $dynamicProperties = array();
21
22
    /**
23
     * @var array
24
     */
25
    protected static $cache = array();
26
27
    /**
28
     * Add a dynamic property.
29
     *
30
     * @param string $name
31
     *   The property name.
32
     * @param mixed $value
33
     *   The property value.
34
     * @param bool $memoize
35
     *   Memoize parameter.
36
     */
37 5
    public static function addDynamicProperty($name, $value, $memoize = false)
38
    {
39 5
        static::$dynamicProperties[get_called_class()][$name] = [
40 5
          'name' => $name,
41 5
          'factory' => $value,
42 5
          'memoize' => $memoize,
43
        ];
44 5
    }
45
46
    /**
47
     * Add a dynamic method.
48
     *
49
     * @param $name
50
     *   The method name.
51
     * @param \Closure $func
52
     *   The method.
53
     * @param bool $memoize
54
     *   Memoize parameter.
55
     */
56 4
    public static function addDynamicMethod($name, \Closure $func, $memoize = false)
57
    {
58 4
        static::$dynamicMethods[get_called_class()][$name] = [
59 4
          'name' => $name,
60 4
          'factory' => $func,
61 4
          'memoize' => $memoize,
62
        ];
63 4
    }
64
65
    /**
66
     * Check if a dynamic property exists.
67
     *
68
     * @param string $name
69
     *   The property name.
70
     * @return bool
71
     *   True if the property exists, false otherwise.
72
     */
73 8
    public static function hasDynamicProperty($name)
74
    {
75 8
        return isset(static::$dynamicProperties[get_called_class()][$name]);
76
    }
77
78
    /**
79
     * Check if a dynamic method exists.
80
     *
81
     * @param string $name
82
     *   The property name.
83
     * @return bool
84
     *   True if the property exists, false otherwise.
85
     */
86 6
    public static function hasDynamicMethod($name)
87
    {
88 6
        return isset(static::$dynamicMethods[get_called_class()][$name]);
89
    }
90
91
    /**
92
     * Get a dynamic property.
93
     *
94
     * @param $name
95
     *   The property name.
96
     * @return mixed|null
97
     *   The property value if it exists, null otherwise.
98
     */
99 4
    public static function getDynamicProperty($name)
100
    {
101 4
        if (static::hasDynamicProperty($name)) {
102 3
            return static::$dynamicProperties[get_called_class()][$name];
103
        }
104
105 1
        return null;
106
    }
107
108
    /**
109
     * Get a dynamic method.
110
     *
111
     * @param $name
112
     *   The method name.
113
     * @return mixed|null
114
     *   The method if it exists, null otherwise.
115
     */
116 2
    public static function getDynamicMethod($name)
117
    {
118 2
        return ( static::hasDynamicMethod($name) ) ?
119 2
            static::$dynamicMethods[get_called_class()][$name] : null;
120
    }
121
122
    /**
123
     * Clear dynamic properties.
124
     */
125 1
    public static function clearDynamicProperties()
126
    {
127 1
        static::$dynamicProperties[get_called_class()] = array();
128 1
    }
129
130
    /**
131
     * Clear dynamic methods.
132
     */
133 1
    public static function clearDynamicMethods()
134
    {
135 1
        static::$dynamicMethods[get_called_class()] = array();
136 1
    }
137
138
    /**
139
     * Remove a dynamic property.
140
     *
141
     * @param string $name
142
     *   The property name.
143
     */
144 1
    public static function removeDynamicProperty($name)
145
    {
146 1
        unset(static::$dynamicProperties[get_called_class()][$name]);
147 1
    }
148
149
    /**
150
     * Remove a dynamic method.
151
     *
152
     * @param string $name
153
     *   The method name.
154
     */
155 1
    public static function removeDynamicMethod($name)
156
    {
157 1
        unset(static::$dynamicMethods[get_called_class()][$name]);
158 1
    }
159
160
    /**
161
     * {inheritdoc}
162
     */
163 3
    public function __call($method, array $parameters = array())
164
    {
165 3
        if (static::hasDynamicMethod($method)) {
166 2
            $data = static::getDynamicMethod($method);
167
168 2
            $func = $data['factory']->bindTo($this, $this);
169
170 2
            if (true === $data['memoize']) {
171 1
                $cacheid = sha1(serialize(func_get_args()));
172
173 1
                if (isset(static::$cache[$cacheid])) {
174 1
                    return static::$cache[$cacheid];
175
                }
176 1
            }
177
178 2
            $result = call_user_func_array($func, $parameters);
179
180 2
            if (true === $data['memoize']) {
181 1
                static::$cache[$cacheid] = $result;
0 ignored issues
show
Bug introduced by
The variable $cacheid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
182 1
            }
183
184 2
            return $result;
185
        }
186
187 1
        throw new \BadMethodCallException(sprintf('Undefined method: %s().', $method));
188
    }
189
190
    /**
191
     * {inheritdoc}
192
     */
193 3
    public function __set($property, $value)
194
    {
195 3
        if (static::hasDynamicProperty($property)) {
196 1
            static::addDynamicProperty($property, $value);
197 1
        }
198 3
    }
199
200
    /**
201
     * {inheritdoc}
202
     */
203 4
    public function __get($property)
204
    {
205 4
        if (static::hasDynamicProperty($property)) {
206 3
            $data = static::getDynamicProperty($property);
207
208 3
            if (is_callable($data['factory'])) {
209 2
                $func = $data['factory']->bindTo($this, $this);
210 2
                $cacheid = sha1(serialize(func_get_args()));
211
212 2
                if (true == $data['memoize']) {
213 1
                    if (isset(static::$cache[$cacheid])) {
214 1
                        return static::$cache[$cacheid];
215
                    }
216 1
                }
217
218 2
                $result = call_user_func($func);
219
220 2
                if (true == $data['memoize']) {
221 1
                    static::$cache[$cacheid] = $result;
222 1
                }
223
224 2
                return $result;
225
            }
226
227 1
            return $data['factory'];
228
        }
229
230 1
        throw new \DomainException(sprintf('Undefined property: %s().', $property));
231
    }
232
}
233