parent
a998bf9de1
commit
b8dc4c2e79
@ -1,3 +1,3 @@
|
||||
# PhpArrayClass
|
||||
# PhpArrayClasses
|
||||
|
||||
Classes for array embedding
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ArrayClasses;
|
||||
|
||||
use OutOfRangeException;
|
||||
|
||||
/**
|
||||
* An array
|
||||
*/
|
||||
class ArrayClass extends ImmutableArrayClass {
|
||||
/**
|
||||
* Set or replace a cell value
|
||||
*
|
||||
* @param mixed $offset The cell offset
|
||||
* @param mixed $value The cell new value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set ($offset, $value): self {
|
||||
$this->array[$offset] = $value;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Remove a cell
|
||||
*
|
||||
* @param mixed $offset The cell offset
|
||||
* @param bool|null $throwsForNonExistentElement If set, temporarily override {@see ImmutableArrayClass::$throwsForNonExistentElement}
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function del ($offset, ?bool $throwsForNonExistentElement = null): self {
|
||||
if ($throwsForNonExistentElement ?? $this->throwsForNonExistentElement() && !$this->has($offset)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
unset($this->array[$offset]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an immutable copy
|
||||
*
|
||||
* @return ImmutableArrayClass The immutable copy
|
||||
*/
|
||||
public function toImmutableArrayClass (): ImmutableArrayClass {
|
||||
return new ImmutableArrayClass($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetSet ($offset, $value): void {
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetUnset ($offset): void {
|
||||
$this->del($offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ArrayClasses;
|
||||
|
||||
/**
|
||||
* Interface for PHP-native array cast
|
||||
*/
|
||||
interface IArrayCast {
|
||||
/**
|
||||
* Transform to a PHP-native array
|
||||
*
|
||||
* @return array The native array
|
||||
*/
|
||||
public function toArray (): array;
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ArrayClasses;
|
||||
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use InvalidArgumentException;
|
||||
use IteratorAggregate;
|
||||
use JsonSerializable;
|
||||
use OutOfRangeException;
|
||||
use Serializable;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* An immutable array
|
||||
*/
|
||||
class ImmutableArrayClass implements IteratorAggregate, JsonSerializable, Serializable, Countable, ArrayAccess, IArrayCast {
|
||||
/**
|
||||
* @var array The internal array
|
||||
*/
|
||||
protected array $array;
|
||||
/**
|
||||
* @var bool Throws an exception for nonexistent elements ?
|
||||
*/
|
||||
private bool $throwsForNonExistentElement;
|
||||
|
||||
/**
|
||||
* Initialize the array
|
||||
*
|
||||
* @param IArrayCast|array|null $initial The initial value
|
||||
* @param bool $throwsForNonExistentElement Throws an exception for nonexistent elements ?
|
||||
*/
|
||||
public function __construct ($initial = null, bool $throwsForNonExistentElement = true) {
|
||||
$this->setThrowsForNonExistentElement($throwsForNonExistentElement);
|
||||
|
||||
if (is_array($initial)) {
|
||||
$this->array = $initial;
|
||||
}
|
||||
elseif (is_null($initial)) {
|
||||
$this->array = [];
|
||||
}
|
||||
elseif ($initial instanceof IArrayCast) {
|
||||
$this->array = $initial->toArray();
|
||||
}
|
||||
else {
|
||||
throw new InvalidArgumentException('The initial value is not valid: null, array or ' . IArrayCast::class);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the value of a cell
|
||||
*
|
||||
* @param mixed $offset The cell offset
|
||||
*
|
||||
* @return mixed|null The cell value
|
||||
*/
|
||||
public function __invoke ($offset) {
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a cell offset exists
|
||||
*
|
||||
* @param mixed $offset The cell offset
|
||||
*
|
||||
* @return bool True if the cell offset exists
|
||||
*/
|
||||
public function has ($offset): bool {
|
||||
return array_key_exists($offset, $this->array);
|
||||
}
|
||||
/**
|
||||
* Get the value of a cell
|
||||
*
|
||||
* @param mixed $offset The cell offset
|
||||
* @param bool|null $throwsForNonExistentElement If set, temporarily override {@see ImmutableArrayClass::$throwsForNonExistentElement}
|
||||
*
|
||||
* @return mixed|null The cell value
|
||||
*/
|
||||
public function get ($offset, ?bool $throwsForNonExistentElement = null) {
|
||||
if ($this->has($offset)) {
|
||||
return $this->array[$offset];
|
||||
}
|
||||
if ($throwsForNonExistentElement ?? $this->throwsForNonExistentElement()) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray (): array {
|
||||
return $this->array;
|
||||
}
|
||||
/**
|
||||
* Create a mutable copy
|
||||
*
|
||||
* @return ArrayClass The mutable copy
|
||||
*/
|
||||
public function toMutableArrayClass (): ArrayClass {
|
||||
return new ArrayClass($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function count (): int {
|
||||
return count($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIterator (): Traversable {
|
||||
return new ArrayIterator($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetExists ($offset): bool {
|
||||
return $this->has($offset);
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetGet ($offset) {
|
||||
return $this->get($offset);
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetSet ($offset, $value): void {
|
||||
throw new ImmutableException();
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetUnset ($offset): void {
|
||||
throw new ImmutableException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function serialize (): string {
|
||||
return serialize($this->array);
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function unserialize ($data): void {
|
||||
$this->array = unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize () {
|
||||
return $this->array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception for nonexistent elements ?
|
||||
*
|
||||
* @return bool Throws an exception for nonexistent elements ?
|
||||
*/
|
||||
public function throwsForNonExistentElement (): bool {
|
||||
return $this->throwsForNonExistentElement;
|
||||
}
|
||||
/**
|
||||
* Set if throws an exception for nonexistent elements
|
||||
*
|
||||
* @param bool $throwsForNonExistentElement Throws an exception for nonexistent elements ?
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setThrowsForNonExistentElement (bool $throwsForNonExistentElement): self {
|
||||
$this->throwsForNonExistentElement = $throwsForNonExistentElement;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ArrayClasses;
|
||||
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
* Exception thrown when trying to modify an immutable element
|
||||
*/
|
||||
class ImmutableException extends LogicException {
|
||||
}
|
Loading…
Reference in New Issue