Completed
Push — v2 ( eb3e88...e6a17b )
by Joschi
07:34
created

Item::getValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * micrometa
5
 *
6
 * @category Jkphl
7
 * @package Jkphl\Micrometa
8
 * @subpackage Jkphl\Micrometa\Ports
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\Ports\Item;
38
39
use Jkphl\Micrometa\Application\Contract\ValueInterface;
40
use Jkphl\Micrometa\Application\Factory\AliasFactory;
41
use Jkphl\Micrometa\Application\Item\ItemInterface as ApplicationItemInterface;
42
use Jkphl\Micrometa\Application\Item\PropertyListInterface;
43
use Jkphl\Micrometa\Domain\Exceptions\OutOfBoundsException as DomainOutOfBoundsException;
44
use Jkphl\Micrometa\Infrastructure\Factory\ItemFactory;
45
use Jkphl\Micrometa\Infrastructure\Factory\ProfiledNamesFactory;
46
use Jkphl\Micrometa\Infrastructure\Parser\ProfiledNamesList;
47
use Jkphl\Micrometa\Ports\Exceptions\InvalidArgumentException;
48
use Jkphl\Micrometa\Ports\Exceptions\OutOfBoundsException;
49
50
/**
51
 * Micro information item
52
 *
53
 * @package Jkphl\Micrometa
54
 * @subpackage Jkphl\Micrometa\Ports
55
 */
56
class Item extends ItemList implements ItemInterface
57
{
58
    /**
59
     * Application item
60
     *
61
     * @var ApplicationItemInterface
62
     */
63
    protected $item;
64
65
    /**
66
     * Item constructor
67
     *
68
     * @param ApplicationItemInterface $item Application item
69
     */
70 13
    public function __construct(ApplicationItemInterface $item)
71
    {
72 13
        $this->item = $item;
73 13
        parent::__construct(ItemFactory::createFromApplicationItems($this->item->getChildren()));
74 13
    }
75
76
    /**
77
     * Get the first value of an item property
78
     *
79
     * @param string $name Item property name
80
     * @return array|string|ItemInterface First value of an item property
81
     * @api
82
     */
83 2
    public function __get($name)
84
    {
85 2
        return $this->getProperty($name, null, 0);
86
    }
87
88
    /**
89
     * Get a single property (value)
90
     *
91
     * @param string $name Property name
92
     * @param string $profile Property profile
93
     * @param int $index Property value index
94
     * @return array|string|ItemInterface Property value(s)
95
     * @throws OutOfBoundsException If the property name is unknown
96
     * @throws OutOfBoundsException If the property value index is out of bounds
97
     * @api
98
     */
99 7
    public function getProperty($name, $profile = null, $index = null)
100
    {
101
        try {
102 7
            $propertyValues = $this->item->getProperty($name, $profile);
103 4
        } catch (DomainOutOfBoundsException $e) {
104 4
            throw new OutOfBoundsException($e->getMessage(), $e->getCode());
105
        }
106
107
        // If all property values should be returned
108 7
        if ($index === null) {
109 5
            return array_map([$this, 'exportPropertyValue'], $propertyValues);
110
        }
111
112
        // If the property value index is out of bounds
113 6
        if (!isset($propertyValues[$index])) {
114 1
            throw new OutOfBoundsException(
115 1
                sprintf(OutOfBoundsException::INVALID_PROPERTY_VALUE_INDEX_STR, $index),
116 1
                OutOfBoundsException::INVALID_PROPERTY_VALUE_INDEX
117
            );
118
        }
119
120 5
        return $this->exportPropertyValue($propertyValues[$index]);
121
    }
122
123
    /**
124
     * Prepare a property value for returning it
125
     *
126
     * @param ValueInterface $value Property value
127
     * @return Item|mixed Returnable property value
128
     */
129 6
    protected function exportPropertyValue(ValueInterface $value)
130
    {
131 6
        return ($value instanceof ApplicationItemInterface) ?
132 6
            ItemFactory::createFromApplicationItem($value) : $value->export();
133
    }
134
135
    /**
136
     * Return whether the item is of a particular type (or contained in a list of types)
137
     *
138
     * The item type(s) can be specified in a variety of ways, @see ProfiledNamesFactory::createFromArguments()
139
     *
140
     * @param array ...$types Item types
141
     * @return boolean Item type is contained in the list of types
142
     * @api
143
     */
144 5
    public function isOfType(...$types)
145
    {
146
        /** @var ProfiledNamesList $profiledTypes */
147 5
        $profiledTypes = ProfiledNamesFactory::createFromArguments($types);
148 5
        $aliasFactory = new AliasFactory();
149
150
        // Run through all item types
151
        /** @var \stdClass $itemType */
152 5
        foreach ($this->item->getType() as $itemType) {
153 5
            $itemTypeNames = $aliasFactory->createAliases($itemType->name);
154 5
            if ($this->isOfProfiledTypes($itemType->profile, $itemTypeNames, $profiledTypes)) {
155 5
                return true;
156
            }
157
        }
158
159 3
        return false;
160
    }
161
162
    /**
163
     * Return whether an aliased item type in contained in a set of query types
164
     *
165
     * @param string $profile Type profile
166
     * @param array $names Aliased type names
167
     * @param ProfiledNamesList $types Query types
168
     * @return bool Item type is contained in the set of query types
169
     */
170 5
    protected function isOfProfiledTypes($profile, array $names, ProfiledNamesList $types)
171
    {
172
        // Run through all query types
173
        /** @var \stdClass $queryType */
174 5
        foreach ($types as $queryType) {
175 5
            if (in_array($queryType->name, $names) &&
176 5
                (($queryType->profile === null) ? true : ($queryType->profile == $profile))
177
            ) {
178 5
                return true;
179
            }
180
        }
181 3
        return false;
182
    }
183
184
    /**
185
     * Get all values of the first available property in a stack
186
     *
187
     * The property stack can be specified in a variety of ways, @see ProfiledNamesFactory::createFromArguments()
188
     *
189
     * @param string $name Name
190
     * @param string $profile Profile
191
     * @return array|string|ItemInterface Property values
192
     * @throws InvalidArgumentException If no property name was given
193
     * @throws OutOfBoundsException If none of the requested properties is known
194
     * @api
195
     */
196 2
    public function getFirstProperty($name, $profile = null)
197
    {
198
        /** @var ProfiledNamesList $properties */
199 2
        $properties = ProfiledNamesFactory::createFromArguments(func_get_args());
200
201
        // Prepare a default exception
202 2
        $e = new OutOfBoundsException(
203 2
            OutOfBoundsException::NO_MATCHING_PROPERTIES_STR,
204 2
            OutOfBoundsException::NO_MATCHING_PROPERTIES
205
        );
206
207
        // Run through all properties
208 2
        foreach ($properties as $property) {
209
            try {
210 2
                return $this->getProperty($property->name, $property->profile);
211 1
            } catch (OutOfBoundsException $e) {
212 1
                continue;
213
            }
214
        }
215
216 1
        throw $e;
217
    }
218
219
    /**
220
     * Return all properties
221
     *
222
     * @return PropertyListInterface Properties
223
     * @api
224
     */
225 1
    public function getProperties()
226
    {
227 1
        return $this->item->getProperties();
228
//        return $this->item->getProperties()->export();
229
    }
230
231
    /**
232
     * Return an object representation of the item
233
     *
234
     * @return \stdClass Micro information item
235
     * @api
236
     */
237 2
    public function toObject()
238
    {
239 2
        return $this->item->export();
240
    }
241
242
    /**
243
     * Get the item type
244
     *
245
     * @return \stdClass[] Item type
246
     */
247 1
    public function getType()
248
    {
249 1
        return $this->item->getType();
250
    }
251
252
    /**
253
     * Get the item format
254
     *
255
     * @return int Item format
256
     */
257 1
    public function getFormat()
258
    {
259 1
        return $this->item->getFormat();
260
    }
261
262
    /**
263
     * Get the item ID
264
     *
265
     * @return string Item ID
266
     */
267
    public function getId()
268
    {
269
        return $this->item->getId();
270
    }
271
272
    /**
273
     * Return the item value
274
     *
275
     * @return string Item value
276
     */
277
    public function getValue()
278
    {
279
        return $this->item->getValue();
280
    }
281
}
282