Completed
Push — master ( d4b7a6...61f16c )
by Joschi
03:53
created

ApparatObjectTrait   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 48.65%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 282
ccs 36
cts 74
cp 0.4865
rs 10
wmc 25
lcom 1
cbo 3

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getIterator() 0 4 1
A delegateObjectGetter() 0 15 3
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 4 1
A uksort() 0 4 1
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 __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
 */
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
        } catch (PropertyInvalidArgumentException $e) {
108
            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 3
    public function offsetGet($offset)
130
    {
131
        // If a known object property has been requested
132 3
        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
        throw new InvalidArgumentException(
140
            sprintf('Invalid apparat object property "%s"', $offset),
141
            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
    public function append($value)
181
    {
182
        throw new InvalidArgumentException(
183
            sprintf('Cannot append apparat object value "%s"', $value),
184
            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
    public function getArrayCopy()
194
    {
195
        $properties = array_keys($this->mapping);
196
        return array_combine(
197
            $properties,
198
            array_map(
199
                function ($property) {
200
                    return $this[$property];
201
                },
202
                $properties
203
            )
204
        );
205
    }
206
207
    /**
208
     * Return the number of object properties
209
     *
210
     * @return int Number of object properties
211
     */
212
    public function count()
213
    {
214
        return count($this->mapping);
215
    }
216
217
    /**
218
     * Sort the object properties by value
219
     *
220
     * @return void
221
     */
222
    public function asort()
223
    {
224
        // Do nothing
225
    }
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
    public function ksort()
239
    {
240
        // Do nothing
241
    }
242
243
    /**
244
     * Sort the object properties by user function
245
     *
246
     * @param \Callable $compareFunction User function
247
     * @return void
248
     */
249
    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
    }
253
254
    /**
255
     * Sort the object properties by name and user function
256
     *
257
     * @param \Callable $compareFunction User function
0 ignored issues
show
Bug introduced by
There is no parameter named $compareFunction. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
258
     * @return void
259
     */
260
    public function uksort($cmp_function)
0 ignored issues
show
Unused Code introduced by
The parameter $cmp_function 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
    }
264
265
    /**
266
     * Sort the object properties using a "natural order" algorithm
267
     *
268
     * @return void
269
     */
270
    public function natsort()
271
    {
272
        // Do nothing
273
    }
274
275
    /**
276
     * Sort the object properties using a case insensitive "natural order" algorithm
277
     *
278
     * @return void
279
     */
280
    public function natcasesort()
281
    {
282
        // Do nothing
283
    }
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
    public function exchangeArray($object)
303
    {
304
        // If a valid option was given
305
        if ($object instanceof ObjectInterface) {
306
            $formerObject = $this->object;
307
            $this->object = $object;
308
            return $formerObject;
309
        }
310
311
        throw new InvalidArgumentException(
312
            sprintf('Invalid exchange object'),
313
            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
    public function getIterator()
333
    {
334
        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