Completed
Push — master ( be0408...83aa6c )
by Mārtiņš
04:43
created

Collection::replaceEntity()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 6
Ratio 40 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
dl 6
loc 15
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 2
crap 2
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();
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 actualy population of data from the given array in blueprint */
53 1 View Code Duplication
    private function populateEntity($instance, $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 ((array) $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 12
    public function addEntity(HasId $entity, $key = null)
70
    {
71
72 12
        if (is_null($key) === false) {
73 2
            $this->replaceEntity($entity, $key);
74 2
            return;
75
        }
76
77 11
        $id = $entity->getId();
78
79 11
        $this->pool[] = $entity;
80
81 11
        $this->indexed[$id] = $entity;
82 11
        $this->map[$id] = $this->retrieveLastPoolKey();
83 11
    }
84
85
86 2
    private function replaceEntity(HasId $entity, $key)
87
    {
88 2 View Code Duplication
        if (isset($this->pool[$key])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
89 1
            $id = $this->pool[$key]->getId();
90
91 1
            unset($this->indexed[$id]);
92 1
            unset($this->map[$id]);
93
        }
94
95 2
        $id = $entity->getId();
96
97 2
        $this->pool[$key] = $entity;
98 2
        $this->indexed[$id] = $entity;
99 2
        $this->map[$id] = $key;
100 2
    }
101
102
103 11
    private function retrieveLastPoolKey()
104
    {
105 11
        end($this->pool);
106 11
        return key($this->pool);
107
    }
108
109
110
    /**
111
     * Method for getting an ordered list of IDs for items in the collection.
112
     *
113
     * @return array
114
     */
115 4
    public function getIds()
116
    {
117 4
        $keys = array_keys($this->indexed);
118 4
        sort($keys);
119 4
        return $keys;
120
    }
121
122
123
    /**
124
     * Replaces all of the domain entities with a content of some other collection
125
     *
126
     * @param Collection $replacement
127
     */
128 1
    public function replaceWith(Collection $replacement)
129
    {
130 1
        $this->pool = [];
131 1
        $this->map = [];
132 1
        $this->indexed = [];
133
134 1
        foreach ($replacement as $entity) {
135 1
            $this->addEntity($entity);
136
        }
137
138 1
    }
139
140
141
    /**
142
     * Removes an entity from collection.
143
     *
144
     * @param HasId $entity
145
     */
146 3
    public function removeEntity(HasId $entity)
147
    {
148 3
        $key = $entity->getId();
149
150 3 View Code Duplication
        if ($key !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
151 3
            unset($this->indexed[$key]);
152 3
            unset($this->pool[$this->map[$key]]);
153 3
            unset($this->map[$key]);
154
        }
155 3
    }
156
157
158
    /**
159
     * Removes all od the content of the collection and resets it to pristine state.
160
     */
161 1
    public function purge()
162
    {
163 1
        $this->pool = [];
164 1
        $this->indexed = [];
165 1
        $this->map = [];
166 1
        $this->position = 0;
167 1
    }
168
169
170
    // imeplementing Countable
171 2
    public function count()
172
    {
173 2
        return count($this->pool);
174
    }
175
176
177
    // implementing Iterator
178 2
    public function rewind()
179
    {
180 2
        $this->position = 0;
181 2
    }
182
183
184 2
    public function current()
185
    {
186 2
        return $this->pool[$this->position];
187
    }
188
189
190
    /**
191
     * @codeCoverageIgnore
192
     */
193
    public function key()
194
    {
195
        return $this->position;
196
    }
197
198
199 2
    public function next()
200
    {
201 2
        ++$this->position;
202 2
    }
203
204
205 2
    public function valid()
206
    {
207 2
        return isset($this->pool[$this->position]);
208
    }
209
210
211
    // implementing ArrayAccess
212 9
    public function offsetSet($offset, $value)
213
    {
214 9
        $this->addEntity($value, $offset);
215 9
    }
216
217
218 1
    public function offsetExists($offset)
219
    {
220 1
        return isset($this->pool[$offset]);
221
    }
222
223
224 3
    public function offsetUnset($offset)
225
    {
226 3
        $this->removeEntity($this->pool[$offset]);
227 3
    }
228
229
230 5
    public function offsetGet($offset)
231
    {
232 5
        if (isset($this->pool[$offset])) {
233 5
            return $this->pool[$offset];
234
        }
235
236 2
        return null;
237
    }
238
239
240
    // pagination
241
242 1
    public function setOffset($offset)
243
    {
244 1
        $data = (int) $offset;
245
246 1
        if ($data < 0) {
247 1
            $data = 0;
248
        }
249
250 1
        $this->offset = $data;
251 1
    }
252
253
254
    /**
255
     * @codeCoverageIgnore
256
     */
257
    public function getOffset()
258
    {
259
        return $this->offset;
260
    }
261
262
263 1
    public function setLimit($limit)
264
    {
265 1
        $data = (int) $limit;
266
267 1
        if ($data < 0) {
268 1
            $data = 0;
269
        }
270
271 1
        $this->limit = $data;
272 1
    }
273
274
275
    /**
276
     * @codeCoverageIgnore
277
     */
278
    public function getLimit()
279
    {
280
        return $this->limit;
281
    }
282
283
284 1
    public function setTotal($total)
285
    {
286 1
        $data = (int) $total;
287
288 1
        if ($data < 0) {
289 1
            $data = 0;
290
        }
291
292 1
        $this->total = $data;
293 1
    }
294
295
296
    /**
297
     * @codeCoverageIgnore
298
     */
299
    public function getTotal()
300
    {
301
        return $this->total;
302
    }
303
}
304