Skip to content

Commit 95d0a6e

Browse files
committed
Fix __construct(): add value type assertion
1 parent 88f4d26 commit 95d0a6e

File tree

24 files changed

+691
-48
lines changed

24 files changed

+691
-48
lines changed

src/Collection/AbstractCollection.php

+11-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626

2727
abstract class AbstractCollection implements CollectionInterface
2828
{
29+
/**
30+
* @param mixed $value
31+
* @return static<mixed>
32+
*/
33+
abstract protected function assertValueType($value): self;
34+
2935
/** @var array<string|int, mixed> */
3036
protected array $values = [];
3137

@@ -334,7 +340,9 @@ public function end(): CollectionInterface
334340
*/
335341
protected function doAdd($value): CollectionInterface
336342
{
337-
$this->assertIsNotReadOnly();
343+
$this
344+
->assertIsNotReadOnly()
345+
->assertValueType($value);
338346

339347
if ($this->canAddValue($value)) {
340348
$this->values[] = $value;
@@ -352,7 +360,8 @@ protected function doSet($key, $value): CollectionInterface
352360
{
353361
$this
354362
->assertIsNotReadOnly()
355-
->assertKeyType($key);
363+
->assertKeyType($key)
364+
->assertValueType($value);
356365

357366
if ($this->canAddValue($value)) {
358367
$this->values[$key] = $value;

src/Collection/AbstractObjectCollection.php

-23
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,6 @@ public function getComparisonMode(): int
2424
return $this->comparisonMode;
2525
}
2626

27-
/**
28-
* @param mixed $value
29-
* @return static<mixed>
30-
*/
31-
protected function doAdd($value): self
32-
{
33-
$this->assertValueType($value);
34-
35-
return parent::doAdd($value);
36-
}
37-
38-
/**
39-
* @param string|int $key
40-
* @param mixed $value
41-
* @return static<mixed>
42-
*/
43-
protected function doSet($key, $value): self
44-
{
45-
$this->assertValueType($value);
46-
47-
return parent::doSet($key, $value);
48-
}
49-
5027
/** @return static<mixed> */
5128
protected function doSetComparisonMode(int $mode): self
5229
{

src/Collection/AbstractScalarCollection.php

-23
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,6 @@ public function isAllowFloat(): bool
3030
return $this->allowFloat;
3131
}
3232

33-
/**
34-
* @param string|int $key
35-
* @param mixed $value
36-
* @return static<mixed>
37-
*/
38-
protected function doSet($key, $value): self
39-
{
40-
$this->assertValueType($value);
41-
42-
return parent::doSet($key, $value);
43-
}
44-
45-
/**
46-
* @param mixed $value
47-
* @return static<mixed>
48-
*/
49-
protected function doAdd($value): self
50-
{
51-
$this->assertValueType($value);
52-
53-
return parent::doAdd($value);
54-
}
55-
5633
/**
5734
* @param mixed $value
5835
* @return static<mixed>

src/Collection/FloatCollection.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpPp\Core\Component\Collection;
66

7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
78
use PhpPp\Core\Contract\Collection\FloatCollectionInterface;
89

910
class FloatCollection extends AbstractCollection implements FloatCollectionInterface
@@ -60,4 +61,14 @@ public function toArray(): array
6061
{
6162
return $this->values;
6263
}
64+
65+
/** @return static */
66+
protected function assertValueType($value): self
67+
{
68+
if (is_float($value) === false) {
69+
throw InvalidValueTypeException::createFromAllowedTypes(new StringCollection(['float']));
70+
}
71+
72+
return $this;
73+
}
6374
}

src/Collection/FloatNullableCollection.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpPp\Core\Component\Collection;
66

7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
78
use PhpPp\Core\Contract\Collection\FloatNullableCollectionInterface;
89

910
class FloatNullableCollection extends AbstractCollection implements FloatNullableCollectionInterface
@@ -60,4 +61,14 @@ public function toArray(): array
6061
{
6162
return $this->values;
6263
}
64+
65+
/** @return static */
66+
protected function assertValueType($value): self
67+
{
68+
if (is_float($value) === false && is_null($value) === false) {
69+
throw InvalidValueTypeException::createFromAllowedTypes(new StringCollection(['float', 'null']));
70+
}
71+
72+
return $this;
73+
}
6374
}

src/Collection/IntegerCollection.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpPp\Core\Component\Collection;
66

7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
78
use PhpPp\Core\Contract\Collection\IntegerCollectionInterface;
89

910
class IntegerCollection extends AbstractCollection implements IntegerCollectionInterface
@@ -62,4 +63,14 @@ public function toArray(): array
6263
{
6364
return $this->values;
6465
}
66+
67+
/** @return static */
68+
protected function assertValueType($value): self
69+
{
70+
if (is_int($value) === false) {
71+
throw InvalidValueTypeException::createFromAllowedTypes(new StringCollection(['integer']));
72+
}
73+
74+
return $this;
75+
}
6576
}

src/Collection/IntegerNullableCollection.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpPp\Core\Component\Collection;
66

7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
78
use PhpPp\Core\Contract\Collection\IntegerNullableCollectionInterface;
89

910
class IntegerNullableCollection extends AbstractCollection implements IntegerNullableCollectionInterface
@@ -60,4 +61,14 @@ public function toArray(): array
6061
{
6162
return $this->values;
6263
}
64+
65+
/** @return static */
66+
protected function assertValueType($value): self
67+
{
68+
if (is_int($value) === false && is_null($value) === false) {
69+
throw InvalidValueTypeException::createFromAllowedTypes(new StringCollection(['integer', 'null']));
70+
}
71+
72+
return $this;
73+
}
6374
}

src/Collection/StringCollection.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpPp\Core\Component\Collection;
66

7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
78
use PhpPp\Core\Contract\Collection\StringCollectionInterface;
89

910
class StringCollection extends AbstractCollection implements StringCollectionInterface
@@ -62,4 +63,14 @@ public function toArray(): array
6263
{
6364
return $this->values;
6465
}
66+
67+
/** @return static */
68+
protected function assertValueType($value): self
69+
{
70+
if (is_string($value) === false) {
71+
throw InvalidValueTypeException::createFromAllowedTypes(new StringCollection(['string']));
72+
}
73+
74+
return $this;
75+
}
6576
}

src/Collection/StringNullableCollection.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpPp\Core\Component\Collection;
66

7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
78
use PhpPp\Core\Contract\Collection\StringNullableCollectionInterface;
89

910
class StringNullableCollection extends AbstractCollection implements StringNullableCollectionInterface
@@ -60,4 +61,14 @@ public function toArray(): array
6061
{
6162
return $this->values;
6263
}
64+
65+
/** @return static */
66+
protected function assertValueType($value): self
67+
{
68+
if (is_string($value) === false && is_null($value) === false) {
69+
throw InvalidValueTypeException::createFromAllowedTypes(new StringCollection(['string', 'null']));
70+
}
71+
72+
return $this;
73+
}
6374
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpPp\Core\Component\Tests\Unit\Collection;
6+
7+
use PhpPp\Core\Component\Exception\Collection\InvalidValueTypeException;
8+
use PhpPp\Core\Contract\Collection\CollectionInterface;
9+
use PHPUnit\Framework\TestCase;
10+
11+
abstract class AbstractConstructTest extends TestCase
12+
{
13+
/**
14+
* @param array<string|int, mixed> $values
15+
* @return CollectionInterface<mixed>
16+
*/
17+
abstract protected function createCollection(array $values): CollectionInterface;
18+
19+
abstract protected function getExceptionMessage(): string;
20+
21+
public function testString(): void
22+
{
23+
$this->expectException(InvalidValueTypeException::class);
24+
$this->expectExceptionCode(0);
25+
$this->expectExceptionMessage($this->getExceptionMessage());
26+
27+
$this->createCollection(['foo']);
28+
}
29+
30+
public function testInteger(): void
31+
{
32+
$this->expectException(InvalidValueTypeException::class);
33+
$this->expectExceptionCode(0);
34+
$this->expectExceptionMessage($this->getExceptionMessage());
35+
36+
$this->createCollection([1]);
37+
}
38+
39+
public function testFloat(): void
40+
{
41+
$this->expectException(InvalidValueTypeException::class);
42+
$this->expectExceptionCode(0);
43+
$this->expectExceptionMessage($this->getExceptionMessage());
44+
45+
$this->createCollection([1.1]);
46+
}
47+
48+
public function testTrue(): void
49+
{
50+
$this->expectException(InvalidValueTypeException::class);
51+
$this->expectExceptionCode(0);
52+
$this->expectExceptionMessage($this->getExceptionMessage());
53+
54+
$this->createCollection([true]);
55+
}
56+
57+
public function testFalse(): void
58+
{
59+
$this->expectException(InvalidValueTypeException::class);
60+
$this->expectExceptionCode(0);
61+
$this->expectExceptionMessage($this->getExceptionMessage());
62+
63+
$this->createCollection([false]);
64+
}
65+
66+
public function testStdClass(): void
67+
{
68+
$this->expectException(InvalidValueTypeException::class);
69+
$this->expectExceptionCode(0);
70+
$this->expectExceptionMessage($this->getExceptionMessage());
71+
72+
$this->createCollection([new \stdClass()]);
73+
}
74+
75+
public function testNull(): void
76+
{
77+
if ($this->isAllowNull()) {
78+
$collection = $this->createCollection([null]);
79+
80+
static::assertNull($collection->toArray()[0]);
81+
} else {
82+
$this->expectException(InvalidValueTypeException::class);
83+
$this->expectExceptionCode(0);
84+
$this->expectExceptionMessage($this->getExceptionMessage());
85+
86+
$this->createCollection([null]);
87+
}
88+
}
89+
90+
protected function isAllowNull(): bool
91+
{
92+
return false;
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpPp\Core\Component\Tests\Unit\Collection\DateTimeCollection;
6+
7+
use PhpPp\Core\Component\{
8+
Collection\DateTimeCollection,
9+
Tests\Unit\Collection\AbstractConstructTest
10+
};
11+
use PhpPp\Core\Contract\Collection\CollectionInterface;
12+
13+
/** @covers \PhpPp\Core\Component\Collection\DateTimeCollection::__construct */
14+
final class ConstructTest extends AbstractConstructTest
15+
{
16+
public function testDateTime(): void
17+
{
18+
$dateTime = new \DateTime();
19+
$collection = new DateTimeCollection([$dateTime]);
20+
21+
static::assertSame($dateTime, $collection->get(0));
22+
}
23+
24+
/** @param array<string|int, mixed> $values */
25+
protected function createCollection(array $values): CollectionInterface
26+
{
27+
return new DateTimeCollection($values);
28+
}
29+
30+
protected function getExceptionMessage(): string
31+
{
32+
return 'Value should be instance of DateTime.';
33+
}
34+
}

0 commit comments

Comments
 (0)