Skip to content

Commit b3cfef4

Browse files
committed
Non-sequential arrays are forbidden.
1 parent e743191 commit b3cfef4

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

src/Util.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,12 @@ public static function normalizeIndex(int $index, int $containerLength, bool $th
1414
}
1515
return $index < 0 ? $containerLength + $index : $index;
1616
}
17+
18+
public static function isArraySequential(array $source): bool
19+
{
20+
if (!function_exists('array_is_list')) {
21+
return array_keys($source) === range(0, count($source) - 1);
22+
}
23+
return array_is_list($source);
24+
}
1725
}

src/Views/ArrayView.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Smoren\ArrayView\Exceptions\LengthError;
1010
use Smoren\ArrayView\Exceptions\NotSupportedError;
1111
use Smoren\ArrayView\Exceptions\ReadonlyError;
12+
use Smoren\ArrayView\Exceptions\ValueError;
1213
use Smoren\ArrayView\Interfaces\ArraySelectorInterface;
1314
use Smoren\ArrayView\Interfaces\ArrayViewInterface;
1415
use Smoren\ArrayView\Selectors\MaskSelector;
@@ -57,6 +58,10 @@ public static function toView(&$source, ?bool $readonly = null): ArrayView
5758
*/
5859
public function __construct(&$source, ?bool $readonly = null)
5960
{
61+
if (is_array($source) && !Util::isArraySequential($source)) {
62+
throw new ValueError('Cannot create view for non-sequential array.');
63+
}
64+
6065
$this->source = &$source;
6166
$this->readonly = $readonly ?? (($source instanceof ArrayViewInterface) ? $source->isReadonly() : false);
6267
$this->parentView = ($source instanceof ArrayViewInterface) ? $source : null;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Smoren\ArrayView\Tests\Unit\ArrayView;
4+
5+
use Smoren\ArrayView\Exceptions\ValueError;
6+
use Smoren\ArrayView\Views\ArrayView;
7+
8+
class NonSequentialErrorTest extends \Codeception\Test\Unit
9+
{
10+
/**
11+
* @dataProvider dataProviderForNonSequentialError
12+
*/
13+
public function testNonSequentialError(callable $arrayGetter)
14+
{
15+
$nonSequentialArray = $arrayGetter();
16+
$this->expectException(ValueError::class);
17+
ArrayView::toView($nonSequentialArray);
18+
}
19+
20+
public function dataProviderForNonSequentialError(): array
21+
{
22+
return [
23+
[fn () => ['test' => 1]],
24+
[fn () => [1 => 1]],
25+
[fn () => [0 => 1, 2 => 2]],
26+
[fn () => [0 => 1, -1 => 2]],
27+
[fn () => [0 => 1, 'a' => 2]],
28+
[static function () {
29+
$array = [1, 2, 3, 4, 5];
30+
unset($array[0]);
31+
return $array;
32+
}],
33+
[static function () {
34+
$array = [1, 2, 3, 4, 5];
35+
unset($array[1]);
36+
return $array;
37+
}],
38+
[static function () {
39+
$array = [1, 2, 3, 4, 5];
40+
$array[6] = 111;
41+
return $array;
42+
}],
43+
[static function () {
44+
$array = [1, 2, 3, 4, 5];
45+
$array[-1] = 111;
46+
return $array;
47+
}],
48+
[static function () {
49+
$array = [1, 2, 3, 4, 5];
50+
$array[-2] = 111;
51+
return $array;
52+
}],
53+
[static function () {
54+
$array = [1, 2, 3, 4, 5];
55+
$array['test'] = 111;
56+
return $array;
57+
}],
58+
];
59+
}
60+
}

0 commit comments

Comments
 (0)