therselman 7 years ago
parent
commit
1ef1b23642
  1. 171
      src/Collection.php
  2. 22
      src/Container.php
  3. 111
      src/Entity.php

171
src/Collection.php

@ -1,160 +1,157 @@
<?php <?php
/**
* Collection class with dynamic members and methods
* Similar functionality to an Array or Dictionary class
* Typically holding a collection/array of Entity members
*/
namespace Twister; namespace Twister;
class Collection implements \Iterator, \Countable, \ArrayAccess class Collection implements \Iterator, \Countable, \ArrayAccess
{ {
protected $_ = null; protected $members = null;
protected $methods = null;
public function __construct(array $members = null) public function __construct(array $members = null, array $methods = null)
{ {
$this->_ =& $members; $this->members =& $members;
$this->methods =& $methods;
} }
function &__get($key)
/**
* Get member by id/index
*
* @param string|int $idx
* @return mixed
*/
public function __get($idx)
{ {
return $this->_[$key] ?? null; return $this->members[$idx];
} }
function __set($key, $value)
/**
* Set member by id/index
*
* @param string|int $idx
* @param mixed $value
* @return void
*/
public function __set($idx, $value)
{ {
return $this->_[$key] = $value; $this->members[$idx] = $value;
} }
function __isset($key) function __isset($idx)
{ {
return isset($this->_[$key]); return isset($this->members[$idx]);
} }
function __unset($key) function __unset($idx)
{ {
unset($this->_[$key]); unset($this->members[$idx]);
} }
function &all() public function &all()
{ {
return $this->_; return $this->members;
} }
function set($key, $value) // alias for __set() public function get($name) // alias for __get()
{ {
return $this->_[$key] =& $value; return $this->members[$name];
} }
function &get($key, $default = null) // alias for __get() public function set($name, $value) // alias for __set()
{ {
return $this->_[$key] ?? $default; return $this->members[$name] = $value;
} }
function has($key) // alias for __isset() public function has($name) // alias for __isset()
{ {
return isset($this->_[$key]); return isset($this->members[$name]);
} }
function &merge($key, array $arr) // we need this function because we cannot (re)`set` the arrays to new values without unsetting the old values first! ie. __set() will fail because it already exists! public function remove($name) // alias for __unset()
{ {
// TODO: Add is_array() checks to the container, and add variable number of array inputs! unset($this->members[$name]);
$this->_[$key] = array_merge($this->_[$key], $arr);
return $this->_[$key];
}
function remove($key) // alias for __unset()
{
unset($this->_[$key]);
} }
/**
* Workaround for the `array access functions` eg. array_push($obj->toArray(), $value);
*/
public function &toArray()
{
return $this->members;
}
function &__call($method, $args) public function __call($method, $args)
{ {
if (isset($this->_[$method])) array_unshift($args, $this);
if (is_callable($this->_[$method])) return call_user_func_array($this->methods[$method], $args);
{
$result = call_user_func_array($this->_[$method], $args);
return $result;
}
else
return $this->_[$method];
else
{
if (preg_match('/^([gs]et|has|isset|unset)([A-Z_])(.*)$/', $method, $match))
{
$property = strtolower($match[2]). $match[3];
switch($match[1])
{
case 'get': return $this->_[$property] ?? $args[0] ?? null;
case 'set': return $this->_[$property] = $args[0];
case 'has': // fallthrough vvv alias for `isset`
case 'isset': $result = isset($this->_[$property]); return $result;
case 'unset': $result = null; unset($this->_[$property]); return $result;
}
//throw new \InvalidArgumentException("Property {$property} doesn't exist");
}
throw new \InvalidArgumentException(__CLASS__ . "->{$method}() doesn't exist");
}
} }
public function __invoke()
//
// Workaround for the `array access functions` eg. array_push($obj->toArray(), 'Hello World!');
//
public function &toArray()
{ {
return $this->_; return $this->methods['__invoke']($this);
} }
public function &__invoke() public function setMethod($method, callable $callable)
{ // TODO: What do you think about this technique? We could just leave it if we don't use it! {
// Basically, we are calling an internal `__invoke` handler $this->methods[$method] = $callable;
// eg. $myCollection['__invoke'] = function($c) { return $c->all(); } return $this;
return $this->_['__invoke']($this);
} }
//
// Iterator interface /**
// * Iterator interface
*/
public function rewind() public function rewind()
{ {
return reset($this->_); return reset($this->members);
} }
public function current() public function current()
{ {
return current($this->_); return current($this->members);
} }
public function key() public function key()
{ {
return key($this->_); return key($this->members);
} }
public function next() public function next()
{ {
return next($this->_); return next($this->members);
} }
public function valid() public function valid()
{ {
return key($this->_) !== null; return key($this->members) !== null;
} }
// /**
// Countable interface * Countable interface
// */
public function count() public function count()
{ {
return count($this->_); return count($this->members);
} }
// /**
// ArrayAccess interface * ArrayAccess interface
// */
public function offsetSet($id, $value) // eg. $obj['two'] = 'A value'; public function offsetGet($idx) // eg. var_dump($obj['two']);
{ {
$this->_[$id] = $value; return $this->members[$idx];
} }
public function offsetExists($id) // eg. isset($obj['two']) public function offsetSet($idx, $value) // eg. $obj['two'] = 'A value';
{ {
return isset($this->_[$id]); $this->members[$idx] = $value;
} }
public function offsetUnset($id) // eg. unset($obj['two']); public function offsetExists($idx) // eg. isset($obj['two'])
{ {
unset($this->_[$id]); return isset($this->members[$idx]);
} }
public function offsetGet($id) // eg. var_dump($obj['two']); public function offsetUnset($idx) // eg. unset($obj['two']);
{ {
return $this->_[$id]; unset($this->members[$idx]);
} }
} }

22
src/Container.php

@ -217,17 +217,6 @@ class Container implements ArrayAccess
} }
/**
* Determine if a given offset exists.
*
* @param string $key
* @return bool
*/
public function offsetExists($key)
{
return isset($this->bindings[$key]);
}
/** /**
* Get the value at a given offset. * Get the value at a given offset.
* *
@ -251,6 +240,17 @@ class Container implements ArrayAccess
$this->__set($key, $value); $this->__set($key, $value);
} }
/**
* Determine if a given offset exists.
*
* @param string $key
* @return bool
*/
public function offsetExists($key)
{
return isset($this->bindings[$key]);
}
/** /**
* Unset the value at a given offset. * Unset the value at a given offset.
* *

111
src/Entity.php

@ -0,0 +1,111 @@
<?php
/**
* Entity class with dynamic properties
* Properties can include callable functions, which can `lazy load` properties, or return dynamic/complex/calculated properties
*/
namespace Twister;
class Entity implements \ArrayAccess
{
protected $properties = null;
public function __construct(array $properties = null)
{
$this->properties =& $properties;
}
/**
* Get entity field/property
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
$value = $this->properties[$name];
return is_callable($value) ? $value($this) : $value;
}
/**
* Set entity field/property
*
* @param string $name
* @param mixed $value
* @return void
*/
public function __set($name, $value)
{
$this->properties[$name] = $value;
}
public function __isset($name)
{
return isset($this->properties[$name]);
}
public function __unset($name)
{
unset($this->properties[$name]);
}
public function &all()
{
return $this->properties;
}
public function get($name) // alias for __get()
{
return $this->properties[$name];
}
public function set($name, $value) // alias for __set()
{
return $this->properties[$name] = $value;
}
public function has($name) // alias for __isset()
{
return isset($this->properties[$name]);
}
public function remove($name) // alias for __unset()
{
unset($this->properties[$name]);
}
public function __call($method, $args)
{
array_unshift($args, $this);
return call_user_func_array($this->properties[$method], $args);
}
public function __invoke()
{
return $this->properties['__invoke']($this);
}
public function setMethod($method, callable $callable)
{
$this->properties[$method] = $callable;
return $this;
}
/**
* ArrayAccess interface
*/
public function offsetGet($name) // eg. var_dump($obj['two']);
{
return $this->properties[$name];
}
public function offsetSet($name, $value) // eg. $obj['two'] = 'A value';
{
$this->properties[$name] = $value;
}
public function offsetExists($name) // eg. isset($obj['two'])
{
return isset($this->properties[$name]);
}
public function offsetUnset($name) // eg. unset($obj['two']);
{
unset($this->properties[$name]);
}
}
Loading…
Cancel
Save