Completed
Push — master ( 755174...9d7326 )
by Joschi
10:05
created

ApparatObjectTrait   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 295
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 97.53%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 295
ccs 79
cts 81
cp 0.9753
rs 10
wmc 28
lcom 1
cbo 3

19 Methods

Rating   Name   Duplication   Size   Complexity  
A delegateObjectGetter() 0 20 4
A offsetExists() 0 4 1
A offsetGet() 0 15 2
A offsetSet() 0 7 1
A offsetUnset() 0 7 1
A append() 0 7 1
A count() 0 4 1
A asort() 0 4 1
A ksort() 0 4 1
A uasort() 0 7 2
A uksort() 0 7 2
A natsort() 0 4 1
A natcasesort() 0 4 1
A unserialize() 0 5 1
A exchangeArray() 0 14 2
A serialize() 0 4 1
A getIterator() 0 4 1
A __call() 0 15 3
A getArrayCopy() 0 13 1
1
<?php
2
3
/**
4
 * apparat/object
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Object
8
 * @subpackage  Apparat\Object\Infrastructure
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 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 © 2016 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 Apparat\Object\Infrastructure\Model\Object\Apparat\Traits;
38
39
use Apparat\Kernel\Tests\Kernel;
40
use Apparat\Object\Application\Model\Object\ApplicationObjectInterface;
41
use Apparat\Object\Domain\Model\Object\ObjectInterface;
42
use Apparat\Object\Domain\Model\Properties\InvalidArgumentException as PropertyInvalidArgumentException;
43
use Apparat\Object\Infrastructure\Model\Object\Apparat\AbstractApparatObject;
44
use Apparat\Object\Infrastructure\Model\Object\Apparat\ApparatObjectIterator;
45
use Apparat\Object\Infrastructure\Model\Object\Object;
46
use Apparat\Object\Ports\Exceptions\InvalidArgumentException;
47
48
/**
49
 * Apparat object trait
50
 *
51
 * @package Apparat\Object
52
 * @subpackage Apparat\Object\Infrastructure
53
 * @property ApplicationObjectInterface $object
54
 * @method string getIteratorClass() Gets the iterator class name for the ArrayObject
55
 * @method int getFlags() Gets the behavior flags
56
 */
57
trait ApparatObjectTrait
58
{
59
    /**
60
     * Property mapping
61
     *
62
     * @var array
63
     */
64
    protected $mapping = [];
65
66
    /**
67
     * Generic getter
68
     *
69
     * @param string $method Method name
70
     * @param array $arguments Arguments
71
     * @return mixed Object property value
72
     * @throws \BadMethodCallException If the method is unknown
73
     */
74 2
    public function __call($method, array $arguments)
75
    {
76
        // If a getter was called
77 2
        if (!strncmp('get', $method, 3)) {
78 2
            $property = lcfirst(substr($method, 3));
79 2
            if (array_key_exists($property, $this->mapping)) {
80 1
                $arguments = (array)$this->mapping[$property];
81 1
                $getter = 'get'.ucfirst(array_shift($arguments));
82 1
                return $this->delegateObjectGetter($property, $getter, $arguments);
83
            }
84
        }
85
86
        // If the method is unknown
87 1
        throw new \BadMethodCallException(sprintf('Unknown apparat object method "%s()"', $method));
88
    }
89
90
    /**
91
     * Delegate the mapped object getter
92
     *
93
     * @param string $property Property name
94
     * @param string $getter Getter name
95
     * @param array $arguments Getter arguments
96
     * @return mixed Property value
97
     * @throws InvalidArgumentException If the property is invalid
98
     */
99 3
    protected function delegateObjectGetter($property, $getter, array $arguments)
100
    {
101
        // If the apparat object itself has the requested getter
102 3
        if ((new \ReflectionClass(static::class))->hasMethod($getter)) {
103 2
            return $this->$getter(...$arguments);
104
        }
105
106
        // If the property is invalid
107 3
        if (!is_callable([$this->object, $getter])) {
108 1
            throw new InvalidArgumentException(
109 1
                sprintf('Invalid apparat object property "%s"', $property),
110 1
                InvalidArgumentException::INVALID_APPARAT_OBJECT_PROPERTY
111
            );
112
        }
113
        try {
114 2
            return $this->object->$getter(...$arguments);
115 1
        } catch (PropertyInvalidArgumentException $e) {
116 1
            return null;
117
        }
118
    }
119
120
    /**
121
     * Return whether a particular property exists
122
     *
123
     * @param string $offset Property name
124
     * @return boolean Property exists
125
     */
126 1
    public function offsetExists($offset)
127
    {
128 1
        return array_key_exists($offset, $this->mapping);
129
    }
130
131
    /**
132
     * Return a particular property
133
     *
134
     * @param string $offset Property name
135
     * @return mixed Property value
136
     * @throws InvalidArgumentException If the requested property is invalid
137
     */
138 4
    public function offsetGet($offset)
139
    {
140
        // If a known object property has been requested
141 4
        if (array_key_exists($offset, $this->mapping)) {
142 3
            $arguments = (array)$this->mapping[$offset];
143 3
            $property = array_shift($arguments);
144 3
            $getter = 'get'.ucfirst($property);
145 3
            return $this->delegateObjectGetter($property, $getter, $arguments);
146
        }
147
148 1
        throw new InvalidArgumentException(
149 1
            sprintf('Invalid apparat object property "%s"', $offset),
150 1
            InvalidArgumentException::INVALID_APPARAT_OBJECT_PROPERTY
151
        );
152
    }
153
154
    /**
155
     * Set a particular property
156
     *
157
     * @param string $offset Property name
158
     * @param mixed $value Property value
159
     * @throws InvalidArgumentException
160
     */
161 1
    public function offsetSet($offset, $value)
162
    {
163 1
        throw new InvalidArgumentException(
164 1
            sprintf('Cannot set apparat object property "%s" to value "%s"', $offset, $value),
165 1
            InvalidArgumentException::CANNOT_SET_APPARAT_OBJECT_PROPERTY
166
        );
167
    }
168
169
    /**
170
     * Unset a particular property
171
     *
172
     * @param string $offset Property name
173
     * @throws InvalidArgumentException
174
     */
175 1
    public function offsetUnset($offset)
176
    {
177 1
        throw new InvalidArgumentException(
178 1
            sprintf('Cannot unset apparat object property "%s"', $offset),
179 1
            InvalidArgumentException::CANNOT_UNSET_APPARAT_OBJECT_PROPERTY
180
        );
181
    }
182
183
    /**
184
     * Append a value
185
     *
186
     * @param mixed $value Value
187
     * @throws InvalidArgumentException
188
     */
189 1
    public function append($value)
190
    {
191 1
        throw new InvalidArgumentException(
192 1
            sprintf('Cannot append apparat object value "%s"', $value),
193 1
            InvalidArgumentException::CANNOT_APPEND_APPARAT_OBJECT_VALUE
194
        );
195
    }
196
197
    /**
198
     * Return an array copy of all object properties
199
     *
200
     * @return array Object properties
201
     */
202 1
    public function getArrayCopy()
203
    {
204 1
        $properties = array_keys($this->mapping);
205 1
        return array_combine(
206
            $properties,
207
            array_map(
208 1
                function ($property) {
209 1
                    return $this[$property];
210 1
                },
211
                $properties
212
            )
213
        );
214
    }
215
216
    /**
217
     * Return the number of object properties
218
     *
219
     * @return int Number of object properties
220
     */
221 1
    public function count()
222
    {
223 1
        return count($this->mapping);
224
    }
225
226
    /**
227
     * Sort the object properties by value
228
     *
229
     * @return void
230
     */
231 1
    public function asort()
232
    {
233
        // Do nothing
234 1
    }
235
236
    /**
237
     * Sort the entries by key
238
     * @link http://php.net/manual/en/arrayobject.ksort.php
239
     * @return void
240
     * @since 5.2.0
241
     */
242
    /**
243
     * Sort the object properties by key
244
     *
245
     * @return void
246
     */
247 1
    public function ksort()
248
    {
249
        // Do nothing
250 1
    }
251
252
    /**
253
     * Sort the object properties by user function
254
     *
255
     * @param \Closure|\Callable $compareFunction User function
256
     * @return void
257
     */
258 1
    public function uasort($compareFunction)
259
    {
260
        // Do nothing
261 1
        if (is_callable($compareFunction())) {
262
            return;
263
        }
264 1
    }
265
266
    /**
267
     * Sort the object properties by name and user function
268
     *
269
     * @param \Closure|\Callable $compareFunction User function
270
     * @return void
271
     */
272 1
    public function uksort($compareFunction)
273
    {
274
        // Do nothing
275 1
        if (is_callable($compareFunction())) {
276
            return;
277
        }
278 1
    }
279
280
    /**
281
     * Sort the object properties using a "natural order" algorithm
282
     *
283
     * @return void
284
     */
285 1
    public function natsort()
286
    {
287
        // Do nothing
288 1
    }
289
290
    /**
291
     * Sort the object properties using a case insensitive "natural order" algorithm
292
     *
293
     * @return void
294
     */
295 1
    public function natcasesort()
296
    {
297
        // Do nothing
298 1
    }
299
300
    /**
301
     * Unserialize the apparat object
302
     *
303
     * @param string $serialized Serialized apparat object
304
     */
305 1
    public function unserialize($serialized)
306
    {
307 1
        $objectUrl = unserialize($serialized);
308 1
        $this->object = Object::load($objectUrl);
309 1
    }
310
311
    /**
312
     * Exchange the associated object
313
     *
314
     * @param mixed $object Object
315
     * @return ObjectInterface Former object
316
     */
317 1
    public function exchangeArray($object)
318
    {
319
        // If a valid option was given
320 1
        if ($object instanceof ObjectInterface) {
321 1
            $formerObject = $this->object;
322 1
            $this->object = $object;
323 1
            return $formerObject;
324
        }
325
326 1
        throw new InvalidArgumentException(
327 1
            sprintf('Invalid exchange object'),
328 1
            InvalidArgumentException::INVALID_EXCHANGE_OBJECT
329
        );
330
    }
331
332
    /**
333
     * Serialize the apparat object
334
     *
335
     * @return AbstractApparatObject Serialized apparat object
336
     */
337 1
    public function serialize()
338
    {
339 1
        return serialize($this->object->getAbsoluteUrl());
340
    }
341
342
    /**
343
     * Create and return a new object iterator instance
344
     *
345
     * @return ApparatObjectIterator Object iterator instance
346
     */
347 1
    public function getIterator()
348
    {
349 1
        return Kernel::create($this->getIteratorClass(), [$this->mapping, $this->getFlags(), $this]);
350
    }
351
}
352