Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/Interfaces/WritableCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ public function set($key, $value);
*/
public function lazy($key, callable $initializer);

/**
* Removes a key from the collection and returns its value
*
* @param mixed $key The key
* @param mixed $default (optional) A default value to return if the collection does not
* contain `$key`. Prevents NoSuchValueException from being thrown.
*
* @return mixed The value associated with the key
*/
public function take($key, $default = null);

/**
* Removes a key from the array
*
Expand Down
34 changes: 0 additions & 34 deletions src/LazyInitializer.php

This file was deleted.

45 changes: 34 additions & 11 deletions src/Traits/ReadableCollectionTrait.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php namespace BapCat\Collection\Traits;

use BapCat\Collection\Exceptions\NoSuchKeyException;
use BapCat\Collection\LazyInitializer;
use BapCat\Collection\Interfaces\Collection;

/**
Expand Down Expand Up @@ -43,14 +42,12 @@ public function get($key, $default = null) {
}
}

// Grab the value
$value = $this->collection[$key];

// Is it a lazy-loaded value
if($value instanceof LazyInitializer) {
// Evaluate and cache the result
if(array_key_exists($key, $this->lazy)) {
$value = $value($key);
$this->collection[$key] = $value;
unset($this->lazy[$key]);
}

return $value;
Expand All @@ -68,7 +65,16 @@ public function first() {
throw new NoSuchKeyException(null, 'Can\'t get first value from empty collection');
}

return reset($this->collection);
$value = reset($this->collection);
$key = key($this->collection);

if(array_key_exists($key, $this->lazy)) {
$value = $value($key);
$this->collection[$key] = $value;
unset($this->lazy[$key]);
}

return $value;
}

/**
Expand All @@ -83,7 +89,16 @@ public function last() {
throw new NoSuchKeyException(null, 'Can\'t get last value from empty collection');
}

return end($this->collection);
$value = end($this->collection);
$key = key($this->collection);

if(array_key_exists($key, $this->lazy)) {
$value = $value($key);
$this->collection[$key] = $value;
unset($this->lazy[$key]);
}

return $value;
}

/**
Expand All @@ -93,6 +108,14 @@ public function last() {
* values contained in the collection.
*/
public function all() {
if(!empty($this->lazy)) {
foreach($this->lazy as $key) {
$this->collection[$key] = $this->collection[$key]($key);
}

$this->lazy = [];
}

return $this->collection;
}

Expand All @@ -105,7 +128,7 @@ public function all() {
* `function($key, $value)`
*/
public function each(callable $callback) {
array_walk($this->collection, $callback);
array_walk($this->all(), $callback);
}

/**
Expand All @@ -114,7 +137,7 @@ public function each(callable $callback) {
* @returns array An array of all keys contained in the collection
*/
public function keys() {
return array_keys($this->collection);
return array_keys($this->all());
}

/**
Expand All @@ -123,7 +146,7 @@ public function keys() {
* @returns array An array of all values contained in the collection
*/
public function values() {
return array_values($this->collection);
return array_values($this->all());
}

/**
Expand All @@ -132,7 +155,7 @@ public function values() {
* @returns int The size of the collection
*/
public function size() {
return count($this->collection);
return count($this->all());
}

/**
Expand Down
35 changes: 33 additions & 2 deletions src/Traits/WritableCollectionTrait.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php namespace BapCat\Collection\Traits;

use BapCat\Collection\LazyInitializer;
use BapCat\Collection\Exceptions\NoSuchKeyException;

/**
* A basic implementation of WritableCollectionInterface
Expand All @@ -11,6 +11,13 @@ trait WritableCollectionTrait {
*/
protected $collection = [];

/**
* Holds all lazy-loaded keys
*
* @var array<mixed>
*/
protected $lazy = [];

/**
* Constructs a new WritableCollectionTrait
*
Expand Down Expand Up @@ -50,7 +57,31 @@ public function set($key, $value) {
* the desired value upon first request.
*/
public function lazy($key, callable $initializer) {
$this->collection[$key] = new LazyInitializer($initializer);
$this->collection[$key] = $initializer;
$this->lazy[$key] = $key;
}

/**
* {@inheritdoc}
*/
public function take($key, $default = null) {
if(!array_key_exists($key, $this->collection)) {
if(func_num_args() < 2) {
throw new NoSuchKeyException($key);
} else {
return $default;
}
}

$value = $this->collection[$key];
$this->remove($key);

if(array_key_exists($key, $this->lazy)) {
$value = $value($key);
unset($this->lazy[$key]);
}

return $value;
}

/**
Expand Down
77 changes: 77 additions & 0 deletions tests/WritableCollectionTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

use BapCat\Collection\Exceptions\NoSuchKeyException;
use BapCat\Collection\Traits\WritableCollectionTrait;

class WritableCollectionTraitTest extends PHPUnit_Framework_TestCase {
private $trait;
private $collection;

public function setUp() {
$this->trait = $this
->getMockBuilder(WritableCollectionTrait::class)
->getMockForTrait()
;

$class = new ReflectionClass($this->trait);
$this->collection = $class->getProperty('collection');
$this->collection->setAccessible(true);
}

public function testAdd() {
$this->trait->add('test');

$this->assertSame(['test'], $this->getCollection());

$this->trait->add('test2');

$this->assertSame(['test', 'test2'], $this->getCollection());
}

public function testSet() {
$this->trait->set('key1', 'val1');

$this->assertSame(['key1' => 'val1'], $this->getCollection());

$this->trait->set('key2', 'val2');

$this->assertSame(['key1' => 'val1', 'key2' => 'val2'], $this->getCollection());
}

public function testAddAndSet() {
$this->trait->add('test');
$this->trait->set('key1', 'val1');

$this->assertSame(['test', 'key1' => 'val1'], $this->getCollection());
}

public function testTake() {
$this->setCollection(['key1' => 'val1', 'key2' => 'val2']);

$this->assertSame(['key1' => 'val1', 'key2' => 'val2'], $this->getCollection());
$this->assertSame('val1', $this->trait->take('key1'));
$this->assertSame(['key2' => 'val2'], $this->getCollection());
$this->assertSame('already removed', $this->trait->take('key1', 'already removed'));

$this->setExpectedException(NoSuchKeyException::class);
$this->trait->take('non-existant key');
}

public function testRemove() {
$this->setCollection(['key1' => 'val1', 'key2' => 'val2']);

$this->assertSame(['key1' => 'val1', 'key2' => 'val2'], $this->getCollection());

$this->trait->remove('key1');

$this->assertSame(['key2' => 'val2'], $this->getCollection());
}

private function getCollection() {
return $this->collection->getValue($this->trait);
}

private function setCollection(array $collection) {
$this->collection->setValue($this->trait, $collection);
}
}