Completed
Push — master ( a373f3...4d04c4 )
by Joschi
03:00
created

ApparatObjectTrait::asort()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
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
 */
55
trait ApparatObjectTrait
56
{
57
    /**
58
     * Property mapping
59
     *
60
     * @var array
61
     */
62
    protected $mapping = [];
63
64
    /**
65
     * Generic getter
66
     *
67
     * @param string $method Method name
68
     * @param array $arguments Arguments
69
     * @throws \BadMethodCallException If the method is unknown
70
     */
71 2
    public function __call($method, array $arguments)
72
    {
73
        // If a getter was called
74 2
        if (!strncmp('get', $method, 3)) {
75 2
            $property = lcfirst(substr($method, 3));
76 2
            if (array_key_exists($property, $this->mapping)) {
77 1
                $arguments = (array)$this->mapping[$property];
78 1
                $getter = 'get'.ucfirst(array_shift($arguments));
79 1
                return $this->delegateObjectGetter($property, $getter, $arguments);
80
            }
81
        }
82
83
        // If the method is unknown
84 1
        throw new \BadMethodCallException(sprintf('Unknown apparat object method "%s()"', $method));
85
    }
86
87
    /**
88
     * Delegate the mapped object getter
89
     *
90
     * @param string $property Property name
91
     * @param string $getter Getter name
92
     * @param array $arguments Getter arguments
93
     * @return mixed Property value
94
     * @throws InvalidArgumentException If the property is invalid
95
     */
96 3
    protected function delegateObjectGetter($property, $getter, array $arguments)
97
    {
98
        // If the property is invalid
99 3
        if (!is_callable([$this->object, $getter])) {
100 1
            throw new InvalidArgumentException(
101 1
                sprintf('Invalid apparat object property "%s"', $property),
102 1
                InvalidArgumentException::INVALID_APPARAT_OBJECT_PROPERTY
103
            );
104
        }
105
        try {
106 2
            return $this->object->$getter(...$arguments);
107 1
        } catch (PropertyInvalidArgumentException $e) {
108 1
            return null;
109
        }
110
    }
111
112
    /**
113
     * Return whether a particular property exists
114
     *
115
     * @param string $offset Property name
116
     */
117 1
    public function offsetExists($offset)
118
    {
119 1
        return array_key_exists($offset, $this->mapping);
120
    }
121
122
    /**
123
     * Return a particular property
124
     *
125
     * @param string $offset Property name
126
     * @return mixed Property value
127
     * @throws InvalidArgumentException If the requested property is invalid
128
     */
129 4
    public function offsetGet($offset)
130
    {
131
        // If a known object property has been requested
132 4
        if (array_key_exists($offset, $this->mapping)) {
133 3
            $arguments = (array)$this->mapping[$offset];
134 3
            $property = array_shift($arguments);
135 3
            $getter = 'get'.ucfirst($property);
136 3
            return $this->delegateObjectGetter($property, $getter, $arguments);
137
        }
138
139 1
        throw new InvalidArgumentException(
140 1
            sprintf('Invalid apparat object property "%s"', $offset),
141 1
            InvalidArgumentException::INVALID_APPARAT_OBJECT_PROPERTY
142
        );
143
    }
144
145
    /**
146
     * Set a particular property
147
     *
148
     * @param string $offset Property name
149
     * @param mixed $value Property value
150
     * @throws InvalidArgumentException
151
     */
152 1
    public function offsetSet($offset, $value)
153
    {
154 1
        throw new InvalidArgumentException(
155 1
            sprintf('Cannot set apparat object property "%s" to value "%s"', $offset, $value),
156 1
            InvalidArgumentException::CANNOT_SET_APPARAT_OBJECT_PROPERTY
157
        );
158
    }
159
160
    /**
161
     * Unset a particular property
162
     *
163
     * @param string $offset Property name
164
     * @throws InvalidArgumentException
165
     */
166 1
    public function offsetUnset($offset)
167
    {
168 1
        throw new InvalidArgumentException(
169 1
            sprintf('Cannot unset apparat object property "%s"', $offset),
170 1
            InvalidArgumentException::CANNOT_UNSET_APPARAT_OBJECT_PROPERTY
171
        );
172
    }
173
174
    /**
175
     * Append a value
176
     *
177
     * @param mixed $value Value
178
     * @throws InvalidArgumentException
179
     */
180 1
    public function append($value)
181
    {
182 1
        throw new InvalidArgumentException(
183 1
            sprintf('Cannot append apparat object value "%s"', $value),
184 1
            InvalidArgumentException::CANNOT_APPEND_APPARAT_OBJECT_VALUE
185
        );
186
    }
187
188
    /**
189
     * Return an array copy of all object properties
190
     *
191
     * @return array Object properties
192
     */
193 1
    public function getArrayCopy()
194
    {
195 1
        $properties = array_keys($this->mapping);
196 1
        return array_combine(
197
            $properties,
198
            array_map(
199 1
                function ($property) {
200 1
                    return $this[$property];
201 1
                },
202
                $properties
203
            )
204
        );
205
    }
206
207
    /**
208
     * Return the number of object properties
209
     *
210
     * @return int Number of object properties
211
     */
212 1
    public function count()
213
    {
214 1
        return count($this->mapping);
215
    }
216
217
    /**
218
     * Sort the object properties by value
219
     *
220
     * @return void
221
     */
222 1
    public function asort()
223
    {
224
        // Do nothing
225 1
    }
226
227
    /**
228
     * Sort the entries by key
229
     * @link http://php.net/manual/en/arrayobject.ksort.php
230
     * @return void
231
     * @since 5.2.0
232
     */
233
    /**
234
     * Sort the object properties by key
235
     *
236
     * @return void
237
     */
238 1
    public function ksort()
239
    {
240
        // Do nothing
241 1
    }
242
243
    /**
244
     * Sort the object properties by user function
245
     *
246
     * @param \Callable $compareFunction User function
247
     * @return void
248
     */
249 1
    public function uasort($compareFunction)
0 ignored issues
show
Unused Code introduced by
The parameter $compareFunction is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
250
    {
251
        // Do nothing
252 1
    }
253
254
    /**
255
     * Sort the object properties by name and user function
256
     *
257
     * @param \Callable $compareFunction User function
258
     * @return void
259
     */
260 1
    public function uksort($compareFunction)
0 ignored issues
show
Unused Code introduced by
The parameter $compareFunction is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
261
    {
262
        // Do nothing
263 1
    }
264
265
    /**
266
     * Sort the object properties using a "natural order" algorithm
267
     *
268
     * @return void
269
     */
270 1
    public function natsort()
271
    {
272
        // Do nothing
273 1
    }
274
275
    /**
276
     * Sort the object properties using a case insensitive "natural order" algorithm
277
     *
278
     * @return void
279
     */
280 1
    public function natcasesort()
281
    {
282
        // Do nothing
283 1
    }
284
285
    /**
286
     * Unserialize the apparat object
287
     *
288
     * @param string $serialized Serialized apparat object
289
     */
290 1
    public function unserialize($serialized)
291
    {
292 1
        $objectUrl = unserialize($serialized);
293 1
        $this->object = Object::load($objectUrl);
294 1
    }
295
296
    /**
297
     * Exchange the associated object
298
     *
299
     * @param mixed $object Object
300
     * @return ObjectInterface Former object
301
     */
302 1
    public function exchangeArray($object)
303
    {
304
        // If a valid option was given
305 1
        if ($object instanceof ObjectInterface) {
306 1
            $formerObject = $this->object;
307 1
            $this->object = $object;
308 1
            return $formerObject;
309
        }
310
311 1
        throw new InvalidArgumentException(
312 1
            sprintf('Invalid exchange object'),
313 1
            InvalidArgumentException::INVALID_EXCHANGE_OBJECT
314
        );
315
    }
316
317
    /**
318
     * Serialize the apparat object
319
     *
320
     * @return AbstractApparatObject Serialized apparat object
321
     */
322 1
    public function serialize()
323
    {
324 1
        return serialize($this->object->getAbsoluteUrl());
325
    }
326
327
    /**
328
     * Create and return a new object iterator instance
329
     *
330
     * @return ApparatObjectIterator Object iterator instance
331
     */
332 1
    public function getIterator()
333
    {
334 1
        return Kernel::create($this->getIteratorClass(), [$this->mapping, $this->getFlags(), $this]);
0 ignored issues
show
Documentation Bug introduced by
The method getIteratorClass does not exist on object<Apparat\Object\In...its\ApparatObjectTrait>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Documentation Bug introduced by
The method getFlags does not exist on object<Apparat\Object\In...its\ApparatObjectTrait>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
335
    }
336
}
337