Completed
Push — v2 ( 7fc49e...7442ee )
by Joschi
04:33
created

Item::validatePropertyStructure()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 9
nc 2
nop 1
dl 0
loc 15
ccs 10
cts 10
cp 1
crap 6
rs 8.8571
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\AliasFactory;
41
use Jkphl\Micrometa\Domain\Factory\AliasFactoryInterface;
42
use Jkphl\Micrometa\Domain\Factory\IriFactory;
43
use Jkphl\Micrometa\Domain\Value\ValueInterface;
44
45
/**
46
 * Micro information item
47
 *
48
 * @package Jkphl\Micrometa
49
 * @subpackage Jkphl\Micrometa\Domain
50
 */
51
class Item implements ItemInterface
52
{
53
    /**
54
     * Item type(s)
55
     *
56
     * @var string[]
57
     */
58
    protected $type;
59
60
    /**
61
     * Item properties
62
     *
63
     * @var PropertyList
64
     */
65
    protected $properties;
66
67
    /**
68
     * Item ID
69
     *
70
     * @var string
71
     */
72
    protected $itemId;
73
74
    /**
75
     * Alias factory
76
     *
77
     * @var AliasFactoryInterface
78
     */
79
    protected $aliasFactory;
80
81
    /**
82
     * Item constructor
83
     *
84
     * @param string|\stdClass|\stdClass[] $type Item type(s)
85
     * @param array[] $properties Item properties
86
     * @param string|null $itemId Item id
87
     * @param AliasFactoryInterface $aliasFactory Alias factory
88
     */
89 31
    public function __construct(
90
        $type,
91
        array $properties = [],
92
        $itemId = null,
93
        AliasFactoryInterface $aliasFactory = null
94
    ) {
95 31
        $this->aliasFactory = $aliasFactory ?: new AliasFactory();
96 31
        $this->type = $this->validateTypes(is_array($type) ? $type : [$type]);
97 29
        $this->properties = $this->validateProperties($properties);
98 26
        $this->itemId = trim($itemId) ?: null;
99 26
    }
100
101
    /**
102
     * Validate and sanitize the item types
103
     *
104
     * @param \stdClass[] $types Item types
105
     * @return array Validated item types
106
     * @throws InvalidArgumentException If there are no valid types
107
     */
108 31
    protected function validateTypes(array $types)
109
    {
110 31
        $nonEmptyTypes = array_filter(array_map([$this, 'validateType'], $types));
111
112
        // If there are no valid types
113 30
        if (!count($nonEmptyTypes)) {
114 1
            throw new InvalidArgumentException(
115 1
                InvalidArgumentException::EMPTY_TYPES_STR,
116 1
                InvalidArgumentException::EMPTY_TYPES
117
            );
118
        }
119
120 29
        return array_values($nonEmptyTypes);
121
    }
122
123
    /**
124
     * Validate the item properties
125
     *
126
     * @param array $properties Item properties
127
     * @return PropertyList Validated item properties
128
     * @throws InvalidArgumentException If the property name is empty
129
     */
130 29
    protected function validateProperties(array $properties)
131
    {
132 29
        $validatedProperties = new PropertyList($this->aliasFactory);
133
134
        // Run through all validated properties
135 29
        foreach (array_filter(array_map([$this, 'validateProperty'], $properties)) as $property) {
136 15
            $validatedProperties->add($property);
137
        }
138
139 26
        return $validatedProperties;
140
    }
141
142
    /**
143
     * Return the item types
144
     *
145
     * @return string[] Item types
146
     */
147 16
    public function getType()
148
    {
149 16
        return $this->type;
150
    }
151
152
    /**
153
     * Return the item ID (if any)
154
     *
155
     * @return string|null Item id
156
     */
157 14
    public function getId()
158
    {
159 14
        return $this->itemId;
160
    }
161
162
    /**
163
     * Return all item properties
164
     *
165
     * @return PropertyList Item properties list
166
     */
167 15
    public function getProperties()
168
    {
169 15
        return $this->properties;
170
    }
171
172
    /**
173
     * Return the values of a particular property
174
     *
175
     * @param string $name Property name
176
     * @param string|null $profile Property profile
177
     * @return array Item property values
178
     */
179 4
    public function getProperty($name, $profile = null)
180
    {
181 4
        $iri = IriFactory::create(($profile === null) ? $name : (object)['profile' => $profile, 'name' => $name]);
182 4
        return $this->properties->offsetGet($iri);
183
    }
184
185
    /**
186
     * Return whether the value should be considered empty
187
     *
188
     * @return boolean Value is empty
189
     */
190 9
    public function isEmpty()
191
    {
192 9
        return false;
193
    }
194
195
    /**
196
     * Validate a single property
197
     *
198
     * @param \stdClass $property Property
199
     * @return \stdClass Validated property
200
     */
201 20
    protected function validateProperty($property)
202
    {
203
        // Validate the property structure
204 20
        $this->validatePropertyStructure($property);
205
206
        // If the property has values
207 19
        if (count($property->values)) {
208
            // Validate the property name
209 18
            $property->name = $this->validatePropertyName($property);
210
211
            // Validate the property values
212 17
            $property->values = $this->validatePropertyValues($property->values);
213
214
            // If the property has significant values
215 16
            if (count($property->values)) {
216 15
                return $property;
217
            }
218
        }
219
220 2
        return null;
221
    }
222
223
    /**
224
     * Validate the structure of a property object
225
     *
226
     * @param \stdClass $property Property object
227
     * @throws InvalidArgumentException If the property object is invalid
228
     */
229 20
    protected function validatePropertyStructure($property)
230
    {
231
        // If the property object is invalid
232 20
        if (!is_object($property)
233 20
            || !isset($property->profile)
234 19
            || !isset($property->name)
235 19
            || !isset($property->values)
236 20
            || !is_array($property->values)
237
        ) {
238 1
            throw new InvalidArgumentException(
239 1
                InvalidArgumentException::INVALID_PROPERTY_STR,
240 1
                InvalidArgumentException::INVALID_PROPERTY
241
            );
242
        }
243 19
    }
244
245
    /**
246
     * Validate a property name
247
     *
248
     * @param \stdClass $property Property
249
     * @return string Property name
250
     */
251 18
    protected function validatePropertyName($property)
252
    {
253 18
        $propertyName = trim($property->name);
254
255
        // If the property name is empty
256 18
        if (!strlen($propertyName)) {
257 1
            throw new InvalidArgumentException(
258 1
                InvalidArgumentException::EMPTY_PROPERTY_NAME_STR,
259 1
                InvalidArgumentException::EMPTY_PROPERTY_NAME
260
            );
261
        }
262
263 17
        return $propertyName;
264
    }
265
266
    /**
267
     * Validate a list of property values
268
     *
269
     * @param array $values Property values
270
     * @return array Validated property values
271
     * @throws InvalidArgumentException If the value is not a nested item
272
     */
273 17
    protected function validatePropertyValues(array $values)
274
    {
275 17
        $nonEmptyPropertyValues = [];
276
277
        // Run through all property values
278
        /** @var ValueInterface $value */
279 17
        foreach ($values as $value) {
280
            // If the value is not a nested item
281 17
            if (!($value instanceof ValueInterface)) {
282 1
                throw new InvalidArgumentException(
283 1
                    sprintf(InvalidArgumentException::INVALID_PROPERTY_VALUE_STR, gettype($value)),
284 1
                    InvalidArgumentException::INVALID_PROPERTY_VALUE
285
                );
286
            }
287
288 16
            if (!$value->isEmpty()) {
289 16
                $nonEmptyPropertyValues[] = $value;
290
            }
291
        }
292
293 16
        return $nonEmptyPropertyValues;
294
    }
295
296
    /**
297
     * Validate a single item type
298
     *
299
     * @param \stdClass|string $type Item type
300
     * @return \stdClass|null Validated item type
301
     * @throws InvalidArgumentException If the item type object is invalid
302
     */
303 31
    protected function validateType($type)
304
    {
305 31
        $type = IriFactory::create($type);
306 30
        return strlen($type->name) ? $type : null;
307
    }
308
}
309