Success!
ICollator.interface.phps
<?php
interface ICollator extends ArrayAccess, Countable, IteratorAggregate
{
}
?>
Collator.class.phps
<?php
abstract class Collator implements ICollator
{
protected $_items = array();
protected function __construct(ICollator $collator = null)
{
if (!is_null($collator))
foreach ($collator as $offset => $value)
$this->_items[$offset] = $value;
}
public function OffsetExists($offset)
{
return array_key_exists($offset, $this->_items);
}
public function OffsetGet($offset)
{
if ($this->offsetExists($offset))
return $this->_items[$offset];
else
throw new Exception('Requested offset was not found!');
}
public function OffsetSet($offset, $value)
{
if ($this->offsetExists($offset))
$this->_items[$offset] = $value;
else
throw new Exception('Requested offset was not found!');
}
public function OffsetUnset($offset)
{
throw new Exception('Unsetting an element is not allowed!');
}
public function Count()
{
return count($this->_items);
}
public function GetIterator()
{
return new ArrayIterator($this->_items);
}
}
?>
ICollection.interface.phps
<?php
interface ICollection extends ICollator
{
function Add($value);
function Contains($value);
function Remove($value);
}
?>
Collection.class.phps
<?php
class Collection extends Collator implements ICollection
{
public function __construct(ICollection $collection = null)
{
parent::__construct($collection);
}
public function Add($value)
{
if (!$this->Contains($value))
$this->_items[] = $value;
}
public function Contains($value)
{
return in_array($value, array_values($this->_items));
}
public function Remove($value)
{
if ($this->Contains($value))
unset($this->_items[array_search($value, $this->_items)]);
}
}
?>
IDictionary.interface.phps
<?php
interface IDictionary extends ArrayAccess, Countable, IteratorAggregate
{
function Add($key, $value);
function Contains($value);
function Keys();
function Remove($key);
function Values();
}
?>
Dictionary.class.phps
<?php
class Dictionary extends Collator implements IDictionary
{
public function __construct(IDictionary $dictionary = null)
{
parent::__construct($dictionary);
}
public function Add($key, $value)
{
if (!is_string($key) || is_null($key) || empty($key))
throw new Exception('String key expected!');
if (!$this->Keys()->Contains($key))
$this->_items[$key] = $value;
}
public function Contains($value)
{
return in_array($value, array_values($this->_items));
}
public function Keys()
{
$keys = new Collection();
foreach (array_keys($this->_items) as $key)
$keys->Add($key);
return $keys;
}
public function Remove($key)
{
if ($this->Keys()->Contains($key))
unset($this->_items[$key]);
}
public function Values()
{
$values = new Collection();
foreach (array_values($this->_items) as $value)
$values->Add($value);
return $values;
}
}
?>
Usage
// creating collections
$collection = new Collection();
$collection = new Collection($existing);
// adding to a collection
$collection->Add($item);
// testing inclusion in a collection
if ($collection->Contains($item))
{
// do something
}
// getting a collection value
$item = $collection[0];
// setting a collection value
$collection[0] = $item;
// removing a collection value
$collection->Remove($item);
// creating dictionaries
$dictionary = new Dictionary();
$dictionary = new Dictionary($existing);
// adding to a dictionary
$dictionary->Add($key, $item);
// testing key inclusion in a dictionary
if ($dictionary->Keys()->Contains($key))
{
// do something
}
// testing item inclusion in a dictionary
if ($dictionary->Values()->Contains($item))
{
// do something
}
// or
if ($dictionary->Contains($item))
{
// do something
}
// getting a dictionary value
$item = $dictionary["key"];
// setting a dictionary value
$dictionary["key"] = $item;
// removing a dictionary value
$dictionary->Remove($key);
As you can see, it is built to be extensible, so feel free to come up with your own implementations of Collator. I will probably do a typecast version where I extend Collator to TypedCollator and pass in $type before the optional collator instance. You could also do a read only version if you wanted.
=)