Completed
Push — master ( 653e9c...250e23 )
by Mariano
06:12
created

PropertyParser::createInstanceOfTypeFromValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4.125

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 12
ccs 4
cts 8
cp 0.5
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 4.125
1
<?php
2
/**
3
 * This file is part of php-simple-request.
4
 *
5
 * php-simple-request is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * php-simple-request is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with php-simple-request.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
namespace Mcustiel\SimpleRequest;
19
20
use Mcustiel\SimpleRequest\Interfaces\ValidatorInterface;
21
use Mcustiel\SimpleRequest\Interfaces\FilterInterface;
22
use Mcustiel\SimpleRequest\Exception\InvalidValueException;
23
use Mcustiel\SimpleRequest\Exception\InvalidAnnotationException;
24
25
/**
26
 * Utility class used to parse the value of a property.
27
 * It contains all filters and validators specified for the aforementioned property.
28
 *
29
 * @author mcustiel
30
 */
31
class PropertyParser
32
{
33
    /**
34
     *
35
     * @var \Mcustiel\SimpleRequest\Interfaces\ValidatorInterface[]
36
     */
37
    private $validators;
38
    /**
39
     *
40
     * @var \Mcustiel\SimpleRequest\Interfaces\FilterInterface[]
41
     */
42
    private $filters;
43
    /**
44
     *
45
     * @var string
46
     */
47
    private $name;
48
    /**
49
     *
50
     * @var string
51
     */
52
    private $type;
53
    /**
54
     *
55
     * @var RequestBuilder
56
     */
57
    private $requestBuilder;
58
59
    /**
60
     * Class constructor. Initialized with the property name.
61
     *
62
     * @param string $name
63
     */
64 86
    public function __construct($name, RequestBuilder $requestBuilder)
65
    {
66 86
        $this->validators = [];
67 86
        $this->filters = [];
68 86
        $this->type = null;
69 86
        $this->name = $name;
70 86
        $this->requestBuilder = $requestBuilder;
71 86
    }
72
73
    /**
74
     * Adds a validator to the parser.
75
     *
76
     * @param \Mcustiel\SimpleRequest\Interfaces\ValidatorInterface $validator
77
     */
78 85
    public function addValidator(ValidatorInterface $validator)
79
    {
80 85
        $this->validators[] = $validator;
81 85
    }
82
83
    /**
84
     * Adds a filter to the parser.
85
     *
86
     * @param \Mcustiel\SimpleRequest\Interfaces\FilterInterface $filter
87
     */
88 12
    public function addFilter(FilterInterface $filter)
89
    {
90 12
        $this->filters[] = $filter;
91 12
    }
92
93
    /**
94
     * Returns the name of the property.
95
     *
96
     * @return string
97
     */
98 88
    public function getName()
99
    {
100 88
        return $this->name;
101
    }
102
103
    /**
104
     *
105
     * @param string $type
106
     */
107 2
    public function setType($type)
108
    {
109 2
        $this->type = $type;
110 2
        return $this;
111
    }
112
113
    /**
114
     * Filters and validates a value. And return the filtered value.
115
     * It throws an exception if the value is not valid.
116
     *
117
     * @param mixed $value
118
     * @return mixed
119
     *
120
     * @throws \Mcustiel\SimpleRequest\Exception\InvalidValueException
121
     */
122 88
    public function parse($value)
123
    {
124 88
        $return = $this->cloneValue($value);
125 88
        if ($this->type !== null) {
126 2
            $return = $this->createInstanceOfTypeFromValue($return);
127 2
        }
128 88
        $return = $this->runFilters($return);
129 88
        $this->validate($return);
130
131 88
        return $return;
132
    }
133
134 88
    private function cloneValue($value)
135
    {
136 88
        if (is_object($value)) {
137 74
            return clone $value;
138
        }
139 88
        return $value;
140
    }
141
142
    /**
143
     * Checks the value against all validators.
144
     *
145
     * @param mixed $value
146
     *
147
     * @throws \Mcustiel\SimpleRequest\Exception\InvalidValueException
148
     */
149 88
    private function validate($value)
150
    {
151 88
        foreach ($this->validators as $validator) {
152 87
            if (!$validator->validate($value)) {
153 56
                throw new InvalidValueException(
154 56
                    "Field {$this->name}, was set with invalid value: " . var_export($value, true)
155 56
                );
156
            }
157 88
        }
158 88
    }
159
160
    /**
161
     * Run all the filters on the value.
162
     *
163
     * @param mixed $value
164
     *
165
     * @return mixed
166
     */
167 88
    private function runFilters($value)
168
    {
169 88
        $return = $value;
170 88
        if ($return !== null) {
171 88
            foreach ($this->filters as $filter) {
172 13
                $return = $filter->filter($return);
173 88
            }
174 88
        }
175
176 88
        return $return;
177
    }
178
179
    /**
180
     * Parses the value as it is an instance of the class specified in type property.
181
     *
182
     * @param array|\stdClass $value The value to parse and convert to an object
183
     *
184
     * @throws \Mcustiel\SimpleRequest\Exception\InvalidAnnotationException
185
     * @return object Parsed value as instance of class specified in type property
186
     */
187 2
    private function createInstanceOfTypeFromValue($value)
188
    {
189 2
        if ($value === null) {
190
            return null;
191
        }
192 2
        if (class_exists($this->type)) {
193 2
            return $this->requestBuilder->parseRequest($value, $this->type);
194
        }
195
        throw new InvalidAnnotationException(
196
            "Class {$this->type} does not exist. Annotated in property {$this->name}."
197
        );
198
    }
199
}
200