Skip to content

Commit fa2ab39

Browse files
authored
SafeAssocList (#2)
* SafeAssocList * Add Travis
1 parent 1e628da commit fa2ab39

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language: php
2+
3+
php:
4+
- 7.4
5+
6+
install:
7+
- composer install --dev
8+
9+
script:
10+
- ./vendor/bin/phpunit tests

src/SafeAccessorTrait.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,15 @@ public function array(string $key): SafeAssocArray
171171

172172
return SafeAssocArray::from($value);
173173
}
174+
175+
public function list(string $key): SafeAssocList
176+
{
177+
$value = $this->value($key, null) ?? [];
178+
179+
if (!is_array($value)) {
180+
throw new InvalidArgumentException("Value of {$key} cannot be array");
181+
}
182+
183+
return SafeAssocList::fromArray($value);
184+
}
174185
}

src/SafeAssocList.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace GW\Safe;
4+
5+
use Countable;
6+
use function array_filter;
7+
use function array_map;
8+
use function array_values;
9+
use function count;
10+
11+
final class SafeAssocList implements Countable
12+
{
13+
/** @var SafeAssocArray[] */
14+
private array $items;
15+
16+
private function __construct(SafeAssocArray ...$items)
17+
{
18+
$this->items = $items;
19+
}
20+
21+
public static function from(SafeAssocArray ...$items): self
22+
{
23+
return new self(...$items);
24+
}
25+
26+
/** @param array<int, array<string|int, mixed>> $items */
27+
public static function fromArray(array $items): self
28+
{
29+
return self::from(
30+
...array_map([SafeAssocArray::class, 'from'], array_values(array_filter($items, 'is_array')))
31+
);
32+
}
33+
34+
/** @return SafeAssocArray[] */
35+
public function toArray(): array
36+
{
37+
return $this->items;
38+
}
39+
40+
public function count(): int
41+
{
42+
return count($this->items);
43+
}
44+
45+
/**
46+
* @template T
47+
* @phpstan-param callable(SafeAssocArray):T $map
48+
* @phpstan-return T[]
49+
*/
50+
public function map(callable $map): array
51+
{
52+
return array_map($map, $this->items);
53+
}
54+
55+
/**
56+
* @phpstan-param callable(SafeAssocArray):bool $filter
57+
* @phpstan-return T[]
58+
*/
59+
public function filter(callable $filter): self
60+
{
61+
return new self(...array_values(array_filter($this->items, $filter)));
62+
}
63+
}

tests/SafeAssocListTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace tests\GW\Safe;
4+
5+
use GW\Safe\SafeAssocArray;
6+
use GW\Safe\SafeAssocList;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class SafeAssocListTest extends TestCase
10+
{
11+
function test_from()
12+
{
13+
$john = SafeAssocArray::from(['name' => 'John']);
14+
$mary = SafeAssocArray::from(['name' => 'Mary']);
15+
$list = SafeAssocList::from($john, $mary);
16+
17+
self::assertEquals([$john, $mary], $list->toArray());
18+
}
19+
20+
function test_to_array()
21+
{
22+
$arrayList = SafeAssocList::fromArray([['name' => 'John'], ['name' => 'Mary']])->toArray();
23+
24+
self::assertContainsOnly(SafeAssocArray::class, $arrayList);
25+
self::assertEquals('John', $arrayList[0]->string('name'));
26+
self::assertEquals('Mary', $arrayList[1]->string('name'));
27+
self::assertEquals('???', $arrayList[1]->string('age', '???'));
28+
}
29+
30+
function test_count()
31+
{
32+
self::assertCount(3, SafeAssocList::fromArray([[], [], []]));
33+
}
34+
35+
function test_filter()
36+
{
37+
$list = SafeAssocList::fromArray(
38+
[
39+
['name' => 'John', 'age' => 30],
40+
['name' => 'Mary', 'age' => 28],
41+
['name' => 'Kevin', 'age' => 8]
42+
]
43+
)->filter(fn(SafeAssocArray $person): bool => $person->int('age', 0) > 18);
44+
45+
self::assertCount(2, $list);
46+
}
47+
48+
function test_map()
49+
{
50+
$names = SafeAssocList::fromArray(
51+
[
52+
['name' => 'John', 'age' => 30],
53+
['name' => 'Mary', 'age' => 28],
54+
['age' => 0],
55+
]
56+
)->map(fn(SafeAssocArray $person): string => $person->string('name', 'unknown'));
57+
58+
self::assertEquals(['John', 'Mary', 'unknown'], $names);
59+
}
60+
}

0 commit comments

Comments
 (0)