A fast and light-weight component library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

440 lines
8.5 KiB

<?php
/**
* Collection class with dynamic members
* Similar functionality to an Array or Dictionary class
* Typically holding a collection/array of Entity members
*
*
* @link https://laravel.com/docs/5.4/eloquent-collections#available-methods
*
* @link http://php.net/manual/en/class.iterator.php
* @link http://php.net/manual/en/class.arrayaccess.php
* @link http://php.net/manual/en/class.countable.php
* @link http://php.net/manual/en/class.iteratoraggregate.php
* @link http://php.net/manual/en/class.jsonserializable.php
*
*
* @author Trevor Herselman <therselman@gmail.com>
*/
namespace Twister\ORM;
class Collection implements \Iterator, \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
{
protected $members = null;
public function __construct(array $members = [])
{
$this->members =& $members;
}
/**
*
*/
public function find(...$params)
{
if (count($params) === 1)
return count($this->members);
}
/**
* Get the keys of the collection members.
*
* @return static
*/
public function keys()
{
return new static(array_keys($this->members)); // or array_keys($this->members)
}
/**
* Get the items in the collection that are not present in the given array.
*
* @param mixed $items
* @return static
*/
public function diff($items)
{
return new static(array_diff($this->members, $this->getArrayableItems($items)));
}
/**
* Execute a callback over each item.
*
* @param callable $callback
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->members as $key => $member)
{
if ($callback($key, $member) === false) {
break;
}
}
return $this;
}
/**
* Run a map over each of the members.
*
* @link http://php.net/manual/en/function.array-map.php
*
* @param callable $callback
* @return static
*/
public function map(callable $callback)
{
$keys = array_keys($this->members);
$members = array_map($callback, $this->members, $keys);
return new static(array_combine($keys, $members));
}
/**
* Merge the collection with the given items.
*
* @param mixed $items
* @return static
*/
public function merge($items)
{
return new static(array_merge($this->items, $this->getArrayableItems($items)));
}
/**
* Results array of items from Collection or Arrayable.
*
* Used by PHP functions that only accept a standard array
*
* @param mixed $items
* @return array
*/
protected function getArrayableItems($items)
{
if ($items instanceof self) {
return $items->all();
} else if (is_array($items)) {
return $items;
} else if ($items instanceof Arrayable) {
return $items->toArray();
} else if ($items instanceof Jsonable) {
return json_decode($items->toJson(), true);
} else if (is_object($items) && method_exists($items, 'toArray')) {
return $items->toArray();
}
return (array) $items;
}
/**
* Get and remove the last member from the collection.
*
* @link http://php.net/manual/en/function.array-pop.php
*
* @return mixed
*/
public function pop()
{
return array_pop($this->members);
}
/**
* Push an item onto the end of the collection.
*
* @link http://php.net/manual/en/function.array-push.php
*
* @param mixed $value
* @return $this
*/
public function push($value)
{
$this->members[] = $value;
return $this;
}
/**
* Put an item in the collection by key.
*
* @param mixed $key
* @param mixed $value
* @return $this
*/
public function put($key, $value)
{
$this->members[$key] = $value;
return $this;
}
/**
* Get one or more random members from the collection.
*
* @link http://php.net/manual/en/function.array-rand.php
*
* @param int $num
* @return mixed
*/
public function random($num = 1)
{
if ($num == 1)
return $this->members[array_rand($this->members)];
$keys = array_rand($this->members, $num);
return new static(array_intersect_key($this->members, array_flip($keys)));
}
/**
* Get and remove the first item from the collection.
*
* @link http://php.net/manual/en/function.array-shift.php
*
* @return mixed
*/
public function shift()
{
return array_shift($this->members);
}
/**
* Shuffle the members in the collection.
*
* @return static
*/
public function shuffle()
{
$members = $this->members;
shuffle($members);
return new static($members);
}
/**
* Slice the underlying collection array.
*
* @param int $offset
* @param int $length
* @param bool $preserve_keys
* @return static
*/
public function slice($offset, $length = null, $preserve_keys = false)
{
return new static(array_slice($this->members, $offset, $length, $preserve_keys));
}
/**
* Take the first or last {$limit} members.
*
* @param int $limit
* @return static
*/
public function take($limit)
{
return $limit < 0 ? $this->slice($limit, abs($limit)) : $this->slice(0, $limit);
}
/**
* Run a filter over each of the members.
*
* @link http://php.net/manual/en/function.array-filter.php
*
* @param callable|null $callback
* @return static
*/
public function filter(callable $callback = null)
{
return new static($callback ? array_filter($this->members, $callback) : array_filter($this->members));
}
/**
* Reset the keys on the underlying array.
*
* @link http://php.net/manual/en/function.array-values.php
*
* @return static
*/
public function values()
{
return new static(array_values($this->members));
}
/**
* Prepend one or more members to the beginning of the collection
*
* @link http://php.net/manual/en/function.array-values.php
*
* @return $this
*/
public function unshift(...$values)
{
array_unshift($this->members, $values);
return $this;
}
/**
* Flip the members of the collection.
*
* @return static
*/
public function flip()
{
return new static(array_flip($this->members));
}
/**
* Determine if the collection is empty or not.
*
* @return bool
*/
public function isEmpty()
{
return empty($this->members);
}
/**
* Determine if the collection is not empty.
*
* @return bool
*/
public function isNotEmpty()
{
return ! empty($this->members);
}
/**
* Get the collection of items as a plain array.
*
* @return array
*/
/**
* Workaround for the `array access functions` eg. array_push($obj->toArray(), $value);
*/
public function toArray()
{
return $this->members;
}
/**
* Get all of the items in the collection.
*
* @alias toArray()
*
* @return array
*/
public function all()
{
return $this->members;
}
/**
* JsonSerializable interface
*/
public function jsonSerialize()
{
return $this->members;
}
public function __toString()
{
return json_encode($this->members);
}
/**
* Get an external iterator to the members.
*
* IteratorAggregate interface
*
* @link http://php.net/manual/en/class.iteratoraggregate.php
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->members);
}
/**
* Iterator interface
*/
public function rewind()
{
return reset($this->members);
}
public function current()
{
return current($this->members);
}
public function key()
{
return key($this->members);
}
public function next()
{
return next($this->members);
}
public function valid()
{
return key($this->members) !== null; // or current($this->attributes) !== false
}
/**
* Countable interface
*/
public function count()
{
return count($this->members);
}
/**
* @alias count()
*/
public function length()
{
return count($this->members);
}
/**
* ArrayAccess interface
*/
public function offsetGet($idx) // eg. var_dump($obj['two']);
{
return $this->members[$idx];
}
public function offsetSet($idx, $value) // eg. $obj['two'] = 'A value';
{
$this->members[$idx] = $value;
}
public function offsetExists($idx) // eg. isset($obj['two'])
{
return isset($this->members[$idx]);
}
public function offsetUnset($idx) // eg. unset($obj['two']);
{
unset($this->members[$idx]);
}
}