Skip to content

Commit

Permalink
Non-sequential arrays are forbidden.
Browse files Browse the repository at this point in the history
  • Loading branch information
Smoren committed Mar 10, 2024
1 parent e743191 commit b3cfef4
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@ public static function normalizeIndex(int $index, int $containerLength, bool $th
}
return $index < 0 ? $containerLength + $index : $index;
}

public static function isArraySequential(array $source): bool
{
if (!function_exists('array_is_list')) {
return array_keys($source) === range(0, count($source) - 1);
}
return array_is_list($source);
}
}
5 changes: 5 additions & 0 deletions src/Views/ArrayView.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Smoren\ArrayView\Exceptions\LengthError;
use Smoren\ArrayView\Exceptions\NotSupportedError;
use Smoren\ArrayView\Exceptions\ReadonlyError;
use Smoren\ArrayView\Exceptions\ValueError;
use Smoren\ArrayView\Interfaces\ArraySelectorInterface;
use Smoren\ArrayView\Interfaces\ArrayViewInterface;
use Smoren\ArrayView\Selectors\MaskSelector;
Expand Down Expand Up @@ -57,6 +58,10 @@ public static function toView(&$source, ?bool $readonly = null): ArrayView
*/
public function __construct(&$source, ?bool $readonly = null)
{
if (is_array($source) && !Util::isArraySequential($source)) {
throw new ValueError('Cannot create view for non-sequential array.');
}

$this->source = &$source;
$this->readonly = $readonly ?? (($source instanceof ArrayViewInterface) ? $source->isReadonly() : false);
$this->parentView = ($source instanceof ArrayViewInterface) ? $source : null;
Expand Down
60 changes: 60 additions & 0 deletions tests/unit/ArrayView/NonSequentialErrorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Smoren\ArrayView\Tests\Unit\ArrayView;

use Smoren\ArrayView\Exceptions\ValueError;
use Smoren\ArrayView\Views\ArrayView;

class NonSequentialErrorTest extends \Codeception\Test\Unit
{
/**
* @dataProvider dataProviderForNonSequentialError
*/
public function testNonSequentialError(callable $arrayGetter)
{
$nonSequentialArray = $arrayGetter();
$this->expectException(ValueError::class);
ArrayView::toView($nonSequentialArray);
}

public function dataProviderForNonSequentialError(): array
{
return [
[fn () => ['test' => 1]],
[fn () => [1 => 1]],
[fn () => [0 => 1, 2 => 2]],
[fn () => [0 => 1, -1 => 2]],
[fn () => [0 => 1, 'a' => 2]],
[static function () {
$array = [1, 2, 3, 4, 5];
unset($array[0]);
return $array;
}],
[static function () {
$array = [1, 2, 3, 4, 5];
unset($array[1]);
return $array;
}],
[static function () {
$array = [1, 2, 3, 4, 5];
$array[6] = 111;
return $array;
}],
[static function () {
$array = [1, 2, 3, 4, 5];
$array[-1] = 111;
return $array;
}],
[static function () {
$array = [1, 2, 3, 4, 5];
$array[-2] = 111;
return $array;
}],
[static function () {
$array = [1, 2, 3, 4, 5];
$array['test'] = 111;
return $array;
}],
];
}
}

0 comments on commit b3cfef4

Please sign in to comment.