Completed
Push — master ( 57eaae...d53a99 )
by Simone
03:18 queued 01:22
created

MagicResource::properties()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6.0208

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 11
cts 12
cp 0.9167
rs 8.5125
c 0
b 0
f 0
cc 6
eloc 12
nc 7
nop 0
crap 6.0208
1
<?php
2
3
/**
4
 * This file is part of sensorario/resources repository
5
 *
6
 * (c) Simone Gentili <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sensorario\Resources;
13
14
use Sensorario\Resources\Configurator;
15
use Sensorario\Resources\Validators\ResourcesValidator;
16
17
/**
18
 * @method array defaults() returns resource's default values
19
 * @method array rules() returns resource's rules
20
 */
21
abstract class MagicResource
22
{
23
    protected $properties = [];
24
25
    private static $methodWhiteList = [
26
        'box',
27
        'allowedValues'
28
    ];
29
30 3
    public function __call($functionName, $arguments)
31
    {
32 3
        $propertyName = strtolower($functionName);
33
34 3
        if ($this->hasProperty($propertyName)) {
35 1
            return $this->get($propertyName);
36
        }
37
38 2
        if (isset($this->defaults()[$propertyName])) {
39 1
            return $this->defaults()[$propertyName];
40
        }
41
42 1
        throw new \Sensorario\Resources\Exceptions\UndefinedMethodException(
43 1
            'Method `' . get_class($this)
44 1
            . '::' . $functionName 
45 1
            . '()` is not yet implemented'
46
        );
47
    }
48
49
    abstract public function applyConfiguration(Configurator $configurator);
50
51 39
    public function __construct(
52
        array $properties,
53
        ResourcesValidator $validator,
54
        Configurator $configuration = null
55
    ) {
56 39
        $this->properties = $properties;
57
58 39
        if ($configuration) {
59 21
            $this->applyConfiguration(
60 21
                $configuration
61
            );
62
        }
63
64 39
        foreach ($properties as $k => $v) {
65 31
            if ('object' === gettype($v) && !isset($this->rules()[$k])) {
66 1
                throw new \Sensorario\Resources\Exceptions\PropertyWithoutRuleException(
67 1
                    'When property `' . $k . '` is an object class, must be defined in Resources::rules()' .
68 1
                    ' but rules here are equals to ' . var_export($this->rules(), true)
69 1
                    . ' And properties are ' . var_export($this->properties, true)
70
                );
71
            }
72
        }
73
74 38
        $validator->validate($this);
75 24
    }
76
77 39
    public static function __callStatic($methodName, array $args)
78
    {
79 39
        $isMethodAllowed = in_array(
80 39
            $methodName,
81 39
            self::$methodWhiteList
82
        );
83
84 39
        $configuration = null;
85
86
        if (
87 39
            isset($args[1])
88 22
            && 'Sensorario\Resources\Configurator' == get_class($args[1])
89
        ) {
90 21
            $configuration = new Configurator(
91 21
                $args[1]->resourceName(),
92 21
                $args[1]->container()
93
            );
94
        }
95
96 39
        if ($isMethodAllowed) {
97 38
            return new static(
98 38
                $args[0] ?? [],
99 38
                new ResourcesValidator(),
100 38
                $configuration
101
            );
102
        }
103
104 1
        throw new \Sensorario\Resources\Exceptions\FactoryMethodException(
105
            'Invalid factory method '
106 1
            . '`' . $methodName . '`'
107
        );
108
    }
109
110 31
    final public function hasProperty($propertyName)
111
    {
112
        return isset(
113 31
            $this->properties[$propertyName]
114
        );
115
    }
116
117 1
    final public function set($propertyName, $propertValue) 
118
    {
119 1
        $this->properties[$propertyName] = $propertValue;
120 1
    }
121
122 24
    final public function get($propertyName)
123
    {
124 24
        if ('' == $propertyName) {
125 1
            throw new \Sensorario\Resources\Exceptions\PropertyNameEmptyException(
126 1
                'Oops! Property name requested is empty string!!'
127
            );
128
        }
129
130 23
        if ($this->hasNotProperty($propertyName)) {
131 3
            if ($prop = $this->defaults()[$propertyName] ?? false) {
132 2
                return $prop;
133
            }
134
135 1
            throw new \Sensorario\Resources\Exceptions\NoValuesException(
136
                'No value nor method `'
137 1
                . $propertyName
138 1
                . '` found in this resource'
139
            );
140
        }
141
142 20
        return $this->properties[$propertyName];
143
    }
144
145 29
    final public function hasNotProperty($propertyName)
146
    {
147 29
        return !$this->hasProperty($propertyName);
148
    }
149
150 2
    final public function hasProperties(array $properties)
151
    {
152 2
        foreach ($properties as $property) {
153 2
            if ($this->hasNotProperty($property)) {
154 1
                return false;
155
            }
156
        }
157
158 1
        return true;
159
    }
160
161 38
    final public function properties()
162
    {
163 38
        $properties = $this->properties;
164
165 38
        foreach ($properties as $k => $v) {
166 30
            if ('object' === gettype($v)) {
167 5
                if (!isset($this->rules()[$k]['object'])) {
168 1
                    throw new \Sensorario\Resources\Exceptions\PropertyWithoutRuleException(
169 1
                        'Property ' . $k . ' is an object but is not defined in rules'
170
                    );
171
                }
172
173 4
                if ($this->rules()[$k]['object'] === '\\Sensorario\\Resources\\Resource') {
174 1
                    $properties[$k] = $v->properties();
175
                }
176
177 4
                if ($this->rules()[$k]['object'] === 'array') {
178
                    $properties[$k] = (array) $v;
179
                }
180
            }
181
        }
182
183 37
        return $properties;
184
    }
185
}
186