diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 0895782c..82fd93ba 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -26,15 +26,6 @@
is_object($options)
-
-
- setList
- setStrict
-
-
- (bool) $strict
-
-
$typeOrOptions
@@ -977,17 +968,6 @@
-
- $strict
-
-
- $expected
- $value
-
-
- $data
- [$value, $expected]
-
defaultTestProvider
listTestProvider
diff --git a/src/AllowList.php b/src/AllowList.php
index d9393c15..4a59a0dd 100644
--- a/src/AllowList.php
+++ b/src/AllowList.php
@@ -5,53 +5,58 @@
namespace Laminas\Filter;
use Laminas\Stdlib\ArrayUtils;
-use Traversable;
+use function array_values;
use function in_array;
use function is_array;
/**
* @psalm-type Options = array{
* strict?: bool,
- * list?: array,
- * ...
+ * list?: iterable,
* }
- * @extends AbstractFilter
*/
-final class AllowList extends AbstractFilter
+final class AllowList implements FilterInterface
{
- /** @var bool */
- protected $strict = false;
+ private bool $strict = false;
+ /** @var list */
+ private array $list = [];
- /** @var array */
- protected $list = [];
+ /**
+ * @param Options $options
+ */
+ public function __construct(array $options = [])
+ {
+ $this->setOptions($options);
+ }
/**
- * @param null|array|Traversable $options
+ * @param Options $options
+ * @return $this
*/
- public function __construct($options = null)
+ public function setOptions(array $options = []): self
{
- if (null !== $options) {
- $this->setOptions($options);
- }
+ $strict = $options['strict'] ?? false;
+ $list = $options['list'] ?? [];
+
+ $this->setStrict($strict);
+ $this->setList($list);
+
+ return $this;
}
/**
* Determine whether the in_array() call should be "strict" or not. See in_array docs.
- *
- * @param bool $strict
*/
- public function setStrict($strict = true): void
+ public function setStrict(bool $strict): void
{
- $this->strict = (bool) $strict;
+ $this->strict = $strict;
}
/**
* Returns whether the in_array() call should be "strict" or not. See in_array docs.
- *
- * @return bool
*/
- public function getStrict()
+ public function getStrict(): bool
{
return $this->strict;
}
@@ -59,23 +64,23 @@ public function getStrict()
/**
* Set the list of items to allow
*
- * @param array|Traversable $list
+ * @param iterable $list
*/
- public function setList($list = []): void
+ public function setList(iterable $list = []): void
{
if (! is_array($list)) {
$list = ArrayUtils::iteratorToArray($list);
}
- $this->list = $list;
+ $this->list = array_values($list);
}
/**
* Get the list of items to allow
*
- * @return array
+ * @return list
*/
- public function getList()
+ public function getList(): array
{
return $this->list;
}
@@ -91,6 +96,18 @@ public function getList()
*/
public function filter(mixed $value): mixed
{
- return in_array($value, $this->getList(), $this->getStrict()) ? $value : null;
+ return in_array($value, $this->list, $this->strict) ? $value : null;
+ }
+
+ /**
+ * Will return $value if its present in the allow-list. If $value is rejected then it will return null.
+ *
+ * @template T
+ * @param T $value
+ * @return T|null
+ */
+ public function __invoke(mixed $value): mixed
+ {
+ return $this->filter($value);
}
}
diff --git a/test/AllowListTest.php b/test/AllowListTest.php
index d22c3581..866ee055 100644
--- a/test/AllowListTest.php
+++ b/test/AllowListTest.php
@@ -8,11 +8,13 @@
use Laminas\Filter\FilterPluginManager;
use Laminas\ServiceManager\ServiceManager;
use Laminas\Stdlib\ArrayObject;
-use Laminas\Stdlib\Exception;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
+use TypeError;
+use function assert;
use function gettype;
+use function is_array;
use function sprintf;
use function var_export;
@@ -45,14 +47,6 @@ public function testWithPluginManager(): void
self::assertInstanceOf(AllowListFilter::class, $filter);
}
- public function testNullListShouldThrowException(): void
- {
- $this->expectException(Exception\InvalidArgumentException::class);
- new AllowListFilter([
- 'list' => null,
- ]);
- }
-
public function testTraversableConvertsToArray(): void
{
$array = ['test', 1];
@@ -63,12 +57,13 @@ public function testTraversableConvertsToArray(): void
self::assertSame($array, $filter->getList());
}
- public function testSetStrictShouldCastToBoolean(): void
+ public function testSetStrictShouldBeBoolean(): void
{
- $filter = new AllowListFilter([
+ $this->expectException(TypeError::class);
+ /** @psalm-suppress InvalidArgument */
+ new AllowListFilter([
'strict' => 1,
]);
- self::assertSame(true, $filter->getStrict());
}
#[DataProvider('defaultTestProvider')]
@@ -78,6 +73,10 @@ public function testDefault(mixed $value): void
self::assertNull($filter->filter($value));
}
+ /**
+ * @param list $list
+ * @param array{0: mixed, 1: mixed} $testData
+ */
#[DataProvider('listTestProvider')]
public function testList(bool $strict, array $list, array $testData): void
{
@@ -86,13 +85,14 @@ public function testList(bool $strict, array $list, array $testData): void
'list' => $list,
]);
foreach ($testData as $data) {
+ assert(is_array($data));
[$value, $expected] = $data;
$message = sprintf(
'%s (%s) is not filtered as %s; type = %s',
var_export($value, true),
gettype($value),
var_export($expected, true),
- $strict
+ $strict ? 'strict' : 'non-strict',
);
self::assertSame($expected, $filter->filter($value), $message);
}
@@ -110,7 +110,7 @@ public static function defaultTestProvider(): array
];
}
- /** @return list */
+ /** @return list, 2: list}> */
public static function listTestProvider(): array
{
return [
@@ -141,4 +141,25 @@ public static function listTestProvider(): array
],
];
}
+
+ public function testStrictModeCanBeSetAtRuntime(): void
+ {
+ $filter = new AllowListFilter();
+
+ $filter->setStrict(true);
+ self::assertTrue($filter->getStrict());
+ }
+
+ public function testListCanBeSetAtRuntime(): void
+ {
+ $filter = new AllowListFilter();
+ $filter->setList(['foo', 'bar']);
+ self::assertSame(['foo', 'bar'], $filter->getList());
+ }
+
+ public function testFilterCanBeInvoked(): void
+ {
+ $filter = new AllowListFilter(['list' => ['foo']]);
+ self::assertSame('foo', $filter->__invoke('foo'));
+ }
}