Completed
Pull Request — master (#133)
by Simone
02:00
created

MagicResource   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 98.67%

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 7
dl 0
loc 165
ccs 74
cts 75
cp 0.9867
rs 10
c 0
b 0
f 0

10 Methods

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