1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Innmind\Immutable; |
4
|
|
|
|
5
|
|
|
use Innmind\Immutable\Exception\InvalidArgumentException; |
6
|
|
|
use Innmind\Immutable\Exception\BadMethodCallException; |
7
|
|
|
|
8
|
|
|
class TypedCollection extends Collection implements TypedCollectionInterface |
9
|
|
|
{ |
10
|
|
|
private $type; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Constructor |
14
|
|
|
* |
15
|
|
|
* @param string $type The class every element must respect |
16
|
|
|
* @param array $values |
17
|
|
|
*/ |
18
|
63 |
|
public function __construct($type, array $values) |
19
|
|
|
{ |
20
|
63 |
|
$type = (string) $type; |
21
|
63 |
|
$this->validate($type, $values); |
22
|
|
|
|
23
|
62 |
|
$this->type = $type; |
24
|
62 |
|
parent::__construct($values); |
25
|
62 |
|
} |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* {@inheritdoc} |
29
|
|
|
*/ |
30
|
57 |
|
public function getType() |
31
|
|
|
{ |
32
|
57 |
|
return $this->type; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* {@inheritdoc} |
37
|
|
|
*/ |
38
|
1 |
|
public function filter(callable $filter = null) |
39
|
|
|
{ |
40
|
1 |
|
return new self( |
41
|
1 |
|
$this->type, |
42
|
1 |
|
parent::filter($filter)->toPrimitive() |
43
|
1 |
|
); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* {@inheritdoc} |
48
|
|
|
*/ |
49
|
3 |
|
public function intersect(CollectionInterface $collection) |
50
|
|
|
{ |
51
|
3 |
|
$this->validateCollection($collection); |
52
|
|
|
|
53
|
1 |
|
return new self( |
54
|
1 |
|
$this->type, |
55
|
1 |
|
parent::intersect($collection)->toPrimitive() |
56
|
1 |
|
); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* {@inheritdoc} |
61
|
|
|
*/ |
62
|
2 |
|
public function chunk($size) |
63
|
|
|
{ |
64
|
2 |
|
$chunks = parent::chunk($size); |
65
|
2 |
|
$subs = []; |
66
|
|
|
|
67
|
2 |
|
foreach ($chunks as $chunk) { |
68
|
2 |
|
$subs[] = new self( |
69
|
2 |
|
$this->type, |
70
|
2 |
|
$chunk->toPrimitive() |
71
|
2 |
|
); |
72
|
2 |
|
} |
73
|
|
|
|
74
|
2 |
|
return new parent($subs); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* {@inheritdoc} |
79
|
|
|
*/ |
80
|
1 |
|
public function shift() |
81
|
|
|
{ |
82
|
1 |
|
return new self( |
83
|
1 |
|
$this->type, |
84
|
1 |
|
parent::shift()->toPrimitive() |
85
|
1 |
|
); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* {@inheritdoc} |
90
|
|
|
*/ |
91
|
1 |
|
public function uintersect(CollectionInterface $collection, callable $intersecter) |
92
|
|
|
{ |
93
|
1 |
|
$this->validateCollection($collection); |
94
|
|
|
|
95
|
1 |
|
return new self( |
96
|
1 |
|
$this->type, |
97
|
1 |
|
parent::uintersect($collection, $intersecter)->toPrimitive() |
98
|
1 |
|
); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* {@inheritdoc} |
103
|
|
|
*/ |
104
|
2 |
|
public function keyIntersect(CollectionInterface $collection) |
105
|
|
|
{ |
106
|
2 |
|
$this->validateCollection($collection); |
107
|
|
|
|
108
|
1 |
|
return new self( |
109
|
1 |
|
$this->type, |
110
|
1 |
|
parent::keyIntersect($collection)->toPrimitive() |
111
|
1 |
|
); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* {@inheritdoc} |
116
|
|
|
*/ |
117
|
1 |
|
public function map(callable $mapper) |
118
|
|
|
{ |
119
|
1 |
|
return new self( |
120
|
1 |
|
$this->type, |
121
|
1 |
|
parent::map($mapper)->toPrimitive() |
122
|
1 |
|
); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* {@inheritdoc} |
127
|
|
|
*/ |
128
|
2 |
View Code Duplication |
public function pad($size, $value) |
|
|
|
|
129
|
|
|
{ |
130
|
2 |
|
$this->validate($this->type, [$value]); |
131
|
|
|
|
132
|
1 |
|
return new self( |
133
|
1 |
|
$this->type, |
134
|
1 |
|
parent::pad($size, $value)->toPrimitive() |
135
|
1 |
|
); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* {@inheritdoc} |
140
|
|
|
*/ |
141
|
1 |
|
public function pop() |
142
|
|
|
{ |
143
|
1 |
|
return new self( |
144
|
1 |
|
$this->type, |
145
|
1 |
|
parent::pop()->toPrimitive() |
146
|
1 |
|
); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* {@inheritdoc} |
151
|
|
|
*/ |
152
|
2 |
|
public function diff(CollectionInterface $collection) |
153
|
|
|
{ |
154
|
2 |
|
$this->validateCollection($collection); |
155
|
|
|
|
156
|
1 |
|
return new self( |
157
|
1 |
|
$this->type, |
158
|
1 |
|
parent::diff($collection)->toPrimitive() |
159
|
1 |
|
); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* {@inheritdoc} |
164
|
|
|
*/ |
165
|
2 |
View Code Duplication |
public function push($value) |
|
|
|
|
166
|
|
|
{ |
167
|
2 |
|
$this->validate($this->type, [$value]); |
168
|
|
|
|
169
|
1 |
|
return new self( |
170
|
1 |
|
$this->type, |
171
|
1 |
|
parent::push($value)->toPrimitive() |
172
|
1 |
|
); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* {@inheritdoc} |
177
|
|
|
*/ |
178
|
2 |
|
public function rand($num = 1) |
179
|
|
|
{ |
180
|
2 |
|
return new self( |
181
|
2 |
|
$this->type, |
182
|
2 |
|
parent::rand($num)->toPrimitive() |
183
|
1 |
|
); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* {@inheritdoc} |
188
|
|
|
*/ |
189
|
2 |
|
public function merge(CollectionInterface $collection) |
190
|
|
|
{ |
191
|
2 |
|
$this->validateCollection($collection); |
192
|
|
|
|
193
|
1 |
|
return new self( |
194
|
1 |
|
$this->type, |
195
|
1 |
|
parent::merge($collection)->toPrimitive() |
196
|
1 |
|
); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* {@inheritdoc} |
201
|
|
|
*/ |
202
|
1 |
|
public function slice($offset, $length = null, $preserveKeys = false) |
203
|
|
|
{ |
204
|
1 |
|
return new self( |
205
|
1 |
|
$this->type, |
206
|
1 |
|
parent::slice($offset, $length, $preserveKeys)->toPrimitive() |
207
|
1 |
|
); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* {@inheritdoc} |
212
|
|
|
*/ |
213
|
2 |
|
public function udiff(CollectionInterface $collection, callable $differ) |
214
|
|
|
{ |
215
|
2 |
|
$this->validateCollection($collection); |
216
|
|
|
|
217
|
1 |
|
return new self( |
218
|
1 |
|
$this->type, |
219
|
1 |
|
parent::udiff($collection, $differ)->toPrimitive() |
220
|
1 |
|
); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* {@inheritdoc} |
225
|
|
|
*/ |
226
|
1 |
|
public function splice($offset, $length = 0, $replacement = []) |
227
|
|
|
{ |
228
|
1 |
|
return new self( |
229
|
1 |
|
$this->type, |
230
|
1 |
|
parent::splice($offset, $length, $replacement)->toPrimitive() |
231
|
1 |
|
); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* {@inheritdoc} |
236
|
|
|
*/ |
237
|
1 |
|
public function unique($flags = SORT_REGULAR) |
238
|
|
|
{ |
239
|
1 |
|
return new self( |
240
|
1 |
|
$this->type, |
241
|
1 |
|
parent::unique($flags)->toPrimitive() |
242
|
1 |
|
); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* {@inheritdoc} |
247
|
|
|
*/ |
248
|
1 |
|
public function values() |
249
|
|
|
{ |
250
|
1 |
|
return new self( |
251
|
1 |
|
$this->type, |
252
|
1 |
|
parent::values()->toPrimitive() |
253
|
1 |
|
); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* {@inheritdoc} |
258
|
|
|
*/ |
259
|
2 |
|
public function replace(CollectionInterface $collection) |
260
|
|
|
{ |
261
|
2 |
|
$this->validateCollection($collection); |
262
|
|
|
|
263
|
1 |
|
return new self( |
264
|
1 |
|
$this->type, |
265
|
1 |
|
parent::replace($collection)->toPrimitive() |
266
|
1 |
|
); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* {@inheritdoc} |
271
|
|
|
*/ |
272
|
1 |
|
public function reverse($preserveKeys = false) |
273
|
|
|
{ |
274
|
1 |
|
return new self( |
275
|
1 |
|
$this->type, |
276
|
1 |
|
parent::reverse($preserveKeys)->toPrimitive() |
277
|
1 |
|
); |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* {@inheritdoc} |
282
|
|
|
*/ |
283
|
2 |
View Code Duplication |
public function unshift($value) |
|
|
|
|
284
|
|
|
{ |
285
|
2 |
|
$this->validate($this->type, [$value]); |
286
|
|
|
|
287
|
1 |
|
return new self( |
288
|
1 |
|
$this->type, |
289
|
1 |
|
parent::unshift($value)->toPrimitive() |
290
|
1 |
|
); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* {@inheritdoc} |
295
|
|
|
*/ |
296
|
2 |
|
public function keyDiff(CollectionInterface $collection) |
297
|
|
|
{ |
298
|
2 |
|
$this->validateCollection($collection); |
299
|
|
|
|
300
|
1 |
|
return new self( |
301
|
1 |
|
$this->type, |
302
|
1 |
|
parent::keyDiff($collection)->toPrimitive() |
303
|
1 |
|
); |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* {@inheritdoc} |
308
|
|
|
*/ |
309
|
2 |
|
public function ukeyDiff(CollectionInterface $collection, callable $differ) |
310
|
|
|
{ |
311
|
2 |
|
$this->validateCollection($collection); |
312
|
|
|
|
313
|
1 |
|
return new self( |
314
|
1 |
|
$this->type, |
315
|
1 |
|
parent::ukeyDiff($collection, $differ)->toPrimitive() |
316
|
1 |
|
); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* {@inheritdoc} |
321
|
|
|
*/ |
322
|
2 |
|
public function associativeDiff(CollectionInterface $collection) |
323
|
|
|
{ |
324
|
2 |
|
$this->validateCollection($collection); |
325
|
|
|
|
326
|
1 |
|
return new self( |
327
|
1 |
|
$this->type, |
328
|
1 |
|
parent::associativeDiff($collection)->toPrimitive() |
329
|
1 |
|
); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* {@inheritdoc} |
334
|
|
|
*/ |
335
|
2 |
|
public function ukeyIntersect(CollectionInterface $collection, callable $intersecter) |
336
|
|
|
{ |
337
|
2 |
|
$this->validateCollection($collection); |
338
|
|
|
|
339
|
1 |
|
return new self( |
340
|
1 |
|
$this->type, |
341
|
1 |
|
parent::ukeyIntersect($collection, $intersecter)->toPrimitive() |
342
|
1 |
|
); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* {@inheritdoc} |
347
|
|
|
*/ |
348
|
2 |
|
public function associativeIntersect(CollectionInterface $collection) |
349
|
|
|
{ |
350
|
2 |
|
$this->validateCollection($collection); |
351
|
|
|
|
352
|
1 |
|
return new self( |
353
|
1 |
|
$this->type, |
354
|
1 |
|
parent::associativeIntersect($collection)->toPrimitive() |
355
|
1 |
|
); |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
/** |
359
|
|
|
* {@inheritdoc} |
360
|
|
|
*/ |
361
|
1 |
|
public function sort($flags = SORT_REGULAR) |
362
|
|
|
{ |
363
|
1 |
|
return new self( |
364
|
1 |
|
$this->type, |
365
|
1 |
|
parent::sort($flags)->toPrimitive() |
366
|
1 |
|
); |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* {@inheritdoc} |
371
|
|
|
*/ |
372
|
1 |
|
public function associativeSort($flags = SORT_REGULAR) |
373
|
|
|
{ |
374
|
1 |
|
return new self( |
375
|
1 |
|
$this->type, |
376
|
1 |
|
parent::associativeSort($flags)->toPrimitive() |
377
|
1 |
|
); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* {@inheritdoc} |
382
|
|
|
*/ |
383
|
1 |
|
public function keySort($flags = SORT_REGULAR) |
384
|
|
|
{ |
385
|
1 |
|
return new self( |
386
|
1 |
|
$this->type, |
387
|
1 |
|
parent::keySort($flags)->toPrimitive() |
388
|
1 |
|
); |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* {@inheritdoc} |
393
|
|
|
*/ |
394
|
1 |
|
public function ukeySort(callable $sorter) |
395
|
|
|
{ |
396
|
1 |
|
return new self( |
397
|
1 |
|
$this->type, |
398
|
1 |
|
parent::ukeySort($sorter)->toPrimitive() |
399
|
1 |
|
); |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
/** |
403
|
|
|
* {@inheritdoc} |
404
|
|
|
*/ |
405
|
1 |
|
public function reverseSort($flags = SORT_REGULAR) |
406
|
|
|
{ |
407
|
1 |
|
return new self( |
408
|
1 |
|
$this->type, |
409
|
1 |
|
parent::reverseSort($flags)->toPrimitive() |
410
|
1 |
|
); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
|
|
* {@inheritdoc} |
415
|
|
|
*/ |
416
|
1 |
|
public function usort(callable $sorter) |
417
|
|
|
{ |
418
|
1 |
|
return new self( |
419
|
1 |
|
$this->type, |
420
|
1 |
|
parent::usort($sorter)->toPrimitive() |
421
|
1 |
|
); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* {@inheritdoc} |
426
|
|
|
*/ |
427
|
1 |
|
public function associativeReverseSort($flags = SORT_REGULAR) |
428
|
|
|
{ |
429
|
1 |
|
return new self( |
430
|
1 |
|
$this->type, |
431
|
1 |
|
parent::associativeReverseSort($flags)->toPrimitive() |
432
|
1 |
|
); |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* {@inheritdoc} |
437
|
|
|
*/ |
438
|
1 |
|
public function keyReverseSort($flags = SORT_REGULAR) |
439
|
|
|
{ |
440
|
1 |
|
return new self( |
441
|
1 |
|
$this->type, |
442
|
1 |
|
parent::keyReverseSort($flags)->toPrimitive() |
443
|
1 |
|
); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* {@inheritdoc} |
448
|
|
|
*/ |
449
|
1 |
|
public function uassociativeSort(callable $sorter) |
450
|
|
|
{ |
451
|
1 |
|
return new self( |
452
|
1 |
|
$this->type, |
453
|
1 |
|
parent::uassociativeSort($sorter)->toPrimitive() |
454
|
1 |
|
); |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* {@inheritdoc} |
459
|
|
|
*/ |
460
|
1 |
|
public function naturalSort() |
461
|
|
|
{ |
462
|
1 |
|
return new self( |
463
|
1 |
|
$this->type, |
464
|
1 |
|
parent::naturalSort()->toPrimitive() |
465
|
1 |
|
); |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* {@inheritdoc} |
470
|
|
|
*/ |
471
|
1 |
|
public function shuffle() |
472
|
|
|
{ |
473
|
1 |
|
return new self( |
474
|
1 |
|
$this->type, |
475
|
1 |
|
parent::shuffle()->toPrimitive() |
476
|
1 |
|
); |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
/** |
480
|
|
|
* {@inheritdoc} |
481
|
|
|
*/ |
482
|
1 |
|
public function take($size, $preserveKeys = false) |
483
|
|
|
{ |
484
|
1 |
|
return new self( |
485
|
1 |
|
$this->type, |
486
|
1 |
|
parent::take($size, $preserveKeys)->toPrimitive() |
487
|
1 |
|
); |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
/** |
491
|
|
|
* {@inheritdoc} |
492
|
|
|
*/ |
493
|
1 |
|
public function grep($pattern, $revert = false) |
494
|
|
|
{ |
495
|
1 |
|
return new self( |
496
|
1 |
|
$this->type, |
497
|
1 |
|
parent::grep($pattern, $revert)->toPrimitive() |
498
|
1 |
|
); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* Check if every element respect the given type |
503
|
|
|
* |
504
|
|
|
* @throws InvalidArgumentException If a value doesn't respect the type |
505
|
|
|
* |
506
|
|
|
* @param string $type |
507
|
|
|
* @param array $values |
508
|
|
|
* |
509
|
|
|
* @return void |
510
|
|
|
*/ |
511
|
63 |
|
protected function validate($type, array $values) |
512
|
|
|
{ |
513
|
63 |
|
foreach ($values as $value) { |
514
|
51 |
|
if (!$value instanceof $type) { |
515
|
4 |
|
throw new InvalidArgumentException(sprintf( |
516
|
4 |
|
'Each value must be an instance of "%s"', |
517
|
|
|
$type |
518
|
4 |
|
)); |
519
|
|
|
} |
520
|
62 |
|
} |
521
|
62 |
|
} |
522
|
|
|
|
523
|
|
|
/** |
524
|
|
|
* Check if the given collection is compatible with the current one |
525
|
|
|
* |
526
|
|
|
* @throws BadMethodCallException If the collection is not compatible |
527
|
|
|
* |
528
|
|
|
* @param CollectionInterface $collection |
529
|
|
|
* |
530
|
|
|
* @return void |
531
|
|
|
*/ |
532
|
24 |
|
private function validateCollection(CollectionInterface $collection) |
533
|
|
|
{ |
534
|
|
|
if ( |
535
|
24 |
|
!$collection instanceof self || |
536
|
24 |
|
$collection->getType() !== $this->type |
537
|
24 |
|
) { |
538
|
12 |
|
throw new BadMethodCallException( |
539
|
|
|
'The given collection is not compatible' |
540
|
12 |
|
); |
541
|
|
|
} |
542
|
12 |
|
} |
543
|
|
|
} |
544
|
|
|
|
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.