AbstractObjectContainer   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Test Coverage

Coverage 98.15%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
eloc 43
c 4
b 0
f 1
dl 0
loc 147
ccs 53
cts 54
cp 0.9815
rs 10
wmc 23

15 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetGet() 0 6 2
A beforeObjectIsStored() 0 6 2
A add() 0 6 1
A getObjectKey() 0 13 3
A offsetSet() 0 4 1
A count() 0 4 1
A jsonSerialize() 0 3 1
A valid() 0 3 1
A offsetUnset() 0 5 2
A rewind() 0 4 1
A get() 0 7 4
A current() 0 6 1
A key() 0 4 1
A offsetExists() 0 5 1
A next() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WsdlToPhp\PackageGenerator\Container;
6
7
use WsdlToPhp\PackageGenerator\Generator\AbstractGeneratorAware;
8
9
abstract 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 24
    public function offsetExists($offset): bool
18
    {
19 24
        $element = array_slice($this->objects, $offset, 1);
20
21 24
        return !empty($element);
22
    }
23
24
    /**
25
     * @param mixed $offset
26
     *
27
     * @return mixed
28
     */
29 12
    #[\ReturnTypeWillChange]
30 12
    public function offsetGet($offset)
31
    {
32 24
        $element = array_slice($this->objects, $offset, 1);
33
34 24
        return $this->offsetExists($offset) ? array_shift($element) : null;
35
    }
36
37
    /**
38
     * @param mixed $offset
39
     * @param mixed $value
40
     *
41
     * @return mixed
42
     */
43 1
    #[\ReturnTypeWillChange]
44 1
    public function offsetSet($offset, $value)
45
    {
46 2
        throw new \InvalidArgumentException('This method can\'t be used as object are stored with a string as array index', __LINE__);
47
    }
48
49 1
    #[\ReturnTypeWillChange]
50 1
    public function offsetUnset($offset): void
51
    {
52 2
        if ($this->offsetExists($offset)) {
53 2
            unset($this->objects[$this->getObjectKey($this->offsetGet($offset))]);
54
        }
55
    }
56
57
    /**
58
     * @return mixed
59
     */
60 165
    #[\ReturnTypeWillChange]
61 165
    public function current()
62
    {
63 330
        $current = array_slice($this->objects, $this->offset, 1);
64
65 330
        return array_shift($current);
66
    }
67
68 165
    #[\ReturnTypeWillChange]
69 165
    public function next(): void
70
    {
71 330
        ++$this->offset;
72
    }
73
74 56
    #[\ReturnTypeWillChange]
75 56
    public function key(): int
76
    {
77 112
        return $this->offset;
78
    }
79
80 364
    public function valid(): bool
81
    {
82 364
        return 0 < count(array_slice($this->objects, $this->offset, 1));
83
    }
84
85 182
    #[\ReturnTypeWillChange]
86 182
    public function rewind(): void
87
    {
88 364
        $this->offset = 0;
89
    }
90
91 175
    #[\ReturnTypeWillChange]
92 175
    public function count(): int
93
    {
94 350
        return count($this->objects);
95
    }
96
97 572
    public function add(object $object): self
98
    {
99 572
        $this->beforeObjectIsStored($object);
100 560
        $this->objects[$this->getObjectKey($object)] = $object;
101
102 558
        return $this;
103
    }
104
105 568
    public function get($value)
106
    {
107 568
        if (!is_scalar($value)) {
108 2
            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__);
109
        }
110
111 566
        return array_key_exists($value, $this->objects) ? $this->objects[$value] : null;
112
    }
113
114 4
    public function jsonSerialize(): array
115
    {
116 4
        return array_values($this->objects);
117
    }
118
119
    /**
120
     * Must return the object class name that this container is made to contain.
121
     */
122
    abstract protected function objectClass(): string;
123
124
    /**
125
     * Must return the object's property name that this container is using to store the object.
126
     */
127
    abstract protected function objectProperty(): string;
128
129
    /**
130
     * This method is called before the object has been stored.
131
     *
132
     * @throws \InvalidArgumentException
133
     */
134 572
    protected function beforeObjectIsStored(object $object): void
135
    {
136 572
        $objectClass = $this->objectClass();
137
138 572
        if (!$object instanceof $objectClass) {
139 12
            throw new \InvalidArgumentException(sprintf('Model of type "%s" does not match the object contained by this class: "%s"', get_class($object), $objectClass), __LINE__);
140
        }
141
    }
142
143 560
    protected function getObjectKey(object $object)
144
    {
145 560
        $get = sprintf('get%s', ucfirst($this->objectProperty()));
146 560
        if (!method_exists($object, $get)) {
147 2
            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__);
148
        }
149
150 558
        $key = $object->{$get}();
151 558
        if (!is_scalar($key)) {
152
            throw new \InvalidArgumentException(sprintf('Property "%s" of "%s" must be scalar, "%s" returned', $this->objectProperty(), get_class($object), gettype($key)), __LINE__);
153
        }
154
155 558
        return $key;
156
    }
157
}
158