Completed
Push — master ( bde6a9...31142b )
by Simone
02:25
created

MagicResource::__construct()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 30
rs 8.439
cc 6
eloc 19
nc 10
nop 5
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\Container;
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
        $validationRequired = true,
45
        Container $container = null,
46
        $resourceName = null
47
    ) {
48
        $this->properties = $properties;
49
50
        if ($container) {
51
            $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...
52
                $resourceName,
53
                $container
54
            );
55
        }
56
57
        foreach ($properties as $k => $v) {
58
            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...
59
                throw new RuntimeException(
60
                    'When property `' . $k . '` is an object class, must be defined in Resources::rules()'.
61
                    ' 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...
62
                    . ' And properties are ' . var_export($this->properties, true)
63
                );
64
            }
65
        }
66
67
        if ($validationRequired) {
68
            $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...
69
        }
70
    }
71
72
    public static function __callStatic($methodName, array $args)
73
    {
74
        $methodWhiteList = [
75
            'box',
76
            'allowedValues'
77
        ];
78
79
        $isMethodAllowed = in_array(
80
            $methodName,
81
            $methodWhiteList
82
        );
83
84
        $properties = isset($args[0]) ? $args[0] : [];
85
        $container = null;
86
        $resourceName = null;
87
88
        if (
89
            isset($args[1])
90
            && 'Sensorario\Resources\Container' == get_class($args[1])
91
        ) {
92
            $container = $args[1];
93
            $resourceName = $args[2];
94
        }
95
96
        if ($isMethodAllowed) {
97
            return new static(
98
                $properties,
99
                new ResourcesValidator(),
100
                $validationRequired = true,
101
                $container,
102
                $resourceName
103
            );
104
        }
105
106
        throw new RuntimeException(
107
            'Invalid factory method `' . $methodName . '`'
108
        );
109
    }
110
111
    final public function hasProperty($propertyName)
112
    {
113
        return isset(
114
            $this->properties[$propertyName]
115
        );
116
    }
117
118
    final public function get($propertyName)
119
    {
120
        if ('' == $propertyName) {
121
            throw new RuntimeException(
122
                'Oops! Property name requested is empty string!!'
123
            );
124
        }
125
126
        if ($this->hasNotProperty($propertyName)) {
127
            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...
128
                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...
129
            }
130
131
            throw new RuntimeException(
132
                'No value nor method `'
133
                . $propertyName
134
                . '` found in this resource'
135
            );
136
        }
137
138
        return $this->properties[$propertyName];
139
    }
140
141
    final public function hasNotProperty($propertyName)
142
    {
143
        return !$this->hasProperty($propertyName);
144
    }
145
146
    final public function hasProperties(array $properties)
147
    {
148
        foreach ($properties as $property) {
149
            if ($this->hasNotProperty($property)) {
150
                return false;
151
            }
152
        }
153
154
        return true;
155
    }
156
157
    final public function properties()
158
    {
159
        $properties = $this->properties;
160
161
        foreach ($properties as $k => $v) {
162
            if ('object' === gettype($v)) {
163
                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...
164
                    $properties[$k] = $v->properties();
165
                }
166
            }
167
        }
168
169
        return $properties;
170
    }
171
}
172