public function remove($key, callable $beforeRemove = null)
{
// check if a key has been passed
if (is_null($key)) {
throw new NullPointerException('Passed key is null');
}
// check if a primitive datatype is passed
if (is_integer($key) || is_string($key) || is_double($key) || is_bool($key)) {
if (array_key_exists($key, $this->items)) {
// invoke the callback before
if (is_callable($beforeRemove)) {
call_user_func($beforeRemove, $this->items[$key]);
}
// remove the item
unset($this->items[$key]);
// remove the lifetime if set
if (isset($this->lifetime[$key])) {
unset($this->lifetime[$key]);
}
return;
} else {
throw new IndexOutOfBoundsException('Index ' . $key . ' out of bounds');
}
}
// check if an object is passed
if (is_object($key)) {
if ($key instanceof String) {
$newKey = $key->stringValue();
} elseif ($key instanceof Float) {
$newKey = $key->floatValue();
} elseif ($key instanceof Integer) {
$newKey = $key->intValue();
} elseif ($key instanceof Boolean) {
$newKey = $key->booleanValue();
} elseif (method_exists($key, '__toString')) {
$newKey = $key->__toString();
} else {
throw new InvalidKeyException('Passed key has to be a primitive datatype or ' . 'has to implement the __toString() method');
}
if (array_key_exists($newKey, $this->items)) {
// invoke the callback before
if (is_callable($beforeRemove)) {
call_user_func($beforeRemove, $this->items[$newKey]);
}
// remove the item
unset($this->items[$newKey]);
// remove the lifetime if set
if (isset($this->lifetime[$newKey])) {
unset($this->lifetime[$newKey]);
}
return;
} else {
throw new IndexOutOfBoundsException('Index ' . $newKey . ' out of bounds');
}
}
throw new InvalidKeyException('Passed key has to be a primitive datatype or ' . 'has to implement the __toString() method');
}