Add Psalm tooling
This commit is contained in:
parent
7a8ac2f87a
commit
addf2e869d
|
@ -39,7 +39,8 @@
|
||||||
"phpstan/phpstan": "^1.10.56",
|
"phpstan/phpstan": "^1.10.56",
|
||||||
"phpstan/phpstan-strict-rules": "^1.5",
|
"phpstan/phpstan-strict-rules": "^1.5",
|
||||||
"friendsofphp/php-cs-fixer": "^3.48",
|
"friendsofphp/php-cs-fixer": "^3.48",
|
||||||
"squizlabs/php_codesniffer": "^3.8"
|
"squizlabs/php_codesniffer": "^3.8",
|
||||||
|
"vimeo/psalm": "^5.20"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<ignore-tag>extends</ignore-tag>
|
<ignore-tag>extends</ignore-tag>
|
||||||
<ignore-tag>implements</ignore-tag>
|
<ignore-tag>implements</ignore-tag>
|
||||||
<ignore-tag>phpstan-require-implements</ignore-tag>
|
<ignore-tag>phpstan-require-implements</ignore-tag>
|
||||||
|
<ignore-tag>psalm-suppress</ignore-tag>
|
||||||
</ignore-tags>
|
</ignore-tags>
|
||||||
</api>
|
</api>
|
||||||
<guide>
|
<guide>
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
|
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||||
|
errorLevel="1"
|
||||||
|
resolveFromConfigFile="true"
|
||||||
|
findUnusedBaselineEntry="true"
|
||||||
|
findUnusedCode="false"
|
||||||
|
>
|
||||||
|
<issueHandlers>
|
||||||
|
<RedundantCastGivenDocblockType errorLevel="suppress"/>
|
||||||
|
<RedundantConditionGivenDocblockType errorLevel="suppress"/>
|
||||||
|
<RedundantFunctionCallGivenDocblockType errorLevel="suppress"/>
|
||||||
|
</issueHandlers>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="src"/>
|
||||||
|
<ignoreFiles>
|
||||||
|
<directory name="vendor"/>
|
||||||
|
</ignoreFiles>
|
||||||
|
</projectFiles>
|
||||||
|
</psalm>
|
|
@ -23,110 +23,223 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
namespace OCC\Basics\DataStructures;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use Countable;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use Iterator;
|
||||||
|
use OutOfRangeException;
|
||||||
|
use RuntimeException;
|
||||||
use SplDoublyLinkedList;
|
use SplDoublyLinkedList;
|
||||||
use OCC\Basics\Traits\Getter;
|
use OCC\Basics\Traits\Getter;
|
||||||
|
use Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type-sensitive, taversable list.
|
* A type-sensitive, taversable list.
|
||||||
*
|
*
|
||||||
* Extends [\SplDoublyLinkedList](https://www.php.net/spldoublylinkedlist) with
|
* Extends [\SplDoublyLinkedList](https://www.php.net/spldoublylinkedlist) with
|
||||||
* an option to specify the allowed data types for list items.
|
* an option to specify the allowed data types for list values.
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\DataStructures
|
* @package Basics\DataStructures
|
||||||
*
|
*
|
||||||
* @property-read string[] $allowedTypes
|
* @property-read string[] $allowedTypes The allowed data types for values.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*
|
*
|
||||||
* @template AllowedType of mixed
|
* @template AllowedType of mixed
|
||||||
* @extends SplDoublyLinkedList<AllowedType>
|
* @extends SplDoublyLinkedList<AllowedType>
|
||||||
|
* @implements ArrayAccess<int, AllowedType>
|
||||||
|
* @implements Iterator<int, AllowedType>
|
||||||
*/
|
*/
|
||||||
class StrictList extends SplDoublyLinkedList
|
class StrictList extends SplDoublyLinkedList implements ArrayAccess, Countable, Iterator, Serializable
|
||||||
{
|
{
|
||||||
use Getter;
|
use Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the allowed data types for items.
|
* Queue style iterator mode (First In, First Out).
|
||||||
|
*/
|
||||||
|
public const IT_MODE_FIFO = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stack style iterator mode (Last In, First Out).
|
||||||
|
*/
|
||||||
|
public const IT_MODE_LIFO = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructive iterator mode (delete values after iteration).
|
||||||
|
*/
|
||||||
|
public const IT_MODE_DELETE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preserving iterator mode (keep values after iteration).
|
||||||
|
*/
|
||||||
|
public const IT_MODE_KEEP = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The allowed data types for values.
|
||||||
*
|
*
|
||||||
* @var string[]
|
* @var string[]
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
protected array $allowedTypes = [];
|
protected array $allowedTypes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add/insert a new item at the specified index.
|
* Add/insert a new value at the specified offset.
|
||||||
*
|
*
|
||||||
* @param int $index The index where the new item is to be inserted
|
* @param int $offset The offset where the new value is to be inserted
|
||||||
* @param AllowedType $item The new item for the index
|
* @param AllowedType $value The new value for the offset
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
public function add(int $index, mixed $item): void
|
public function add(int $offset, mixed $value): void
|
||||||
{
|
{
|
||||||
if (!$this->isAllowedType($item)) {
|
if (!$this->isAllowedType($value)) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Parameter 2 must be an allowed type, %s given.',
|
'Parameter 2 must be an allowed type, %s given.',
|
||||||
get_debug_type($item)
|
get_debug_type($value)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
parent::add($index, $item);
|
parent::add($offset, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append items at the end of the list.
|
* Append values at the end of the list.
|
||||||
*
|
*
|
||||||
* @param AllowedType ...$items One or more items to append
|
* @param AllowedType ...$values One or more values to append
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
public function append(mixed ...$items): void
|
public function append(mixed ...$values): void
|
||||||
{
|
{
|
||||||
foreach ($items as $count => $item) {
|
foreach ($values as $count => $value) {
|
||||||
if (!$this->isAllowedType($item)) {
|
if (!$this->isAllowedType($value)) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Parameter %d must be an allowed type, %s given.',
|
'Parameter %d must be an allowed type, %s given.',
|
||||||
(int) $count + 1,
|
(int) $count + 1,
|
||||||
get_debug_type($item)
|
get_debug_type($value)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($items as $item) {
|
foreach ($values as $value) {
|
||||||
parent::push($item);
|
parent::push($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the item's data type is allowed on the list.
|
* Peek at the value at the beginning of the list.
|
||||||
*
|
*
|
||||||
* @param AllowedType $item The item to check
|
* @return AllowedType The first value of the list
|
||||||
*
|
*
|
||||||
* @return bool Whether the item's data type is allowed
|
* @throws RuntimeException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
public function isAllowedType(mixed $item): bool
|
public function bottom(): mixed
|
||||||
|
{
|
||||||
|
return parent::bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of values on the list.
|
||||||
|
*
|
||||||
|
* @return int The current number of values
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function count(): int
|
||||||
|
{
|
||||||
|
return parent::count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current list value.
|
||||||
|
*
|
||||||
|
* @return AllowedType The current value
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function current(): mixed
|
||||||
|
{
|
||||||
|
return parent::current();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mode of iteration.
|
||||||
|
*
|
||||||
|
* @return int The set of flags and modes of iteration
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function getIteratorMode(): int
|
||||||
|
{
|
||||||
|
return parent::getIteratorMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the value's data type is allowed on the list.
|
||||||
|
*
|
||||||
|
* @param AllowedType $value The value to check
|
||||||
|
*
|
||||||
|
* @return bool Whether the value's data type is allowed
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function isAllowedType(mixed $value): bool
|
||||||
{
|
{
|
||||||
if (count($this->allowedTypes) === 0) {
|
if (count($this->allowedTypes) === 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
foreach ($this->allowedTypes as $type) {
|
foreach ($this->allowedTypes as $type) {
|
||||||
$function = 'is_' . $type;
|
$function = 'is_' . $type;
|
||||||
if (function_exists($function) && $function($item)) {
|
if (function_exists($function) && $function($value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/** @var class-string */
|
||||||
$fqcn = ltrim($type, '\\');
|
$fqcn = ltrim($type, '\\');
|
||||||
if (is_object($item) && is_a($item, $fqcn)) {
|
if (is_object($value) && is_a($value, $fqcn)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the list is empty.
|
||||||
|
*
|
||||||
|
* @return bool Whether the list is empty
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function isEmpty(): bool
|
||||||
|
{
|
||||||
|
return parent::isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current value's offset.
|
||||||
|
*
|
||||||
|
* @return int The current offset
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function key(): int
|
||||||
|
{
|
||||||
|
return parent::key();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic getter method for $this->allowedTypes.
|
* Magic getter method for $this->allowedTypes.
|
||||||
*
|
*
|
||||||
|
@ -140,93 +253,275 @@ class StrictList extends SplDoublyLinkedList
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the item at the specified index.
|
* Move cursor to the next value on the list.
|
||||||
*
|
|
||||||
* @param ?int $index The index being set or NULL to append
|
|
||||||
* @param AllowedType $item The new item for the index
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @api
|
||||||
*/
|
*/
|
||||||
public function offsetSet(mixed $index, mixed $item): void
|
public function next(): void
|
||||||
{
|
{
|
||||||
if (!$this->isAllowedType($item)) {
|
parent::next();
|
||||||
throw new InvalidArgumentException(
|
|
||||||
sprintf(
|
|
||||||
'Parameter 2 must be an allowed type, %s given.',
|
|
||||||
get_debug_type($item)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
parent::offsetSet($index, $item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepend items at the start of the list.
|
* Check if the specified offset exists.
|
||||||
*
|
*
|
||||||
* @param AllowedType ...$items One or more items to prepend
|
* @param int $offset The offset being checked
|
||||||
|
*
|
||||||
|
* @return bool Whether the offset exists
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function offsetExists(mixed $offset): bool
|
||||||
|
{
|
||||||
|
return parent::offsetExists($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value at the specified offset.
|
||||||
|
*
|
||||||
|
* @param int $offset The offset to get
|
||||||
|
*
|
||||||
|
* @return ?AllowedType The value at the offset or NULL
|
||||||
|
*
|
||||||
|
* @throws OutOfRangeException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function offsetGet(mixed $offset): mixed
|
||||||
|
{
|
||||||
|
return parent::offsetGet($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value at the specified offset.
|
||||||
|
*
|
||||||
|
* @param ?int $offset The offset being set or NULL to append
|
||||||
|
* @param AllowedType $value The new value for the offset
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
public function prepend(mixed ...$items): void
|
public function offsetSet(mixed $offset, mixed $value): void
|
||||||
{
|
{
|
||||||
foreach ($items as $count => $item) {
|
if (!$this->isAllowedType($value)) {
|
||||||
if (!$this->isAllowedType($item)) {
|
throw new InvalidArgumentException(
|
||||||
|
sprintf(
|
||||||
|
'Parameter 2 must be an allowed type, %s given.',
|
||||||
|
get_debug_type($value)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/** @psalm-suppress PossiblyNullArgument */
|
||||||
|
parent::offsetSet($offset, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unset the specified offset.
|
||||||
|
*
|
||||||
|
* @param int $offset The offset to unset
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws OutOfRangeException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function offsetUnset(mixed $offset): void
|
||||||
|
{
|
||||||
|
parent::offsetUnset($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops an value from the end of the list.
|
||||||
|
*
|
||||||
|
* @return AllowedType The value from the end of the list
|
||||||
|
*
|
||||||
|
* @throws RuntimeException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function pop(): mixed
|
||||||
|
{
|
||||||
|
return parent::pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend values at the start of the list.
|
||||||
|
*
|
||||||
|
* @param AllowedType ...$values One or more values to prepend
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function prepend(mixed ...$values): void
|
||||||
|
{
|
||||||
|
foreach ($values as $count => $value) {
|
||||||
|
if (!$this->isAllowedType($value)) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Parameter %d must be an allowed type, %s given.',
|
'Parameter %d must be an allowed type, %s given.',
|
||||||
(int) $count + 1,
|
(int) $count + 1,
|
||||||
get_debug_type($item)
|
get_debug_type($value)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($items as $item) {
|
foreach ($values as $value) {
|
||||||
parent::unshift($item);
|
parent::unshift($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push an item at the end of the list.
|
* Move cursor to the previous value on the list.
|
||||||
*
|
*
|
||||||
* @param AllowedType $item The item to push
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function prev(): void
|
||||||
|
{
|
||||||
|
parent::prev();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push an value at the end of the list.
|
||||||
|
*
|
||||||
|
* @param AllowedType $value The value to push
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
public function push(mixed $item): void
|
public function push(mixed $value): void
|
||||||
{
|
{
|
||||||
if (!$this->isAllowedType($item)) {
|
if (!$this->isAllowedType($value)) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Parameter 1 must be an allowed type, %s given.',
|
'Parameter 1 must be an allowed type, %s given.',
|
||||||
get_debug_type($item)
|
get_debug_type($value)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
parent::push($item);
|
parent::push($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move cursor back to the start of the list.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function rewind(): void
|
||||||
|
{
|
||||||
|
parent::rewind();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get string representation of $this.
|
* Get string representation of $this.
|
||||||
*
|
*
|
||||||
* @return string The string representation
|
* @return string The string representation
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function serialize(): string
|
public function serialize(): string
|
||||||
{
|
{
|
||||||
return serialize($this->__serialize());
|
return serialize($this->__serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set allowed data types of list values.
|
||||||
|
*
|
||||||
|
* @param string[] $allowedTypes Allowed data types of values
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function setAllowedTypes(array $allowedTypes = []): void
|
||||||
|
{
|
||||||
|
if (array_sum(array_map('is_string', $allowedTypes)) !== count($allowedTypes)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'Allowed types must be array of strings or empty array.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->allowedTypes = $allowedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mode of iteration.
|
||||||
|
*
|
||||||
|
* @param int $mode The new iterator mode (0, 1, 2 or 3)
|
||||||
|
*
|
||||||
|
* There are two orthogonal sets of modes that can be set.
|
||||||
|
*
|
||||||
|
* The direction of iteration (either one or the other):
|
||||||
|
* - StrictList::IT_MODE_FIFO (queue style)
|
||||||
|
* - StrictList::IT_MODE_LIFO (stack style)
|
||||||
|
*
|
||||||
|
* The behavior of the iterator (either one or the other):
|
||||||
|
* - StrictList::IT_MODE_DELETE (delete items)
|
||||||
|
* - StrictList::IT_MODE_KEEP (keep items)
|
||||||
|
*
|
||||||
|
* The default mode is: IT_MODE_FIFO | IT_MODE_KEEP
|
||||||
|
*
|
||||||
|
* @return int The set of flags and modes of iteration
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function setIteratorMode(int $mode): int
|
||||||
|
{
|
||||||
|
return parent::setIteratorMode($mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift an value from the beginning of the list.
|
||||||
|
*
|
||||||
|
* @return AllowedType The first value of the list
|
||||||
|
*
|
||||||
|
* @throws RuntimeException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function shift(): mixed
|
||||||
|
{
|
||||||
|
return parent::shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek at the value at the end of the list.
|
||||||
|
*
|
||||||
|
* @return AllowedType The last value of the list
|
||||||
|
*
|
||||||
|
* @throws RuntimeException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function top(): mixed
|
||||||
|
{
|
||||||
|
return parent::top();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore $this from string representation.
|
* Restore $this from string representation.
|
||||||
*
|
*
|
||||||
* @param string $data The string representation
|
* @param string $data The string representation
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function unserialize($data): void
|
public function unserialize($data): void
|
||||||
{
|
{
|
||||||
|
@ -236,31 +531,46 @@ class StrictList extends SplDoublyLinkedList
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepend the list with an item.
|
* Prepend the list with an value.
|
||||||
*
|
*
|
||||||
* @param AllowedType $item The item to unshift
|
* @param AllowedType $value The value to unshift
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
public function unshift(mixed $item): void
|
public function unshift(mixed $value): void
|
||||||
{
|
{
|
||||||
if (!$this->isAllowedType($item)) {
|
if (!$this->isAllowedType($value)) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Parameter 1 must be an allowed type, %s given.',
|
'Parameter 1 must be an allowed type, %s given.',
|
||||||
get_debug_type($item)
|
get_debug_type($value)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
parent::unshift($item);
|
parent::unshift($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a type-sensitive, traversable list of items.
|
* Check if the list contains any more values.
|
||||||
|
*
|
||||||
|
* @return bool Whether the list contains more values
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function valid(): bool
|
||||||
|
{
|
||||||
|
return parent::valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a type-sensitive, traversable list of values.
|
||||||
|
*
|
||||||
|
* @param string[] $allowedTypes Allowed data types of values (optional)
|
||||||
*
|
*
|
||||||
* @param string[] $allowedTypes Allowed data types of items (optional)
|
|
||||||
* If empty, all types are allowed.
|
* If empty, all types are allowed.
|
||||||
* Possible values are:
|
* Possible values are:
|
||||||
* - "array"
|
* - "array"
|
||||||
|
@ -277,16 +587,13 @@ class StrictList extends SplDoublyLinkedList
|
||||||
* - "scalar"
|
* - "scalar"
|
||||||
* - "string"
|
* - "string"
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function __construct(array $allowedTypes = [])
|
public function __construct(array $allowedTypes = [])
|
||||||
{
|
{
|
||||||
if (array_sum(array_map('is_string', $allowedTypes)) !== count($allowedTypes)) {
|
$this->setAllowedTypes($allowedTypes);
|
||||||
throw new InvalidArgumentException(
|
|
||||||
'Allowed types must be array of strings or empty array.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$this->allowedTypes = $allowedTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -325,15 +632,17 @@ class StrictList extends SplDoublyLinkedList
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
|
*
|
||||||
|
* @psalm-suppress MethodSignatureMismatch
|
||||||
*/
|
*/
|
||||||
public function __unserialize(array $data): void
|
public function __unserialize(array $data): void
|
||||||
{
|
{
|
||||||
/** @var string[] $allowedTypes */
|
/** @var string[] $allowedTypes */
|
||||||
$allowedTypes = $data['StrictList::allowedTypes'];
|
$allowedTypes = $data['StrictList::allowedTypes'];
|
||||||
$this->__construct($allowedTypes);
|
$this->setAllowedTypes($allowedTypes);
|
||||||
/** @var iterable<AllowedType> $items */
|
/** @var array<int, AllowedType> $values */
|
||||||
$items = $data['SplDoublyLinkedList::dllist'];
|
$values = $data['SplDoublyLinkedList::dllist'];
|
||||||
$this->append(...$items);
|
$this->append(...$values);
|
||||||
/** @var int $flags */
|
/** @var int $flags */
|
||||||
$flags = $data['SplDoublyLinkedList::flags'];
|
$flags = $data['SplDoublyLinkedList::flags'];
|
||||||
$this->setIteratorMode($flags);
|
$this->setIteratorMode($flags);
|
||||||
|
|
|
@ -23,10 +23,14 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
namespace OCC\Basics\DataStructures;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use Countable;
|
||||||
|
use Iterator;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
use Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type-sensitive, taversable First In, First Out Queue (FIFO).
|
* A type-sensitive, taversable First In, First Out queue (FIFO).
|
||||||
*
|
*
|
||||||
* Extends [\SplQueue](https://www.php.net/splqueue) with an option to specify
|
* Extends [\SplQueue](https://www.php.net/splqueue) with an option to specify
|
||||||
* the allowed data types for list items.
|
* the allowed data types for list items.
|
||||||
|
@ -34,12 +38,14 @@ use RuntimeException;
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\DataStructures
|
* @package Basics\DataStructures
|
||||||
*
|
*
|
||||||
* @property-read string[] $allowedTypes
|
* @api
|
||||||
*
|
*
|
||||||
* @template AllowedType of mixed
|
* @template AllowedType of mixed
|
||||||
* @extends StrictList<AllowedType>
|
* @extends StrictList<AllowedType>
|
||||||
|
* @implements ArrayAccess<int, AllowedType>
|
||||||
|
* @implements Iterator<int, AllowedType>
|
||||||
*/
|
*/
|
||||||
class StrictQueue extends StrictList
|
class StrictQueue extends StrictList implements ArrayAccess, Countable, Iterator, Serializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Dequeue an item from the queue.
|
* Dequeue an item from the queue.
|
||||||
|
@ -70,6 +76,17 @@ class StrictQueue extends StrictList
|
||||||
*
|
*
|
||||||
* @param int $mode The new iterator mode (0 or 1)
|
* @param int $mode The new iterator mode (0 or 1)
|
||||||
*
|
*
|
||||||
|
* There are two orthogonal sets of modes that can be set.
|
||||||
|
*
|
||||||
|
* The direction of iteration (fixed for StrictQueue):
|
||||||
|
* - StrictQueue::IT_MODE_FIFO (queue style)
|
||||||
|
*
|
||||||
|
* The behavior of the iterator (either one or the other):
|
||||||
|
* - StrictQueue::IT_MODE_DELETE (delete items)
|
||||||
|
* - StrictQueue::IT_MODE_KEEP (keep items)
|
||||||
|
*
|
||||||
|
* The default mode is: IT_MODE_FIFO | IT_MODE_KEEP
|
||||||
|
*
|
||||||
* @return int The set of flags and modes of iteration
|
* @return int The set of flags and modes of iteration
|
||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
@ -91,6 +108,7 @@ class StrictQueue extends StrictList
|
||||||
* Create a type-sensitive, traversable queue of items.
|
* Create a type-sensitive, traversable queue of items.
|
||||||
*
|
*
|
||||||
* @param string[] $allowedTypes Allowed data types of items (optional)
|
* @param string[] $allowedTypes Allowed data types of items (optional)
|
||||||
|
*
|
||||||
* If empty, all types are allowed.
|
* If empty, all types are allowed.
|
||||||
* Possible values are:
|
* Possible values are:
|
||||||
* - "array"
|
* - "array"
|
||||||
|
@ -107,6 +125,8 @@ class StrictQueue extends StrictList
|
||||||
* - "scalar"
|
* - "scalar"
|
||||||
* - "string"
|
* - "string"
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function __construct(array $allowedTypes = [])
|
public function __construct(array $allowedTypes = [])
|
||||||
|
|
|
@ -23,10 +23,14 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
namespace OCC\Basics\DataStructures;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use Countable;
|
||||||
|
use Iterator;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
use Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type-sensitive, taversable Last In, First Out Stack (LIFO).
|
* A type-sensitive, taversable Last In, First Out stack (LIFO).
|
||||||
*
|
*
|
||||||
* Extends [\SplStack](https://www.php.net/splstack) with an option to specify
|
* Extends [\SplStack](https://www.php.net/splstack) with an option to specify
|
||||||
* the allowed data types for list items.
|
* the allowed data types for list items.
|
||||||
|
@ -34,12 +38,14 @@ use RuntimeException;
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\DataStructures
|
* @package Basics\DataStructures
|
||||||
*
|
*
|
||||||
* @property-read string[] $allowedTypes
|
* @api
|
||||||
*
|
*
|
||||||
* @template AllowedType of mixed
|
* @template AllowedType of mixed
|
||||||
* @extends StrictList<AllowedType>
|
* @extends StrictList<AllowedType>
|
||||||
|
* @implements ArrayAccess<int, AllowedType>
|
||||||
|
* @implements Iterator<int, AllowedType>
|
||||||
*/
|
*/
|
||||||
class StrictStack extends StrictList
|
class StrictStack extends StrictList implements ArrayAccess, Countable, Iterator, Serializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Add an item to the stack.
|
* Add an item to the stack.
|
||||||
|
@ -70,6 +76,17 @@ class StrictStack extends StrictList
|
||||||
*
|
*
|
||||||
* @param int $mode The new iterator mode (2 or 3)
|
* @param int $mode The new iterator mode (2 or 3)
|
||||||
*
|
*
|
||||||
|
* There are two orthogonal sets of modes that can be set.
|
||||||
|
*
|
||||||
|
* The direction of iteration (fixed for StrictStack):
|
||||||
|
* - StrictStack::IT_MODE_LIFO (stack style)
|
||||||
|
*
|
||||||
|
* The behavior of the iterator (either one or the other):
|
||||||
|
* - StrictStack::IT_MODE_DELETE (delete items)
|
||||||
|
* - StrictStack::IT_MODE_KEEP (keep items)
|
||||||
|
*
|
||||||
|
* The default mode is: IT_MODE_LIFO | IT_MODE_KEEP
|
||||||
|
*
|
||||||
* @return int The set of flags and modes of iteration
|
* @return int The set of flags and modes of iteration
|
||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
@ -91,6 +108,7 @@ class StrictStack extends StrictList
|
||||||
* Create a type-sensitive, traversable stack of items.
|
* Create a type-sensitive, traversable stack of items.
|
||||||
*
|
*
|
||||||
* @param string[] $allowedTypes Allowed data types of items (optional)
|
* @param string[] $allowedTypes Allowed data types of items (optional)
|
||||||
|
*
|
||||||
* If empty, all types are allowed.
|
* If empty, all types are allowed.
|
||||||
* Possible values are:
|
* Possible values are:
|
||||||
* - "array"
|
* - "array"
|
||||||
|
@ -107,6 +125,8 @@ class StrictStack extends StrictList
|
||||||
* - "scalar"
|
* - "scalar"
|
||||||
* - "string"
|
* - "string"
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function __construct(array $allowedTypes = [])
|
public function __construct(array $allowedTypes = [])
|
||||||
|
|
|
@ -32,6 +32,8 @@ use ErrorException;
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\ErrorHandlers
|
* @package Basics\ErrorHandlers
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
class ThrowErrorException
|
class ThrowErrorException
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,8 @@ use Throwable;
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\ErrorHandlers
|
* @package Basics\ErrorHandlers
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
class TriggerExceptionError
|
class TriggerExceptionError
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,25 +23,32 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\InterfaceTraits;
|
namespace OCC\Basics\InterfaceTraits;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic implementation of the ArrayAccess interface.
|
* A generic implementation of the ArrayAccess interface.
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\InterfaceTraits
|
* @package Basics\InterfaceTraits
|
||||||
*
|
*
|
||||||
* @phpstan-require-implements \ArrayAccess
|
* @template TKey of int|string
|
||||||
|
* @template TValue of mixed
|
||||||
|
* @implements ArrayAccess<TKey, TValue>
|
||||||
|
* @phpstan-require-implements ArrayAccess
|
||||||
*/
|
*/
|
||||||
trait ArrayAccess
|
trait ArrayAccessTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Holds the array-accessible data.
|
* Holds the array-accessible data.
|
||||||
|
*
|
||||||
|
* @var array<TKey, TValue>
|
||||||
*/
|
*/
|
||||||
private array $data = [];
|
protected array $data = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the specified offset exists.
|
* Check if the specified offset exists.
|
||||||
*
|
*
|
||||||
* @param mixed $offset The offset to check for
|
* @param TKey $offset The offset to check for
|
||||||
*
|
*
|
||||||
* @return bool Whether the offset exists
|
* @return bool Whether the offset exists
|
||||||
*/
|
*/
|
||||||
|
@ -53,9 +60,9 @@ trait ArrayAccess
|
||||||
/**
|
/**
|
||||||
* Retrieve data at the specified offset.
|
* Retrieve data at the specified offset.
|
||||||
*
|
*
|
||||||
* @param mixed $offset The offset to retrieve at
|
* @param TKey $offset The offset to retrieve at
|
||||||
*
|
*
|
||||||
* @return mixed The value at the offset or NULL
|
* @return ?TValue The value at the offset or NULL
|
||||||
*/
|
*/
|
||||||
public function offsetGet(mixed $offset): mixed
|
public function offsetGet(mixed $offset): mixed
|
||||||
{
|
{
|
||||||
|
@ -65,8 +72,8 @@ trait ArrayAccess
|
||||||
/**
|
/**
|
||||||
* Assign a value to the specified offset.
|
* Assign a value to the specified offset.
|
||||||
*
|
*
|
||||||
* @param mixed $offset The offset to assign to or NULL to append
|
* @param ?TKey $offset The offset to assign to or NULL to append
|
||||||
* @param mixed $value The value to set
|
* @param TValue $value The value to set
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
@ -82,7 +89,7 @@ trait ArrayAccess
|
||||||
/**
|
/**
|
||||||
* Unset the specified offset.
|
* Unset the specified offset.
|
||||||
*
|
*
|
||||||
* @param mixed $offset The offset to unset
|
* @param TKey $offset The offset to unset
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
|
@ -23,20 +23,27 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\InterfaceTraits;
|
namespace OCC\Basics\InterfaceTraits;
|
||||||
|
|
||||||
|
use Countable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic implementation of the Countable interface.
|
* A generic implementation of the Countable interface.
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\InterfaceTraits
|
* @package Basics\InterfaceTraits
|
||||||
*
|
*
|
||||||
* @phpstan-require-implements \Countable
|
* @template TKey of int|string
|
||||||
|
* @template TValue of mixed
|
||||||
|
* @implements Countable<TValue>
|
||||||
|
* @phpstan-require-implements Countable
|
||||||
*/
|
*/
|
||||||
trait Countable
|
trait CountableTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Holds the countable data.
|
* Holds the countable data.
|
||||||
|
*
|
||||||
|
* @var array<TKey, TValue>
|
||||||
*/
|
*/
|
||||||
private array $data = [];
|
protected array $data = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the data items.
|
* Count the data items.
|
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||||
namespace OCC\Basics\InterfaceTraits;
|
namespace OCC\Basics\InterfaceTraits;
|
||||||
|
|
||||||
use ArrayIterator;
|
use ArrayIterator;
|
||||||
|
use IteratorAggregate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic implementation of the IteratorAggregate interface.
|
* A generic implementation of the IteratorAggregate interface.
|
||||||
|
@ -31,19 +32,24 @@ use ArrayIterator;
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\InterfaceTraits
|
* @package Basics\InterfaceTraits
|
||||||
*
|
*
|
||||||
* @phpstan-require-implements \IteratorAggregate
|
* @template TKey of int|string
|
||||||
|
* @template TValue of mixed
|
||||||
|
* @implements IteratorAggregate<TKey, TValue>
|
||||||
|
* @phpstan-require-implements IteratorAggregate
|
||||||
*/
|
*/
|
||||||
trait IteratorAggregate
|
trait IteratorAggregateTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Holds the iterable data.
|
* Holds the iterable data.
|
||||||
|
*
|
||||||
|
* @var array<TKey, TValue>
|
||||||
*/
|
*/
|
||||||
private array $data = [];
|
protected array $data = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve an external iterator.
|
* Retrieve an external iterator.
|
||||||
*
|
*
|
||||||
* @return ArrayIterator
|
* @return ArrayIterator<TKey, TValue> New array iterator for data array
|
||||||
*/
|
*/
|
||||||
public function getIterator(): ArrayIterator
|
public function getIterator(): ArrayIterator
|
||||||
{
|
{
|
|
@ -23,25 +23,32 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\InterfaceTraits;
|
namespace OCC\Basics\InterfaceTraits;
|
||||||
|
|
||||||
|
use Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic implementation of the Iterator interface.
|
* A generic implementation of the Iterator interface.
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package Basics\InterfaceTraits
|
* @package Basics\InterfaceTraits
|
||||||
*
|
*
|
||||||
* @phpstan-require-implements \Iterator
|
* @template TKey of int|string
|
||||||
|
* @template TValue of mixed
|
||||||
|
* @implements Iterator<TKey, TValue>
|
||||||
|
* @phpstan-require-implements Iterator
|
||||||
*/
|
*/
|
||||||
trait Iterator
|
trait IteratorTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Holds the iterable data.
|
* Holds the iterable data.
|
||||||
|
*
|
||||||
|
* @var array<TKey, TValue>
|
||||||
*/
|
*/
|
||||||
private array $data = [];
|
protected array $data = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current item.
|
* Return the current item.
|
||||||
*
|
*
|
||||||
* @return mixed The current item or FALSE if invalid
|
* @return TValue|false The current item or FALSE if invalid
|
||||||
*/
|
*/
|
||||||
public function current(): mixed
|
public function current(): mixed
|
||||||
{
|
{
|
||||||
|
@ -51,7 +58,7 @@ trait Iterator
|
||||||
/**
|
/**
|
||||||
* Return the current key.
|
* Return the current key.
|
||||||
*
|
*
|
||||||
* @return mixed The current key or NULL if invalid
|
* @return ?TKey The current key or NULL if invalid
|
||||||
*/
|
*/
|
||||||
public function key(): mixed
|
public function key(): mixed
|
||||||
{
|
{
|
||||||
|
@ -79,7 +86,7 @@ trait Iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if current position is valid.
|
* Check if current position is valid.
|
||||||
*
|
*
|
||||||
* @return bool Whether the current position is valid
|
* @return bool Whether the current position is valid
|
||||||
*/
|
*/
|
|
@ -75,11 +75,12 @@ trait Getter
|
||||||
public function __isset(string $property): bool
|
public function __isset(string $property): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
/** @var mixed $value */
|
||||||
$value = $this->__get($property);
|
$value = $this->__get($property);
|
||||||
} catch (InvalidArgumentException) {
|
} catch (InvalidArgumentException) {
|
||||||
$value = null;
|
$value = null;
|
||||||
} finally {
|
} finally {
|
||||||
return (bool) $value !== false;
|
return boolval($value ?? null) !== false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ trait Singleton
|
||||||
/**
|
/**
|
||||||
* Holds the singleton instance.
|
* Holds the singleton instance.
|
||||||
*
|
*
|
||||||
* @var array<static>
|
* @var array<string, static>
|
||||||
*/
|
*/
|
||||||
private static array $singleton = [];
|
private static array $singleton = [];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue