Skip to content

Commit f0c7765

Browse files
authored
Merge pull request #25 from worksolutions/array-strict-list
Array Strict List implementation
2 parents 4ee1ca0 + dab532a commit f0c7765

File tree

8 files changed

+199
-0
lines changed

8 files changed

+199
-0
lines changed

src/WS/Utils/Collections/AbstractCollection.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ public function add($element): bool
3030
}
3131
$this->pointer++;
3232
$this->elements[] = $element;
33+
$this->afterElementAdd($element);
3334
return true;
3435
}
3536

3637
public function addAll(iterable $elements): bool
3738
{
3839
foreach ($elements as $element) {
3940
$this->elements[] = $element;
41+
$this->afterElementAdd($element);
4042
}
4143
$newPointer = count($this->elements) - 1;
4244
if ($newPointer > PHP_INT_MAX) {
@@ -96,12 +98,17 @@ protected function setElements(array $elements): void
9698
{
9799
$this->elements = array_values($elements);
98100
$this->pointer = count($elements) - 1;
101+
$this->afterElementsSet();
99102
}
100103

101104
protected function getElements(): array
102105
{
103106
return $this->elements;
104107
}
105108

109+
abstract protected function afterElementAdd($element): void;
110+
111+
abstract protected function afterElementsSet(): void;
112+
106113
abstract public function stream(): Stream;
107114
}

src/WS/Utils/Collections/ArrayList.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function set($element, int $index)
2727
}
2828
$res = $this->elements[$index];
2929
$this->elements[$index] = $element;
30+
$this->afterElementAdd($element);
3031

3132
return $res;
3233
}
@@ -89,4 +90,12 @@ private function removeThroughHashCode(HashCodeAware $element): bool
8990
}
9091
return false;
9192
}
93+
94+
protected function afterElementAdd($element): void
95+
{
96+
}
97+
98+
protected function afterElementsSet(): void
99+
{
100+
}
92101
}

src/WS/Utils/Collections/ArrayQueue.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,12 @@ public function getIndexIterator(): Iterator
4747
{
4848
return IteratorFactory::directSequence($this->size());
4949
}
50+
51+
protected function afterElementAdd($element): void
52+
{
53+
}
54+
55+
protected function afterElementsSet(): void
56+
{
57+
}
5058
}

src/WS/Utils/Collections/ArrayStack.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,12 @@ public function getIndexIterator(): Iterator
6969
{
7070
return IteratorFactory::reverseSequence($this->size());
7171
}
72+
73+
protected function afterElementAdd($element): void
74+
{
75+
}
76+
77+
protected function afterElementsSet(): void
78+
{
79+
}
7280
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/**
3+
* @author Anton Lytkin <a.lytkin@worksolutions.ru>
4+
*/
5+
6+
namespace WS\Utils\Collections;
7+
8+
use InvalidArgumentException;
9+
10+
class ArrayStrictList extends ArrayList
11+
{
12+
protected function afterElementsSet(): void
13+
{
14+
foreach ($this->elements as $element) {
15+
$this->afterElementAdd($element);
16+
}
17+
parent::afterElementsSet();
18+
}
19+
20+
protected function afterElementAdd($element): void
21+
{
22+
$firstElement = $this->elements[0];
23+
if (null === $firstElement && !count($this->elements)) {
24+
return;
25+
}
26+
if (is_object($firstElement)) {
27+
if (!is_object($element) || (get_class($firstElement) !== get_class($element))) {
28+
throw new InvalidArgumentException('Collection must contain elements with identical types');
29+
}
30+
return;
31+
}
32+
if (is_object($element) || (gettype($firstElement) !== gettype($element))) {
33+
throw new InvalidArgumentException('Collection must contain elements with identical types');
34+
}
35+
parent::afterElementAdd($element);
36+
}
37+
}

src/WS/Utils/Collections/CollectionFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ public static function from(array $values): Collection
6363
return new ArrayList($values);
6464
}
6565

66+
public static function fromStrict(array $values): Collection
67+
{
68+
return new ArrayStrictList($values);
69+
}
70+
6671
public static function fromIterable(iterable $iterable): Collection
6772
{
6873
$list = ArrayList::of();
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
/**
3+
* @author Anton Lytkin <a.lytkin@worksolutions.ru>
4+
*/
5+
6+
namespace WS\Utils\Collections;
7+
8+
use InvalidArgumentException;
9+
use PHPUnit\Framework\TestCase;
10+
11+
class ArrayStrictListTest extends TestCase
12+
{
13+
public function createInstance(...$args): ListSequence
14+
{
15+
return ArrayStrictList::of(...$args);
16+
}
17+
18+
public function strictCases(): array
19+
{
20+
return [
21+
[1, 2, 3],
22+
[1.1, 2.2, 3.3],
23+
['one', 'two', 'three'],
24+
[true, false, true],
25+
[[1], ['2'], [3.3]],
26+
[null, null, null],
27+
[
28+
function () {
29+
return '1';
30+
},
31+
function () {
32+
return 'two';
33+
},
34+
function () {
35+
return 3;
36+
},
37+
],
38+
[
39+
$object = new class () {},
40+
clone $object,
41+
clone $object,
42+
],
43+
];
44+
}
45+
46+
public function notStrictCases(): array
47+
{
48+
return [
49+
[1, '2', 3],
50+
[1.1, 2.2, 3],
51+
['one', 'two', 3.3],
52+
['true', false, true],
53+
[[1], null, [3.3]],
54+
[null, null, []],
55+
[
56+
function () {
57+
return '1';
58+
},
59+
new class () {},
60+
function () {
61+
return 3;
62+
},
63+
],
64+
[
65+
$object = new class () {},
66+
clone $object,
67+
new class () {},
68+
],
69+
];
70+
}
71+
72+
/**
73+
* @test
74+
* @dataProvider strictCases
75+
* @doesNotPerformAssertions
76+
* @param $sequence
77+
*/
78+
public function creatingFromStrict(...$sequence): void
79+
{
80+
$this->createInstance(...$sequence);
81+
}
82+
83+
/**
84+
* @test
85+
* @dataProvider notStrictCases
86+
* @param $sequence
87+
*/
88+
public function creatingFromNotStrict(...$sequence): void
89+
{
90+
self::expectException(InvalidArgumentException::class);
91+
$this->createInstance(...$sequence);
92+
}
93+
94+
/**
95+
* @test
96+
*/
97+
public function addingElementsToStrictArray()
98+
{
99+
self::expectException(InvalidArgumentException::class);
100+
101+
$this
102+
->createInstance(1, 2, 3)
103+
->add('4');
104+
105+
$this
106+
->createInstance('one', 'two', 'three')
107+
->addAll(['4', 5, '6']);
108+
109+
$object = new class () {};
110+
$this
111+
->createInstance($object, clone $object, clone $object)
112+
->set(new class () {}, 2);
113+
}
114+
}

tests/WS/Utils/Collections/CollectionFactoryTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ public function creatingFromArray(): void
7171
$this->assertThat($collection, CollectionIsEqual::to([1, 2, 3]));
7272
}
7373

74+
/**
75+
* @test
76+
*/
77+
public function creatingFromStrictArray(): void
78+
{
79+
$collection = CollectionFactory::fromStrict([4, 5, 6]);
80+
81+
$this->assertEquals(3, $collection->size());
82+
$this->assertThat($collection, CollectionIsEqual::to([4, 5, 6]));
83+
}
84+
7485
/**
7586
* @test
7687
*/

0 commit comments

Comments
 (0)