Completed
Push — master ( 9839a9...fa87a0 )
by Simone
02:55
created

MagicResource::properties()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 20
rs 8.8571
cc 5
eloc 10
nc 5
nop 0
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 RuntimeException;
15
use Sensorario\Resources\Validators\ResourcesValidator;
16
use Sensorario\Resources\Configurator;
17
18
abstract class MagicResource
19
{
20
    protected $properties = [];
21
22
    public function __call($functionName, $arguments)
23
    {
24
        $propertyName = strtolower($functionName);
25
26
        if ($this->hasProperty($propertyName)) {
27
            return $this->get($propertyName);
28
        }
29
30
        if (isset($this->defaults()[$propertyName])) {
0 ignored issues
show
Documentation Bug introduced by
The method defaults does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
31
            return $this->defaults()[$propertyName];
0 ignored issues
show
Documentation Bug introduced by
The method defaults does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
32
        }
33
34
        throw new RuntimeException(
35
            'Method `' . get_class($this)
36
            . '::' . $functionName 
37
            . '()` is not yet implemented'
38
        );
39
    }
40
41
    public function __construct(
42
        array $properties,
43
        ResourcesValidator $validator,
44
        Configurator $configuration = null
45
    ) {
46
        $this->properties = $properties;
47
48
        if ($configuration) {
49
            $this->applyConfiguration(
0 ignored issues
show
Documentation Bug introduced by
The method applyConfiguration does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
50
                $configuration
51
            );
52
        }
53
54
        foreach ($properties as $k => $v) {
55
            if ('object' === gettype($v) && !isset($this->rules()[$k])) {
0 ignored issues
show
Documentation Bug introduced by
The method rules does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
56
                throw new RuntimeException(
57
                    'When property `' . $k . '` is an object class, must be defined in Resources::rules()'.
58
                    ' but rules here are equals to ' . var_export($this->rules(), true)
0 ignored issues
show
Documentation Bug introduced by
The method rules does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
59
                    . ' And properties are ' . var_export($this->properties, true)
60
                );
61
            }
62
        }
63
64
        $validator->validate($this);
1 ignored issue
show
Compatibility introduced by
$this of type object<Sensorario\Resources\MagicResource> is not a sub-type of object<Sensorario\Resources\Resource>. It seems like you assume a child class of the class Sensorario\Resources\MagicResource to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
65
    }
66
67
    public static function __callStatic($methodName, array $args)
68
    {
69
        $methodWhiteList = [
70
            'box',
71
            'allowedValues'
72
        ];
73
74
        $isMethodAllowed = in_array(
75
            $methodName,
76
            $methodWhiteList
77
        );
78
79
        $properties = isset($args[0]) ? $args[0] : [];
80
        $configuration = null;
81
82
        if (
83
            isset($args[1])
84
            && 'Sensorario\Resources\Configurator' == get_class($args[1])
85
        ) {
86
            $configuration = new Configurator(
87
                $args[1]->resourceName(),
88
                $args[1]->container()
89
            );
90
        }
91
92
        if ($isMethodAllowed) {
93
            return new static(
94
                $properties,
95
                new ResourcesValidator(),
96
                $configuration
97
            );
98
        }
99
100
        throw new RuntimeException(
101
            'Invalid factory method `' . $methodName . '`'
102
        );
103
    }
104
105
    final public function hasProperty($propertyName)
106
    {
107
        return isset(
108
            $this->properties[$propertyName]
109
        );
110
    }
111
112
    final public function set($propertyName, $propertValue) 
113
    {
114
        $this->properties[$propertyName] = $propertValue;
115
    }
116
117
    final public function get($propertyName)
118
    {
119
        if ('' == $propertyName) {
120
            throw new RuntimeException(
121
                'Oops! Property name requested is empty string!!'
122
            );
123
        }
124
125
        if ($this->hasNotProperty($propertyName)) {
126
            if (isset($this->defaults()[$propertyName])) {
0 ignored issues
show
Documentation Bug introduced by
The method defaults does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
127
                return $this->defaults()[$propertyName];
0 ignored issues
show
Documentation Bug introduced by
The method defaults does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
128
            }
129
130
            throw new RuntimeException(
131
                'No value nor method `'
132
                . $propertyName
133
                . '` found in this resource'
134
            );
135
        }
136
137
        return $this->properties[$propertyName];
138
    }
139
140
    final public function hasNotProperty($propertyName)
141
    {
142
        return !$this->hasProperty($propertyName);
143
    }
144
145
    final public function hasProperties(array $properties)
146
    {
147
        foreach ($properties as $property) {
148
            if ($this->hasNotProperty($property)) {
149
                return false;
150
            }
151
        }
152
153
        return true;
154
    }
155
156
    final public function properties()
157
    {
158
        $properties = $this->properties;
159
160
        foreach ($properties as $k => $v) {
161
            if ('object' === gettype($v)) {
162
                if (!isset($this->rules()[$k]['object'])) {
0 ignored issues
show
Documentation Bug introduced by
The method rules does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
163
                    throw new RuntimeException(
164
                        'Property ' . $k . ' is an object but is not defined in rules'
165
                    );
166
                }
167
168
                if ($this->rules()[$k]['object'] === '\\Sensorario\\Resources\\Resource') {
0 ignored issues
show
Documentation Bug introduced by
The method rules does not exist on object<Sensorario\Resources\MagicResource>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
169
                    $properties[$k] = $v->properties();
170
                }
171
            }
172
        }
173
174
        return $properties;
175
    }
176
}
177