Completed
Push — master ( dfec5f...1a2fe9 )
by Mārtiņš
02:17
created

Collection::purge()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Palladium\Component;
4
5
use Palladium\Component\Collection;
6
use Palladium\Contract\HasId;
7
8
/**
9
 * Class for handling sets of domain entities.
10
 * To use it, it needs to be extended with `buildEntity()` method implemented. This method
11
 * must return an instance of that domain entity.
12
 */
13
14
15
abstract class Collection implements \Iterator, \ArrayAccess, \Countable
16
{
17
18
    abstract protected function buildEntity(): HasId;
19
20
    private $pool = [];
21
    private $indexed = [];
22
23
    private $map = [];
24
25
    private $position = 0;
26
27
    private $total = 0;
28
    private $offset = 0;
29
    private $limit = 10;
30
31
32
    /**
33
     * Add new domain entity, that is constructed using array as values. Each array key
34
     * will be attempted top match with entity's setter method and provided with
35
     * the respective array value. It returns the newly created entity.
36
     *
37
     * @param array $parameters
38
     *
39
     * @return HasId
40
     */
41 1
    public function addBlueprint(array $parameters)
42
    {
43 1
        $instance = $this->buildEntity();
44 1
        $this->populateEntity($instance, $parameters);
45
46 1
        $this->addEntity($instance);
47
48 1
        return $instance;
49
    }
50
51
52
    /** code that does the actual population of data from the given array in blueprint */
53 1 View Code Duplication
    private function populateEntity($instance, array $parameters)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
54
    {
55 1
        foreach ($parameters as $key => $value) {
56 1
            $method = 'set' . str_replace('_', '', $key);
57 1
            if (method_exists($instance, $method)) {
58 1
                $instance->{$method}($value);
59
            }
60
        }
61 1
    }
62
63
64
    /**
65
     * Method for adding already existing domain entity to the collection.
66
     *
67
     * @param HasId $entity
68
     */
69 13
    public function addEntity(HasId $entity, $key = null)
70
    {
71
72 13
        if (is_null($key) === false) {
73 2
            $this->replaceEntity($entity, $key);
74 2
            return;
75
        }
76
77 12
        $entityId = $entity->getId();
78
79 12
        $this->pool[] = $entity;
80
81 12
        $this->indexed[$entityId] = $entity;
82 12
        $this->map[$entityId] = $this->retrieveLastPoolKey();
83 12
    }
84
85
86 1
    public function removeEntityById($key)
87
    {
88 1
        unset($this->pool[$this->map[$key]]);
89 1
        $this->removeIndexEntry($key);
90 1
        $this->pool = array_values($this->pool);
91 1
    }
92
93
94 2
    private function replaceEntity(HasId $entity, $key)
95
    {
96 2
        if (isset($this->pool[$key])) {
97 1
            $this->removeIndexEntry($this->pool[$key]->getId());
98
        }
99
100 2
        $entityId = $entity->getId();
101
102 2
        $this->pool[$key] = $entity;
103 2
        $this->indexed[$entityId] = $entity;
104 2
        $this->map[$entityId] = $key;
105 2
    }
106
107
108 5
    private function removeIndexEntry($key)
109
    {
110 5
        unset($this->indexed[$key]);
111 5
        unset($this->map[$key]);
112 5
    }
113
114
115 12
    private function retrieveLastPoolKey()
116
    {
117 12
        end($this->pool);
118 12
        return key($this->pool);
119
    }
120
121
122
    /**
123
     * Method for getting an ordered list of IDs for items in the collection.
124
     *
125
     * @return array
126
     */
127 5
    public function getIds()
128
    {
129 5
        $keys = array_keys($this->indexed);
130 5
        sort($keys);
131 5
        return $keys;
132
    }
133
134
135
    /**
136
     * Replaces all of the domain entities with a content of some other collection
137
     *
138
     * @param Collection $replacement
139
     */
140 1
    public function replaceWith(Collection $replacement)
141
    {
142 1
        $this->pool = [];
143 1
        $this->map = [];
144 1
        $this->indexed = [];
145
146 1
        foreach ($replacement as $entity) {
147 1
            $this->addEntity($entity);
148
        }
149 1
    }
150
151
152
    /**
153
     * Removes an entity from collection.
154
     *
155
     * @param HasId $entity
156
     */
157 3
    public function removeEntity(HasId $entity)
158
    {
159 3
        $key = $entity->getId();
160
161 3
        if ($key !== null) {
162 3
            unset($this->pool[$this->map[$key]]);
163 3
            $this->removeIndexEntry($key);
164
        }
165 3
    }
166
167
168
    /**
169
     * Removes all of the content of the collection and resets it to pristine state.
170
     */
171 1
    public function purge()
172
    {
173 1
        $this->pool = [];
174 1
        $this->indexed = [];
175 1
        $this->map = [];
176 1
        $this->position = 0;
177 1
    }
178
179
180
    // implementing Countable
181 2
    public function count()
182
    {
183 2
        return count($this->pool);
184
    }
185
186
187
    // implementing Iterator
188 2
    public function rewind()
189
    {
190 2
        $this->position = 0;
191 2
    }
192
193
194 2
    public function current()
195
    {
196 2
        return $this->pool[$this->position];
197
    }
198
199
200
    /**
201
     * @codeCoverageIgnore
202
     */
203
    public function key()
204
    {
205
        return $this->position;
206
    }
207
208
209 2
    public function next()
210
    {
211 2
        ++$this->position;
212 2
    }
213
214
215 2
    public function valid()
216
    {
217 2
        return isset($this->pool[$this->position]);
218
    }
219
220
221
    // implementing ArrayAccess
222 10
    public function offsetSet($offset, $value)
223
    {
224 10
        $this->addEntity($value, $offset);
225 10
    }
226
227
228 1
    public function offsetExists($offset)
229
    {
230 1
        return isset($this->pool[$offset]);
231
    }
232
233
234 3
    public function offsetUnset($offset)
235
    {
236 3
        $this->removeEntity($this->pool[$offset]);
237 3
    }
238
239
240 5
    public function offsetGet($offset)
241
    {
242 5
        if (isset($this->pool[$offset])) {
243 5
            return $this->pool[$offset];
244
        }
245
246 2
        return null;
247
    }
248
249
250
    // pagination
251
252 1
    public function setOffset($offset)
253
    {
254 1
        $data = (int) $offset;
255
256 1
        if ($data < 0) {
257 1
            $data = 0;
258
        }
259
260 1
        $this->offset = $data;
261 1
    }
262
263
264
    /**
265
     * @codeCoverageIgnore
266
     */
267
    public function getOffset()
268
    {
269
        return $this->offset;
270
    }
271
272
273 1
    public function setLimit($limit)
274
    {
275 1
        $data = (int) $limit;
276
277 1
        if ($data < 0) {
278 1
            $data = 0;
279
        }
280
281 1
        $this->limit = $data;
282 1
    }
283
284
285
    /**
286
     * @codeCoverageIgnore
287
     */
288
    public function getLimit()
289
    {
290
        return $this->limit;
291
    }
292
293
294 1
    public function setTotal($total)
295
    {
296 1
        $data = (int) $total;
297
298 1
        if ($data < 0) {
299 1
            $data = 0;
300
        }
301
302 1
        $this->total = $data;
303 1
    }
304
305
306
    /**
307
     * @codeCoverageIgnore
308
     */
309
    public function getTotal()
310
    {
311
        return $this->total;
312
    }
313
}
314