<?php
class Container implements ArrayAccess, Countable, Iterator, JsonSerializable, Serializable
{
protected $values;
public function __construct(... $values)
{
$this->values = [];
foreach ($values as $value) {
if (is_array($value)) {
foreach ($value as $val) {
$this->append($val);
}
}
else {
$this->append($value);
}
}
}
protected function validate($value)
{
return true;
}
protected function format($value)
{
return $value;
}
public function prepend($value)
{
if ($this->validate($value)) {
array_unshift($this->values, $this->format($value));
return true;
}
return false;
}
public function shift()
{
return array_shift($this->values);
}
public function append($value)
{
if ($this->validate($value)) {
array_push($this->values, $this->format($value));
return true;
}
return false;
}
public function pop()
{
return array_pop($this->values);
}
public function toArray()
{
return $this->values;
}
public function filter($callback)
{
$this->values = array_values(array_filter($this->values, $callback));
return $this;
}
public function map($callback)
{
$this->values = array_values(array_map([$this, 'format'], array_filter(array_map($callback, $this->values), [$this, 'validate'])));
return $this;
}
public function offsetExists($offset)
{
return key_exists($offset, $this->values);
}
public function offsetGet($offset)
{
return ($this->offsetExists($offset) ? $this->values[$offset] : null);
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->append($value);
return;
}
if (!$this->offsetExists($offset)) {
$cn = get_called_class();
throw new Exception("{$cn} cannot set value at index {$offset}.");
}
if ($this->validate($value)) {
$this->values[$offset] = $this->format($value);
}
}
public function offsetUnset($offset)
{
if ($this->offsetExists($offset)) {
unset($this->values[$offset]);
}
}
public function count()
{
return count($this->values);
}
public function current()
{
return current($this->values);
}
public function key()
{
return key($this->values);
}
public function next()
{
return next($this->values);
}
public function rewind()
{
reset($this->values);
}
public function valid()
{
return !is_null(key($this->values));
}
public function jsonSerialize()
{
return $this->toArray();
}
public function serialize()
{
return serialize($this->values);
}
public function unserialize($data)
{
$this->values = unserialize($data);
}
}
class IntContainer extends Container
{
protected function validate($value)
{
return is_numeric($value);
}
protected function format($value)
{
return intval($value);
}
}
$nums = new IntContainer(2, 4, 6, 8);
var_dump(
$nums->map(function ($num) {
return sprintf("[%'10s]",sprintf("0x%08x",$num + 1));
})
->toArray()
);