<?php
/*****************************************************************************
*
* Class Name : Collection
* Version : 1.6
* Written By : Diogo Souza da Silva <manifesto@manifesto.blog.br>
* License: GPL
*
******************************************************************************
*
* This class implements Collection object in PHP. Some things you should know.
* This class can behave exactly like an array
* It just work in PHP5
* This class can(maybe should) be extendend
* Only two entry points, add() and set()
* Only one leaving point, remove()
* This class implments Iterator and ArrayAccess
* You can usi it in foreach, while and others just like an array
* It is an iterator for itself also
* You cannot extends ArrayObject and implements ArrayAccess
*
*****************************************************************************
*
* TODO:
* PHPDOC for real
* Clean some functions
* Make real tests, now it example file as test
* Implement type safe Collection
* Implement some kind of "lock" or "state"
* Implement someway for applying a function to all elements
* Improve __toXml and __toString
* Create to __toJson?
* More on SPL?
* Implement Serializable(__wakeup and __sleep)?
* Implement __get and __set for the Collection elements?
* Maybe refactor the hole class for subclasses? (split method in classes)
*/
class Collection implements Iterator , ArrayAccess {
/**
* The number of elements in the Collection
* @var int
*/
public $lenght=0;
/**
* The inner array
* @var array
*/
private $elements = array();
/**
* Create a collection of objects
* @param array|collection $array [optional]
*/
function __construct($array=null) {
$this->merge($array,true);
}
/**
* Adds an object into collection
* if arg1 only is given, it will be the item at last index
* if arg1 and arg2 is given, arg1 will be the index(key) and arg2 will be the value
* It does not "set" to an existing index, use set insted
* @param mixed $ag1
* @param mixed $arg2 [optional]
* @return Collection
*/
function add($arg1,$arg2=false) {
if(!$arg2) {
$this->elements[] = $arg1;
} else {
if (!array_key_exists($arg1,$this->elements)) {
$this->elements[$arg1] = $arg2;
}
}
$this->count();
return $this ;
}
/**
* Set the value of the given key
* @param key $key
* @param mixed $item
* @return mixed $item
*/
function set($key,$item) {
if(isset($key)) {
$this->elements[$key] = $item;
} else {
$this->elements[] = $item ;
}
$this->count();
return $this->get($key);
}
/**
* Adds value at last index
* @param $value
* @return Collection
*/
function append($value) {
return $this->add($value);
//return $this ;
}
/**
* Join(merge) an array or a collection into this one
* @param array|collection $array
* @param bool $keepkeys
* @param bool $overload
* @return Collection
*/
function merge($array,$keepkeys=false,$overload=false) {
if(is_array($array) or $array instanceof ArrayAccess) {
//$this->elements = array_merge($this->elements,$array);
if(count($array) >= 1)
foreach($array as $k=>$v) {
if($keepkeys) {
if($overload)
{ $this->set($k,$v);}
else
{$this->add($k,$v);}
} else {
$this->add($v);
}
}
} else if($array instanceof Iterator) {
//$this->elements = array_merge($this->elements,$array->getArrayCopy());
while($array->valid()) {
if($keepkeys) {
if($overload)
{$this->set($array->key(),$array->current()); }
else
{$this->add($array->key(),$array->current()); }
}else{
$this->add($array->current());
}
$array->next();
}
}
$this->count();
return $this ;
}
/**
* Sort by values, keeping keys
* @param CONST flags
* @return Collection
*/
function asort($flags=null) {
asort($this->elements,$flags);
return $this;
}
/**
* Sort by key
* @param CONST flags
* @return Collection
*
*/
function ksort($flags=null) {
ksort($this->elements,$flags);
return $this;
}
/**
* sort by natural order
* @param CONST flags
* @return Collection
*/
function sort($flags=null) {
sort($this->elements,$flags);
return $this ;
}
/**
* size number of itens;
* @return int
*/
function count() {
$this->lenght = count($this->elements);
return $this->lenght ;
}
/**
* Remove the $key item
* @param key $key
* @return Collection
*/
function remove($key) {
if (array_key_exists($key,$this->elements)) {
unset($this->elements[$key]);
$this->count();
return $this;
}
}
/**
* Verifies if this key is filled
* @param key $k
* @return bool
*/
function exists($k) {
return array_key_exists($k, $this->elements);
}
/**
* Moves the cursor a step foward
* @return bool
*/
function next() {
return next(&$this->elements) ;
}
/**
* If next element is valid
* @return bool
*/
function hasNext() {
$this->next() ;
$v = $this->valid() ;
$this->back() ;
return $v ;
}
/**
* Moves cursor to given key
* @param key $key
* @return bool
*/
function seek($key) {
$this->rewind();
while($this->valid()) {
if($this->key() == $key) {
return true;
}
$this->next();
}
return false;
}
/**
* Moves the cursor a step back
* @return bool
*/
function back() {
return prev(&$this->elements);
}
/**
* Puts the cursor at start
* @return bool
*/
function rewind() {
return reset(&$this->elements);
}
/**
* Puts cursor at the end
* @return bool
*/
function forward() {
return end(&$this->elements);
}
/**
* Return the item in the cursor point
* @return mixed Current Item
*/
function current() {
return current($this->elements);
}
/**
* Returns cursor key
* @return mixed current key
*/
function currentKey() {
return key($this->elements) ;
}
/**
* Actual cursor key
* @return mixed current key
*/
function key() {
return $this->currentKey();
}
/**
* Check if cursor is at a valid item
* @return bool
*/
function valid() {
if(!is_null($this->key())) {
return true;
} else {
return false ;
}
}
/**
* same as valid()
* @return bool
*/
function isValid() {
return $this->valid();
}
/**
* Returns object for given posistion
* @param key $key
*/
function get($key) {
return $this->elements[$key];
}
/**
* Fetchs basic
*/
function fetch() {
if($this->valid()) {
$r = $this->current();
$this->next() ;
return $r ;
} else {
return false;
}
}
/**
* ArrayAccess, check if offset (key) exists
* @param $offset
* @return bool
*/
function offsetExists($offset) {
return $this->exists($offset);
}
/**
* ArrayAccess, get element
* @param $offset
* @return mixed
*/
function offsetGet($offset) {
return $this->get($offset);
}
/**
* ArrayAccess, set element
* @param key $offset
* @param mixed $value
* @return mixed
*/
function offsetSet($offset,$value) {
return $this->set($offset, $value);
}
/**
* ArrayAccess, remove element
* @param key $offset
* @return COllection $this
*/
function offsetUnset($offset) {
return $this->remove($offset);
}
/**
* Null all the collection, including keys
* @return Collection $this;
*/
function clear() {
$this->elements = array();
$this->length = 0;
return $this ;
}
/**
* @return the size of the collection
*/
function size() {
return $this->count();
}
/**
* returns if the collection is empty or not
* @return bool
*/
function isEmpty() {
if($this->count() < 1)
return true ;
else
return false;
}
/**
* Check if given object exists in collection
* Type safe
* @param mixed $obj
* @return bool
*/
function contains($obj) {
foreach($this->elements as $element) {
if($element === $obj) {
$this->rewind();
return true ;
}
}
$this->rewind();
return false ;
}
/**
* Return the (first) index(key) of given object
* @param mixed $obj
* @return key of the obj
*/
function indexOf($obj) {
foreach($this->elements as $k=>$element) {
if($element === $obj) {
$this->rewind();
return $k ;
}
}
$this->rewind();
return null ;
}
/**
* returns last index(key) of given object
* @param mixed $obj
* @return key
*/
function lastIndexOf($obj) {
$return = null ;
foreach($this->elements as $k=>$element) {
if($element === $obj) {
$return = $k ;
}
}
$this->rewind();
return $return ;
}
/**
* Return a new collection with a part of this collection
* @param int $start
* @param int $end
* @return Collection
*/
function subCollection($start,$end) {
$new = new Collection();
$i = 0;
foreach($this->elements as $k=>$element) {
if($i <= $end && $i >= $start) {
$new->add($element) ;
}
$i++ ;
}
$this->rewind();
return $new ;
}
/**
* Cut the array to given size
* @param int $size
* @return Collection
*/
function trimToSize($size) {
$t = array_chunk($this->elements,$size,true);
$this->elements = $t[0];
$this->count();
return $this ;
}
/**
* Return the xml of this collection
* @return string
*/
function __toXml() {
$xml = "\n<Collection>";
foreach($this->elements as $k=>$v) {
$xml .= "\n\t<element key=\"{$k}\">";
if(is_string($v)) {
$xml.= $v ;
} else if(is_object($v) and method_exists($v,"__toXml()")) {
$xml.= $v->__toXml() ;
} else if(is_object($v) and method_exists($v, "__toString()")) {
$xml.= $v->__toString() ;
}
$xml .= "</element>";
}
$xml .= "\n</Collection>";
$this->rewind();
return $xml ;
}
/**
* A alias to __toXMl()
* @return $string
*/
function toXML() {
return $this->__toXML();
}
/**
* Returns as an array
* @return array
*/
function __toArray() {
return $this->elements ;
}
/**
* A alias to __toArray()
* @return array
*/
function toArray() {
return $this->__toArray();
}
/**
* Alias to toArray()
* @return array
*/
function asArray() {
return $this->toArray();
}
/**
* NOT WORKING YET
*/
function getIterator() {
return $this ;
}
/**
* Alias to toArray()
* @return array
*/
function getArrayCopy() {
return $this->toArray() ;
}
/**
* serialize the collection
* @return string
*/
function __toString() {
return "".serialize($this->elements)."" ;
}
/**
* alias to __toString()
* @return string
*/
function toString() {
return $this->__toString();
}
}
?>
|