add ExtractTune use case

This commit is contained in:
2018-04-30 17:24:02 -04:00
parent 3817394951
commit e8c8709976
42 changed files with 1388 additions and 5047 deletions

View File

@@ -0,0 +1,492 @@
<?php
namespace XaiCorp\AbcParser\Domain\Core;
use Closure;
use Enzyme\Collection\BaseCollection;
use Enzyme\Collection\CollectionException;
class Collection extends BaseCollection
{
/**
* @param $initial
* @param callable $callback
* @return mixed
*/
public function reduce($initial, callable $callback)
{
return array_reduce($this->items, $callback, $initial);
}
/**
* @param \XaiCorp\AbcParser\Domain\Core\Collection $collection
* @return static
*/
public function merge(Collection $collection)
{
$results = $this->items;
foreach ($collection as $key => $value) {
if (is_numeric($key)) {
$results[] = $value;
} else {
$results[$key] = $value;
}
}
return new static($results);
}
/**
* Static helper method to instantiate a new collection. Useful for when you
* want to immediately chain a method. Eg: Collection::make([1, 2, 3])->map(...).
*
* @param array $initial
*
* @return Collection
*/
public static function make(array $initial)
{
return new static($initial);
}
/**
* Get a PHP style array from the current collection.
*
* @return array
*/
public function toArray()
{
return $this->items;
}
/**
* Whether the collection has the specified key, and/or value associated
* with the specified key.
*
* @param string $key
* @param mixed $value
*
* @return bool
*/
public function has($key, $value = null)
{
$key_exists = self::keyExists($key, $this->items);
return null !== $value
? $value === $this->get($key)
: $key_exists;
}
/**
* Get the value associated with the specified key.
*
* @param string $key
*
* @throws CollectionException If the key does not exist.
*
* @return mixed
*/
public function get($key)
{
if (false === self::keyExists($key, $this->items)) {
throw new CollectionException(
"An element with the key [${key}] does not exist."
);
}
return $this->items[$key];
}
/**
* Get the value associated with the specified key or return a default value
* instead if it does not exist.
*
* @param string $key
* @param mixed $default
*
* @return mixed
*/
public function getOrDefault($key, $default = null)
{
try {
return $this->get($key);
} catch (CollectionException $e) {
return $default;
}
}
/**
* Execute the given callback function for each element in this collection.
*
* @param Closure $fn
*/
public function each(Closure $fn)
{
foreach ($this->items as $key => $value) {
if (false === $fn($value, $key)) {
break;
}
}
}
/**
* Execute the given callback function for each element in this collection
* and save the results to a new collection.
*
* @param Closure $fn
*
* @return Collection
*/
public function map(Closure $fn)
{
$results = [];
foreach ($this->items as $key => $value) {
$results[] = $fn($value, $key);
}
return new static($results);
}
/**
* Execute the given callback function for each element in this collection
* and save the results to a new collection with the specified key. The
* callback function should return a 1 element associative array, eg:
* ['key' => 'value'] to be mapped.
*
* @param Closure $fn
*
* @return Collection
*/
public function mapWithKey(Closure $fn)
{
$results = [];
foreach ($this->items as $key => $value) {
$result = $fn($value, $key);
$keys = array_keys($result);
if (count($keys) < 1) {
throw new CollectionException(
'Map with key expects a 1 element associative array.'
);
}
$results[$keys[0]] = $result[$keys[0]];
}
return new static($results);
}
/**
* Pluck out all values in this collection which have the specified key.
*
* @param string $pluck_key
* @param bool $deep Whether to traverse into sub-arrays.
*
* @return Collection
*/
public function pluck($pluck_key, $deep = true)
{
return self::pluckKey($this->items, $pluck_key, $deep);
}
/**
* Get the number of elements in this collection.
*
* @return int
*/
public function count()
{
return count($this->items);
}
/**
* Whether this collection is empty.
*
* @return bool
*/
public function isEmpty()
{
return $this->count() < 1;
}
/**
* Get the value of the first element in this collection.
*
* @throws CollectionException If the collection is empty.
*
* @return mixed
*/
public function first()
{
if (true === $this->isEmpty()) {
throw new CollectionException(
'Cannot get first item as the collection is empty.'
);
}
return reset($this->items);
}
/**
* Get the value of the first element in this collection or return the
* default value specified if the collection is empty.
*
* @param mixed $default
*
* @return mixed
*/
public function firstOrDefault($default = null)
{
try {
return $this->first();
} catch (CollectionException $e) {
return $default;
}
}
/**
* Get the value of the last element in this collection.
*
* @throws CollectionException If the collection is empty.
*
* @return mixed
*/
public function last()
{
if (true === $this->isEmpty()) {
throw new CollectionException(
'Cannot get last element as collection is empty.'
);
}
end($this->items);
$key = key($this->items);
reset($this->items);
return $this->items[$key];
}
/**
* Get the value of the last element in this collection or return the
* default value specified if the collection is empty.
*
* @param mixed $default
*
* @return mixed
*/
public function lastOrDefault($default = null)
{
try {
return $this->first();
} catch (CollectionException $e) {
return $default;
}
}
/**
* Get a new collection of only the elements in the current collection
* that have the specified keys.
*
* @param array $keys
*
* @return Collection
*/
public function only(array $keys)
{
return $this->filter(function ($value, $key) use ($keys) {
return true === self::keyExists($key, array_flip($keys));
});
}
/**
* Get a new collection of all the elements in the current collection
* except those that have the specified keys.
*
* @param array $keys
*
* @return Collection
*/
public function except(array $keys)
{
return $this->filter(function ($value, $key) use ($keys) {
return false === self::keyExists($key, array_flip($keys));
});
}
/**
* Return a new collection with the current collection's elements plus the
* given value pushed onto the end of the array.
*
* @param mixed $value
*
* @return Collection
*/
public function push($value)
{
$items = $this->items;
$items[] = $value;
return new static($items);
}
/**
* Return a new collection with the current collection's elements plus the
* given key and value pushed onto the end of the array.
*
* @param string $key
* @param mixed $value
*
* @return Collection
*/
public function pushWithKey($key, $value)
{
$items = $this->items;
$items[$key] = $value;
return new static($items);
}
/**
* Return a new collection with the current collection's elements plus the
* given array pushed onto the end of the array.
*
* @param array $data
*
* @return Collection
*/
public function pushArray(array $data)
{
$items = $this->items;
foreach ($data as $key => $value) {
if (true === is_int($key)) {
$items[] = $value;
} else {
$items[$key] = $value;
}
}
return new static($items);
}
/**
* Return a new collection with a subset of all the current collection's
* elements that pass the given callback functions truth test.
*
* @param Closure $fn
*
* @return static
*/
public function filter(Closure $fn)
{
$results = [];
foreach ($this->items as $key => $value) {
if (true === $fn($value, $key)) {
$results[$key] = $value;
}
}
// Pushing this new array will normalize numeric keys if they exist.
// After filtering, they may not start at zero and sequentially
// go upwards, which is generally not expected.
return (new static())->pushArray($results);
}
/**
* Sort the collection using the provided callback function. Same expected
* parameters and the PHP usort function.
*
* @param Closure $fn
*
* @return Collection
*/
public function sort(Closure $fn)
{
$sorted = $this->items;
$result = usort($sorted, $fn);
if (false === $result) {
throw new CollectionException(
'The collection could be not sorted.'
);
}
return new static($sorted);
}
/**
* Whether this collection has the specified number of elements within the
* given range or equal too or above the minimum value specified.
*
* @param int $min
* @param int $max Default is null.
*
* @return bool
*/
public function hasCount($min, $max = null)
{
if (null === $max) {
return $this->count() >= $min;
}
return $this->count() >= $min
&& $this->count() <= $max;
}
/**
* Get a list of the keys used by this collection.
*
* @return array
*/
public function keys()
{
return array_keys($this->items);
}
/**
* Checks whether the specified key exists in the given collection.
*
* @param string $key
* @param array $collection
*
* @return bool
*/
protected static function keyExists($key, array $collection)
{
return true === isset($collection[$key]);
}
/**
* Pluck all the values that have the specified key from the given
* collection.
*
* @param array $collection
* @param string $pluck_key
* @param bool $deep Whether to traverse into sub-arrays.
*
* @return Collection
*/
protected static function pluckKey(array $collection, $pluck_key, $deep)
{
$results = [];
foreach ($collection as $key => $value) {
if (true === $deep && true === is_array($value)) {
$deeper_results = self::pluckKey(
$value,
$pluck_key,
$deep
)->toArray();
foreach ($deeper_results as $deep_value) {
$results[] = $deep_value;
}
continue;
}
if ($key === $pluck_key) {
$results[] = $value;
}
}
return new static($results);
}
}

View File

@@ -80,6 +80,20 @@ class Tune implements EntityInterface
}
}
public function getETag()
{
return md5(implode(';', array_flatten([
$this->getTitles(),
$this->getAuthors(),
$this->getComposers(),
$this->getGroups(),
$this->getHistory(),
$this->getOrigins(),
$this->getRhythms(),
//TODO: add settings
])));
}
/**
* @param UnsignedIntegerAtom $index
* @return $this

View File

@@ -1,8 +1,6 @@
<?php
namespace XaiCorp\AbcParser\Domain\Core;
use Enzyme\Collection\Collection;
class TuneCollection extends Collection
{
/**
@@ -16,4 +14,19 @@ class TuneCollection extends Collection
{
return parent::first();
}
public function unique()
{
$result = [];
/**
* @var int $key
* @var Tune $tune
*/
foreach ($this->items as $key => $tune) {
$tuneId = $tune->getETag();
$result[$tuneId] = $tune;
}
return new TuneCollection(array_values($result));
}
}

View File

@@ -41,6 +41,15 @@ class Builder
$this->tune->addSetting($this->setting);
}
public function __clone()
{
$this->collection = new TuneCollection();
$this->tune = new Tune([]);
$this->setting = new Setting();
$this->tune->addSetting($this->setting);
}
public function getTune()
{
return $this->tune;