Completed
Push — v2 ( d5d6a3...7fc49e )
by Joschi
05:54
created

Item::validateProperty()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 21
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 9.3142
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * micrometa
5
 *
6
 * @category Jkphl
7
 * @package Jkphl\Micrometa
8
 * @subpackage Jkphl\Micrometa\Domain\Miom
9
 * @author Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright Copyright © 2017 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2017 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Jkphl\Micrometa\Domain\Item;
38
39
use Jkphl\Micrometa\Domain\Exceptions\InvalidArgumentException;
40
use Jkphl\Micrometa\Domain\Factory\IriFactory;
41
use Jkphl\Micrometa\Domain\Value\ValueInterface;
42
43
/**
44
 * Micro information item
45
 *
46
 * @package Jkphl\Micrometa
47
 * @subpackage Jkphl\Micrometa\Domain
48
 */
49
class Item implements ItemInterface
50
{
51
    /**
52
     * Item type(s)
53
     *
54
     * @var string[]
55
     */
56
    protected $type;
57
58
    /**
59
     * Item properties
60
     *
61
     * @var PropertyList
62
     */
63
    protected $properties;
64
65
    /**
66
     * Item ID
67
     *
68
     * @var string
69
     */
70
    protected $itemId;
71
72
    /**
73
     * Item constructor
74
     *
75
     * @param string|\stdClass|\stdClass[] $type Item type(s)
76
     * @param array[] $properties Item properties
77
     * @param string|null $itemId Item id
78
     */
79 27
    public function __construct($type, array $properties = [], $itemId = null)
80
    {
81 27
        $this->type = $this->validateTypes(is_array($type) ? $type : [$type]);
82 26
        $this->properties = $this->validateProperties($properties);
83 24
        $this->itemId = trim($itemId) ?: null;
84 24
    }
85
86
    /**
87
     * Validate and sanitize the item types
88
     *
89
     * @param \stdClass[] $types Item types
90
     * @return array Validated item types
91
     * @throws InvalidArgumentException If there are no valid types
92
     */
93 27
    protected function validateTypes(array $types)
94
    {
95 27
        $nonEmptyTypes = array_filter(array_map([$this, 'validateType'], $types));
96
97
        // If there are no valid types
98 26
        if (!count($nonEmptyTypes)) {
99
            throw new InvalidArgumentException(
100
                InvalidArgumentException::EMPTY_TYPES_STR,
101
                InvalidArgumentException::EMPTY_TYPES
102
            );
103
        }
104
105 26
        return array_values($nonEmptyTypes);
106
    }
107
108
    /**
109
     * Validate the item properties
110
     *
111
     * @param array $properties Item properties
112
     * @return PropertyList Validated item properties
113
     * @throws InvalidArgumentException If the property name is empty
114
     */
115 26
    protected function validateProperties(array $properties)
116
    {
117 26
        $validatedProperties = new PropertyList();
118
119
        // Run through all validated properties
120 26
        foreach (array_filter(array_map([$this, 'validateProperty'], $properties)) as $property) {
121 15
            $validatedProperties->add($property);
122
        }
123
124 24
        return $validatedProperties;
125
    }
126
127
    /**
128
     * Return the item types
129
     *
130
     * @return string[] Item types
131
     */
132 14
    public function getType()
133
    {
134 14
        return $this->type;
135
    }
136
137
    /**
138
     * Return the item ID (if any)
139
     *
140
     * @return string|null Item id
141
     */
142 12
    public function getId()
143
    {
144 12
        return $this->itemId;
145
    }
146
147
    /**
148
     * Return all item properties
149
     *
150
     * @return PropertyList Item properties list
151
     */
152 13
    public function getProperties()
153
    {
154 13
        return $this->properties;
155
    }
156
157
    /**
158
     * Return the values of a particular property
159
     *
160
     * @param string $name Property name
161
     * @param string|null $profile Property profile
162
     * @return array Item property values
163
     */
164 4
    public function getProperty($name, $profile = null)
165
    {
166 4
        $iri = IriFactory::create(($profile === null) ? $name : (object)['profile' => $profile, 'name' => $name]);
167 4
        return $this->properties->offsetGet($iri);
168
    }
169
170
    /**
171
     * Return whether the value should be considered empty
172
     *
173
     * @return boolean Value is empty
174
     */
175 9
    public function isEmpty()
176
    {
177 9
        return false;
178
    }
179
180
    /**
181
     * Validate a single property
182
     *
183
     * @param \stdClass $property Property
184
     * @return \stdClass Validated property
185
     */
186 17
    protected function validateProperty($property)
187
    {
188
        // Validate the property structure
189 17
        $this->validatePropertyStructure($property);
190
191
        // If the property has values
192 17
        if (count($property->values)) {
193
            // Validate the property name
194 17
            $property->name = $this->validatePropertyName($property);
195
196
            // Validate the property values
197 16
            $property->values = $this->validatePropertyValues($property->values);
198
199
            // If the property has significant values
200 15
            if (count($property->values)) {
201 15
                return $property;
202
            }
203
        }
204
205
        return null;
206
    }
207
208
    /**
209
     * Validate the structure of a property object
210
     *
211
     * @param \stdClass $property Property object
212
     * @throws InvalidArgumentException If the property object is invalid
213
     */
214 17
    protected function validatePropertyStructure($property)
215
    {
216
        // If the property object is invalid
217 17
        if (!is_object($property)
218 17
            || !isset($property->profile)
219 17
            || !isset($property->name)
220 17
            || !isset($property->values)
221 17
            || !is_array($property->values)
222
        ) {
223
            throw new InvalidArgumentException(
224
                InvalidArgumentException::INVALID_PROPERTY_STR,
225
                InvalidArgumentException::INVALID_PROPERTY
226
            );
227
        }
228 17
    }
229
230
    /**
231
     * Validate a property name
232
     *
233
     * @param \stdClass $property Property
234
     * @return string Property name
235
     */
236 17
    protected function validatePropertyName($property)
237
    {
238 17
        $propertyName = trim($property->name);
239
240
        // If the property name is empty
241 17
        if (!strlen($propertyName)) {
242 1
            throw new InvalidArgumentException(
243 1
                InvalidArgumentException::EMPTY_PROPERTY_NAME_STR,
244 1
                InvalidArgumentException::EMPTY_PROPERTY_NAME
245
            );
246
        }
247
248 16
        return $propertyName;
249
    }
250
251
    /**
252
     * Validate a list of property values
253
     *
254
     * @param array $values Property values
255
     * @return array Validated property values
256
     * @throws InvalidArgumentException If the value is not a nested item
257
     */
258 16
    protected function validatePropertyValues(array $values)
259
    {
260 16
        $nonEmptyPropertyValues = [];
261
262
        // Run through all property values
263
        /** @var ValueInterface $value */
264 16
        foreach ($values as $value) {
265
            // If the value is not a nested item
266 16
            if (!($value instanceof ValueInterface)) {
267 1
                throw new InvalidArgumentException(
268 1
                    sprintf(InvalidArgumentException::INVALID_PROPERTY_VALUE_STR, gettype($value)),
269 1
                    InvalidArgumentException::INVALID_PROPERTY_VALUE
270
                );
271
            }
272
273 15
            if (!$value->isEmpty()) {
274 15
                $nonEmptyPropertyValues[] = $value;
275
            }
276
        }
277
278 15
        return $nonEmptyPropertyValues;
279
    }
280
281
    /**
282
     * Validate a single item type
283
     *
284
     * @param \stdClass|string $type Item type
285
     * @return \stdClass|null Validated item type
286
     * @throws InvalidArgumentException If the item type object is invalid
287
     */
288 27
    protected function validateType($type)
289
    {
290 27
        $type = IriFactory::create($type);
291 26
        return strlen($type->name) ? $type : null;
292
    }
293
}
294