Completed
Push — master ( 2d80b2...8a71ed )
by Joschi
03:21
created

ApparatObjectTrait::count()   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 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
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\Ports\Exceptions\InvalidArgumentException;
46
47
/**
48
 * Apparat object trait
49
 *
50
 * @package Apparat\Object
51
 * @subpackage Apparat\Object\Infrastructure
52
 * @property ApplicationObjectInterface $object
53
 */
54
trait ApparatObjectTrait
55
{
56
    /**
57
     * Property mapping
58
     *
59
     * @var array
60
     */
61
    protected $mapping = [];
62
63
    /**
64
     * Generic getter
65
     *
66
     * @param string $method Method name
67
     * @param array $arguments Arguments
68
     * @throws \BadMethodCallException If the method is unknown
69
     */
70 2
    public function __call($method, array $arguments)
71
    {
72
        // If a getter was called
73 2
        if (!strncmp('get', $method, 3)) {
74 2
            $property = lcfirst(substr($method, 3));
75 2
            if (array_key_exists($property, $this->mapping)) {
76 1
                $arguments = (array)$this->mapping[$property];
77 1
                $getter = 'get'.ucfirst(array_shift($arguments));
78 1
                return $this->delegateObjectGetter($property, $getter, $arguments);
79
            }
80
        }
81
82
        // If the method is unknown
83 1
        throw new \BadMethodCallException(sprintf('Unknown apparat object method "%s()"', $method));
84
    }
85
86
    /**
87
     * Delegate the mapped object getter
88
     *
89
     * @param string $property Property name
90
     * @param string $getter Getter name
91
     * @param array $arguments Getter arguments
92
     * @return mixed Property value
93
     * @throws InvalidArgumentException If the property is invalid
94
     */
95 2
    protected function delegateObjectGetter($property, $getter, array $arguments)
96
    {
97
        // If the property is invalid
98 2
        if (!is_callable([$this->object, $getter])) {
99 1
            throw new InvalidArgumentException(
100 1
                sprintf('Invalid apparat object property "%s"', $property),
101 1
                InvalidArgumentException::INVALID_APPARAT_OBJECT_PROPERTY
102
            );
103
        }
104
        try {
105 1
            return $this->object->$getter(...$arguments);
106
        } catch (PropertyInvalidArgumentException $e) {
107
            return null;
108
        }
109
    }
110
111
    /**
112
     * Return whether a particular property exists
113
     *
114
     * @param string $offset Property name
115
     */
116 1
    public function offsetExists($offset)
117
    {
118 1
        return array_key_exists($offset, $this->mapping);
119
    }
120
121
    /**
122
     * Return a particular property
123
     *
124
     * @param string $offset Property name
125
     * @return mixed Property value
126
     * @throws InvalidArgumentException If the requested property is invalid
127
     */
128 2
    public function offsetGet($offset)
129
    {
130
        // If a known object property has been requested
131 2
        if (array_key_exists($offset, $this->mapping)) {
132 2
            $arguments = (array)$this->mapping[$offset];
133 2
            $property = array_shift($arguments);
134 2
            $getter = 'get'.ucfirst($property);
135 2
            return $this->delegateObjectGetter($property, $getter, $arguments);
136
        }
137
138
        throw new InvalidArgumentException(
139
            sprintf('Invalid apparat object property "%s"', $offset),
140
            InvalidArgumentException::INVALID_APPARAT_OBJECT_PROPERTY
141
        );
142
    }
143
144
    /**
145
     * Set a particular property
146
     *
147
     * @param string $offset Property name
148
     * @param mixed $value Property value
149
     * @throws InvalidArgumentException
150
     */
151 1
    public function offsetSet($offset, $value)
152
    {
153 1
        throw new InvalidArgumentException(
154 1
            sprintf('Cannot set apparat object property "%s" to value "%s"', $offset, $value),
155 1
            InvalidArgumentException::CANNOT_SET_APPARAT_OBJECT_PROPERTY
156
        );
157
    }
158
159
    /**
160
     * Unset a particular property
161
     *
162
     * @param string $offset Property name
163
     * @throws InvalidArgumentException
164
     */
165 1
    public function offsetUnset($offset)
166
    {
167 1
        throw new InvalidArgumentException(
168 1
            sprintf('Cannot unset apparat object property "%s"', $offset),
169 1
            InvalidArgumentException::CANNOT_UNSET_APPARAT_OBJECT_PROPERTY
170
        );
171
    }
172
173
    /**
174
     * Append a value
175
     *
176
     * @param mixed $value Value
177
     * @throws InvalidArgumentException
178
     */
179
    public function append($value)
180
    {
181
        throw new InvalidArgumentException(
182
            sprintf('Cannot append apparat object value "%s"', $value),
183
            InvalidArgumentException::CANNOT_APPEND_APPARAT_OBJECT_VALUE
184
        );
185
    }
186
187
    /**
188
     * Return an array copy of all object properties
189
     *
190
     * @return array Object properties
191
     */
192
    public function getArrayCopy()
193
    {
194
        $properties = array_keys($this->mapping);
195
        return array_combine(
196
            $properties,
197
            array_map(
198
                function ($property) {
199
                    return $this[$property];
200
                },
201
                $properties
202
            )
203
        );
204
    }
205
206
    /**
207
     * Return the number of object properties
208
     *
209
     * @return int Number of object properties
210
     */
211
    public function count()
212
    {
213
        return count($this->mapping);
214
    }
215
216
    /**
217
     * Sort the object properties by value
218
     *
219
     * @return void
220
     */
221
    public function asort()
222
    {
223
        // Do nothing
224
    }
225
226
    /**
227
     * Sort the entries by key
228
     * @link http://php.net/manual/en/arrayobject.ksort.php
229
     * @return void
230
     * @since 5.2.0
231
     */
232
    /**
233
     * Sort the object properties by key
234
     *
235
     * @return void
236
     */
237
    public function ksort()
238
    {
239
        // Do nothing
240
    }
241
242
    /**
243
     * Sort the object properties by user function
244
     *
245
     * @param \Callable $compareFunction User function
246
     * @return void
247
     */
248
    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...
249
    {
250
        // Do nothing
251
    }
252
253
    /**
254
     * Sort the object properties by name and user function
255
     *
256
     * @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...
257
     * @return void
258
     */
259
    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...
260
    {
261
        // Do nothing
262
    }
263
264
    /**
265
     * Sort the object properties using a "natural order" algorithm
266
     *
267
     * @return void
268
     */
269
    public function natsort()
270
    {
271
        // Do nothing
272
    }
273
274
    /**
275
     * Sort the object properties using a case insensitive "natural order" algorithm
276
     *
277
     * @return void
278
     */
279
    public function natcasesort()
280
    {
281
        // Do nothing
282
    }
283
284
    /**
285
     * Unserialize the apparat object
286
     *
287
     * @param string $serialized Serialized apparat object
288
     * @return AbstractApparatObject Unserialized apparat object
289
     */
290
    public function unserialize($serialized)
291
    {
292
        return unserialize($serialized);
293
    }
294
295
    /**
296
     * Serialize the apparat object
297
     *
298
     * @return AbstractApparatObject Serialized apparat object
299
     */
300
    public function serialize()
301
    {
302
        // TODO: Serialization should consist of repository + object locators (or object URL?)
303
        return '';
304
    }
305
306
    /**
307
     * Exchange the associated object
308
     *
309
     * @param mixed $object Object
310
     * @return ObjectInterface Former object
311
     */
312
    public function exchangeArray($object)
313
    {
314
        // If a valid option was given
315
        if ($object instanceof ObjectInterface) {
316
            $formerObject = $this->object;
317
            $this->object = $object;
318
            return $formerObject;
319
        }
320
321
        throw new InvalidArgumentException(
322
            sprintf('Invalid exchange object'),
323
            InvalidArgumentException::INVALID_EXCHANGE_OBJECT
324
        );
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