Skip to content

Instantly share code, notes, and snippets.

@hugowetterberg
Created August 25, 2010 14:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hugowetterberg/549641 to your computer and use it in GitHub Desktop.
Save hugowetterberg/549641 to your computer and use it in GitHub Desktop.
<?php
class ServicesContext implements ArrayAccess {
protected $handlers;
protected $namespaces;
private $values = array();
function __construct($handlers = array(), $namespaces = array()) {
$this->handlers = $handlers;
$this->namespaces = $namespaces;
}
public function offsetExists($key) {
$value = $this[$key];
return $value !== NULL;
}
public function offsetGet($key) {
$value = NULL;
$namespace = NULL;
$local_key = $key;
// Detect namespace.
if (($pos = strrpos($key, ':')) !== FALSE) {
$namespace = substr($key, 0, $pos);
$local_key = substr($key, $pos+1);
}
// Check for a cached value.
if (isset($this->values[$key])) {
$value = $this->values[$key];
}
else {
// Specific key handlers always override the generic
// namespace handlers.
if (isset($this->handlers[$key])) {
$value = $this->handlers[$key]->value($this, $namespace, $local_key);
}
else if ($namespace && isset($this->namespaces[$namespace])){
$value = $this->namespaces[$namespace]->value($this, $namespace, $local_key);
}
$this->values[$key] = $value;
}
return $value;
}
public function offsetSet($key, $value) {
throw new Exception("You cannot modify your context");
}
public function offsetUnset($key) {
throw new Exception("You cannot modify your context");
}
public function mock() {
return new ServicesMutableContext($this->handlers, $this->namespaces);
}
}
class ServicesMutableContext extends ServicesContext {
function __construct($handlers = array(), $namespaces = array()) {
parent::__construct($handlers, $namespaces);
}
public function addNamespace($namespace, $handler) {
$this->namespaces[$namespace] = $handler;
}
public function getNamespaceHandler($namespace) {
$handler = NULL;
if (isset($this->namespaces[$namespace])) {
$handler = $this->namespaces[$namespace];
}
return $handler;
}
public function offsetExists($key) {
return isset($handlers[$key]);
}
public function offsetGet($key) {
return $handlers[$key];
}
public function offsetSet($key, $handler) {
$this->handlers[$key] = $handler;
}
public function offsetUnset($key) {
unset($this->handlers[$key]);
}
function immutableCopy() {
return new ServicesContext($this->handlers, $this->namespaces);
}
}
interface ServicesContextHandler {
function value($context, $namespace, $key);
}
class ServicesDumbContextHandler implements ServicesContextHandler {
private $value;
function __construct($value) {
$this->value = $value;
}
public function value($context, $namespace, $key) {
return $this->value;
}
}
class ServicesArrayContextHandler implements ServicesContextHandler {
private $array;
function __construct($array) {
$this->array = $array;
}
public function value($context, $namespace, $key) {
$value = NULL;
if (isset($this->array[$key])) {
$value = $this->array[$key];
}
return $value;
}
}
// Example stuff
$getv = array(
'q' => '/some/path',
'p' => 23,
);
$cA = new ServicesMutableContext();
$cA['varA'] = new ServicesDumbContextHandler('Value A');
$cA['http:get:p'] = new ServicesDumbContextHandler(24);
$cA->addNamespace('http:get', new ServicesArrayContextHandler($getv));
$c = $cA->immutableCopy();
print "-- Context\n";
print $c['varA'] . "\n";
print $c['http:get:q'] . "\n";
print $c['http:get:p'] . "\n\n";
$cB = $c->mock();
$cB['varB'] = new ServicesDumbContextHandler('Value B');
$cB['http:get:p'] = new ServicesDumbContextHandler(25);
$cX = $cB->immutableCopy();
print "-- Context X\n";
print $cX['varA'] . "\n";
print $cX['varB'] . "\n";
print $cX['http:get:q'] . "\n";
print $cX['http:get:p'] . "\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment