Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.77% covered (success)
96.77%
30 / 31
93.33% covered (success)
93.33%
14 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
AbstractObjectContainer
96.77% covered (success)
96.77%
30 / 31
93.33% covered (success)
93.33%
14 / 15
23
0.00% covered (danger)
0.00%
0 / 1
 offsetExists
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 offsetGet
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 offsetSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetUnset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 current
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 next
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 valid
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rewind
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 add
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
4
 jsonSerialize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 objectClass
n/a
0 / 0
n/a
0 / 0
0
 objectProperty
n/a
0 / 0
n/a
0 / 0
0
 beforeObjectIsStored
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getObjectKey
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
1<?php
2
3declare(strict_types=1);
4
5namespace WsdlToPhp\PackageGenerator\Container;
6
7use WsdlToPhp\PackageGenerator\Generator\AbstractGeneratorAware;
8
9abstract class AbstractObjectContainer extends AbstractGeneratorAware implements \ArrayAccess, \Iterator, \Countable, \JsonSerializable
10{
11    public const PROPERTY_NAME = 'name';
12
13    protected array $objects = [];
14
15    protected int $offset = 0;
16
17    public function offsetExists($offset): bool
18    {
19        $element = array_slice($this->objects, $offset, 1);
20
21        return !empty($element);
22    }
23
24    /**
25     * @param mixed $offset
26     *
27     * @return mixed
28     */
29    #[\ReturnTypeWillChange]
30    public function offsetGet($offset)
31    {
32        $element = array_slice($this->objects, $offset, 1);
33
34        return $this->offsetExists($offset) ? array_shift($element) : null;
35    }
36
37    /**
38     * @param mixed $offset
39     * @param mixed $value
40     *
41     * @return mixed
42     * @throws \InvalidArgumentException
43     */
44    #[\ReturnTypeWillChange]
45    public function offsetSet($offset, $value)
46    {
47        throw new \InvalidArgumentException('This method can\'t be used as object are stored with a string as array index', __LINE__);
48    }
49
50    #[\ReturnTypeWillChange]
51    public function offsetUnset($offset): void
52    {
53        if ($this->offsetExists($offset)) {
54            unset($this->objects[$this->getObjectKey($this->offsetGet($offset))]);
55        }
56    }
57
58    /**
59     * @return mixed
60     */
61    #[\ReturnTypeWillChange]
62    public function current()
63    {
64        $current = array_slice($this->objects, $this->offset, 1);
65
66        return array_shift($current);
67    }
68
69    #[\ReturnTypeWillChange]
70    public function next(): void
71    {
72        ++$this->offset;
73    }
74
75    #[\ReturnTypeWillChange]
76    public function key(): int
77    {
78        return $this->offset;
79    }
80
81    public function valid(): bool
82    {
83        return 0 < count(array_slice($this->objects, $this->offset, 1));
84    }
85
86    #[\ReturnTypeWillChange]
87    public function rewind(): void
88    {
89        $this->offset = 0;
90    }
91
92    #[\ReturnTypeWillChange]
93    public function count(): int
94    {
95        return count($this->objects);
96    }
97
98    public function add(object $object): self
99    {
100        $this->beforeObjectIsStored($object);
101        $this->objects[$this->getObjectKey($object)] = $object;
102
103        return $this;
104    }
105
106    /**
107     * @param mixed $value
108     * @throws \InvalidArgumentException
109     */
110    public function get($value)
111    {
112        if (!is_scalar($value)) {
113            throw new \InvalidArgumentException(sprintf('Value "%s" can\'t be used to get an object from "%s"', is_object($value) ? get_class($value) : var_export($value, true), get_class($this)), __LINE__);
114        }
115
116        return array_key_exists($value, $this->objects) ? $this->objects[$value] : null;
117    }
118
119    public function jsonSerialize(): array
120    {
121        return array_values($this->objects);
122    }
123
124    /**
125     * Must return the object class name that this container is made to contain.
126     */
127    abstract protected function objectClass(): string;
128
129    /**
130     * Must return the object's property name that this container is using to store the object.
131     */
132    abstract protected function objectProperty(): string;
133
134    /**
135     * This method is called before the object has been stored.
136     *
137     * @throws \InvalidArgumentException
138     */
139    protected function beforeObjectIsStored(object $object): void
140    {
141        $objectClass = $this->objectClass();
142
143        if (!$object instanceof $objectClass) {
144            throw new \InvalidArgumentException(sprintf('Model of type "%s" does not match the object contained by this class: "%s"', get_class($object), $objectClass), __LINE__);
145        }
146    }
147
148    /**
149     * @throws \InvalidArgumentException
150     */
151    protected function getObjectKey(object $object)
152    {
153        $get = sprintf('get%s', ucfirst($this->objectProperty()));
154        if (!method_exists($object, $get)) {
155            throw new \InvalidArgumentException(sprintf('Method "%s" is required in "%s" in order to be stored in "%s"', $get, get_class($object), get_class($this)), __LINE__);
156        }
157
158        $key = $object->{$get}();
159        if (!is_scalar($key)) {
160            throw new \InvalidArgumentException(sprintf('Property "%s" of "%s" must be scalar, "%s" returned', $this->objectProperty(), get_class($object), gettype($key)), __LINE__);
161        }
162
163        return $key;
164    }
165}