Skip to content

Instantly share code, notes, and snippets.

@ricklancee
Created March 4, 2015 22:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ricklancee/7d767e84f2050386d610 to your computer and use it in GitHub Desktop.
Save ricklancee/7d767e84f2050386d610 to your computer and use it in GitHub Desktop.
Collection
<?php
namespace RickLancee;
use Closure;
use Countable;
use ArrayIterator;
use IteratorAggregate;
class Collection implements Countable, IteratorAggregate
{
protected $items;
public function __construct(array $items = [])
{
$this->items = $items;
}
/**
* Gets a new ArrayIterator instance.
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->items);
}
/**
* Gets all items from the Collection.
*
* @return array
*/
public function all()
{
return $this->items;
}
/**
* Gets an item by key from the Collection
*
* @param mixed $key
* @return mixed
*/
public function get($key)
{
return $this->items[$key];
}
/**
* Get the first item of the Collection.
*
* @return mixed
*/
public function first()
{
return reset($this->items);
}
/**
* Gets the last item of the Collection.
*
* @return Mixed
*/
public function last()
{
return end($this->items);
}
/**
* Adds a new item to the Collection.
*
* @param mixed $key
* @param mixed $value
* @return void
*/
public function add($key, $value = null)
{
if ($value === null) {
$this->items[] = $key;
} else {
$this->items[$key] = $value;
}
}
/**
* Removes an item by key from the Collection.
*
* @param mixed $key
* @return void
*/
public function remove($key)
{
unset($this->items[$key]);
}
/**
* Seach for a given key in the collection.
*
* @param mixed $key
* @return mixed
*/
public function search($key)
{
return array_search($key, $this->items);
}
/**
* Re-indexes the array keys on the Collection.
*
* @return void
*/
public function values()
{
$this->items = array_values($this->items);
}
/**
* Sort through each item with a callback.
*
* @param Closure $callback
* @return void
*/
public function sort(Closure $callback)
{
uasort($this->items, $callback);
}
/**
* Loop over each element in the Collection and apply
* the callback on it.
*
* @param Closure $callback
* @return void
*/
public function each(Closure $callback)
{
array_map($callback, $this->items);
}
/**
* Loop over each element in the Collection and apply
* the callback on it, modifing the values.
*
* @param Closure $callback
* @return
*/
public function map(Closure $callback)
{
return new self(array_map(
$callback,
$this->items,
array_keys($this->items)
));
}
/**
* Run a Closure over each item and return a new Collection.
*
* @param Closure $callback
* @return Collection
*/
public function filter(Closure $callback)
{
return new self(array_filter($this->items, $callback));
}
/**
* Push an item onto the end of the Collection.
*
* @param mixed $value
* @return void
*/
public function push($value)
{
$this->items[] = $value;
}
/**
* Push an item onto the start of the Collection.
*
* @param mixed $value
* @return void
*/
public function prepend($value)
{
array_unshift($this->items, $value);
}
/**
* Counts the amount of items on the array.
*
* @return int
*/
public function count()
{
return count($this->items);
}
/**
* Returns an array containing all keys of the Collection.
*
* @return array
*/
public function keys()
{
return array_keys($this->items);
}
/**
* Pulls the last item from the Collection.
*
* @return mixed
*/
public function pop()
{
return array_pop($this->items);
}
/**
* Pulls the first item from the Collection.
*
* @return mixed
*/
public function shift()
{
return array_shift($this->items);
}
/**
* Check if a given item exists in the Collection.
*
* @param mixed $item
* @return boolean Returns true if it exists, otherwise false.
*/
public function contains($item)
{
return in_array($item, $this->items);
}
/**
* Check if Collection is empty.
*
* @return boolean
*/
public function isEmpty()
{
return empty($this->items);
}
}
<?php
use Lancee\Collection;
class CollectionTest extends \PHPUnit_Framework_TestCase
{
/** @var array */
private $items = ['Basket', 'Currency', 'Honey', 'Money', 'Dough'];
/** @var Collection */
private $collection;
public function setUp()
{
$this->collection = new Collection($this->items);
}
public function testGetShouldGetItemByKey()
{
$this->assertEquals('Honey', $this->collection->get(2));
}
public function testAddShouldAddItemWithoutKey()
{
$this->collection->add('Copter');
$this->assertEquals('Copter', $this->collection->get(5));
}
public function testAddShouldAddItemWithKey()
{
$this->collection->add(5, 'Copter');
$this->assertEquals('Copter', $this->collection->get(5));
}
public function testAllShouldGetAllItems()
{
$this->assertEquals($this->items, $this->collection->all());
}
public function testContainsItemShouldExist()
{
$this->assertTrue($this->collection->contains('Basket'));
}
public function testIsEmptyArrayShouldNotBeEmpty()
{
$this->assertFalse($this->collection->isEmpty());
}
public function testIsEmptyEmptyCollectionArrayShouldBeEmpty()
{
$collection = new Collection;
$this->assertTrue($collection->isEmpty());
}
public function testFirstShouldGetFirstItem()
{
$this->assertEquals('Basket', $this->collection->first());
}
public function testLastShouldGetLastItem()
{
$this->assertEquals('Dough', $this->collection->last());
}
public function testAllShouldGetAllKeys()
{
$keys = [0, 1, 2, 3, 4];
$this->assertEquals($this->collection->keys(), $keys);
}
public function testPopShouldGetAndRemoveLastItem()
{
$item = $this->collection->pop();
$this->assertEquals(4, $this->collection->count());
$this->assertEquals($item, 'Dough');
}
public function testShiftShouldGetAndRemoveFirstItem()
{
$item = $this->collection->shift();
$this->assertEquals(4, $this->collection->count());
$this->assertEquals($item, 'Basket');
}
public function testPushShouldPushItemOnCollection()
{
$this->collection->push('pushed');
$this->assertEquals(6, $this->collection->count());
$this->assertEquals('pushed', $this->collection->get(5));
}
public function testPrependShouldPrependItemOnCollection()
{
$this->collection->prepend('prepended');
$this->assertEquals(6, $this->collection->count());
$this->assertEquals('prepended', $this->collection->get(0));
}
public function testRemoveShouldRemoveItemFromCollection()
{
$this->collection->remove(0);
$this->assertEquals(4, $this->collection->count());
$this->assertFalse($this->collection->contains('Basket'));
}
public function testSearchShouldFindItem()
{
$this->assertEquals(1, $this->collection->search('Currency'));
}
public function testValuesShouldReIndexMessyKeys()
{
$messy = [0 => 'Basket', 1 => 'Currency', 4 => 'Dough'];
$collection = new Collection($messy);
$collection->values();
$this->assertEquals([0, 1, 2], $collection->keys());
}
public function testSortShouldSortItemsInCollection()
{
$this->collection->sort(function ($a, $b) {
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
});
$this->assertEquals([
0 => 'Basket',
1 => 'Currency',
4 => 'Dough',
2 => 'Honey',
3 => 'Money'
], $this->collection->all());
}
public function testEachShouldRunCallback()
{
$this->collection->each(function($item) {
$this->assertTrue(is_string($item));
});
}
public function testFilterShouldFilterOutItem()
{
$filterdCollection = $this->collection->filter(function($item) {
return $item !== 'Basket';
});
$this->assertEquals(4, $filterdCollection->count());
$this->assertFalse($filterdCollection->contains('Basket'));
}
public function testMapShouldAppendWordAfterEachItem()
{
$mappedCollection = $this->collection->map(function($item) {
return $item . '-mapped';
});
$this->assertEquals([
'Basket-mapped',
'Currency-mapped',
'Honey-mapped',
'Money-mapped',
'Dough-mapped'
], $mappedCollection->all());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment