Commit c70e2692 authored by Avris's avatar Avris
Browse files

Cleanup

parent 38409593
Pipeline #15664981 failed with stage
......@@ -81,7 +81,8 @@ Just like with a simple array, you can also **iterate** over a Bag and **json_en
* `$bag->appendToElement($key, $value)` -- treats `$bag[$key]` as a list and appends `$value` at its end;
* `$bag->prependToElement($key, $value)` -- treats `$bag[$key]` as a list and prepends `$value` at its beginning;
* `$bag->map(function ($key, $value) {})` -- returns a new Bag, with values mapped by the callback function;
* `$bag->filter(function ($value, $key) {})` -- returns a new Bag, with only those values from the original Bag, for which the callback function returns true.
* `$bag->filter(function ($key, $value) {})` -- returns a new Bag, with only those values from the original Bag, for which the callback function returns true.
* `$bag->flatten()` -- returns a new Bag, with keys flattened, for instance `lorem.ipsum`.
### Set
......
......@@ -6,9 +6,6 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
/** @var array */
protected $array = [];
/**
* @param array $array
*/
public function __construct($array = [])
{
foreach (BagHelper::toArray($array) as $key => $value) {
......@@ -16,90 +13,53 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
}
}
/**
* @return array
*/
public function all()
public function all(): array
{
return $this->array;
}
/**
* @return array
*/
public function keys()
public function keys(): array
{
return array_keys($this->array);
}
/**
* @return int
*/
public function count()
public function count(): int
{
return count($this->array);
}
public function isEmpty()
public function isEmpty(): bool
{
return empty($this->array);
}
/**
* @param string $key
* @param mixed|null $default
* @return mixed
*/
public function get($key, $default = null)
{
return isset($this->array[$key]) ? $this->array[$key] : $default;
return $this->array[$key] ?? $default;
}
/**
* @param string $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* @param string $key
* @param mixed|null $default
* @return mixed
*/
public function __invoke($key, $default = null)
{
return $this->get($key, $default);
}
/**
* @param string $key
* @param mixed|null $default
* @return mixed
*/
public function getDeep($key, $default = null)
{
return Nested::get($this->array, explode('.', $key), $default);
}
/**
* @param string $key
* @param mixed $value
* @return Bag
*/
public function set($key, $value)
public function set($key, $value): self
{
$this->array[$key] = $value;
return $this;
}
/**
* @param string $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
......@@ -109,11 +69,7 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
}
}
/**
* @param string|string[] $key
* @return bool true if any $key is found
*/
public function has($key)
public function has($key): bool
{
if (!is_array($key)) {
return array_key_exists($key, $this->array);
......@@ -128,54 +84,36 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
return false;
}
/**
* @param string $offset
* @return bool
*/
public function offsetExists($offset)
public function offsetExists($offset): bool
{
return $this->has($offset);
}
/**
* @param string $key
* @return $this
*/
public function delete($key)
public function delete($key): self
{
unset($this->array[$key]);
return $this;
}
/**
* @param string $offset
*/
public function offsetUnset($offset)
{
$this->delete($offset);
}
/**
* @return $this
*/
public function clear()
public function clear(): self
{
$this->array = [];
return $this;
}
public function getIterator()
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->array);
}
/**
* @param array|\Traversable $array
* @return $this
*/
public function add($array)
public function add($array): self
{
foreach (BagHelper::toArray($array) as $key => $value) {
if (!isset($this->array[$key])) {
......@@ -186,11 +124,7 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
return $this;
}
/**
* @param array|\Traversable $array
* @return $this
*/
public function replace($array)
public function replace($array): self
{
foreach (BagHelper::toArray($array) as $key => $value) {
$this->set($key, $value);
......@@ -199,13 +133,7 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
return $this;
}
/**
* @param string $key
* @param mixed $value
* @return $this
* @throws \InvalidArgumentException
*/
public function appendToElement($key, $value)
public function appendToElement($key, $value): self
{
$array = $this->getArrayFromElement($key);
$array[] = $value;
......@@ -213,13 +141,7 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
return $this->set($key, $array);
}
/**
* @param string $key
* @param mixed $value
* @return $this
* @throws \InvalidArgumentException
*/
public function prependToElement($key, $value)
public function prependToElement($key, $value): self
{
$array = $this->getArrayFromElement($key);
array_unshift($array, $value);
......@@ -229,10 +151,8 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
protected function getArrayFromElement($key)
{
$array = $this->get($key);
if ($array === null) {
return [];
}
$array = $this->get($key, []);
if (!is_array($array)) {
throw new \InvalidArgumentException(sprintf(
'Cannot append to element "%s", because it\'s not an array',
......@@ -243,7 +163,7 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
return $array;
}
public function map(callable $callback)
public function map(callable $callback): self
{
$result = [];
foreach ($this->array as $key => $value) {
......@@ -251,17 +171,24 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
$result[$key] = $mapped;
}
return new Bag($result);
return new static($result);
}
public function filter(callable $callback)
public function filter(callable $callback): self
{
return new Bag(array_filter($this->array, $callback, ARRAY_FILTER_USE_BOTH));
$result = [];
foreach ($this->array as $key => $value) {
if ($callback($key, $value)) {
$result[$key] = $value;
}
}
return new static($result);
}
public function flatten(): Bag
public function flatten(): self
{
return new Bag(iterator_to_array($this->doFlatten($this->array)));
return new static(iterator_to_array($this->doFlatten($this->array)));
}
private function doFlatten($array, $base = [])
......@@ -277,15 +204,12 @@ class Bag implements \ArrayAccess, \IteratorAggregate, \Countable, \JsonSerializ
}
}
/**
* @return array
*/
public function jsonSerialize()
public function jsonSerialize(): array
{
return $this->array;
}
public function __debugInfo()
public function __debugInfo(): array
{
return $this->array;
}
......
<?php
namespace Avris\Bag;
class BagHelper
final class BagHelper
{
const THROW_EXCEPTION = '___throw_exception___';
/**
* @param mixed $object
* @return bool
*/
public static function isArray($object)
public static function isArray($object): bool
{
return is_array($object) || $object instanceof \Traversable;
}
/**
* @param mixed $object
* @return array
*/
public static function toArray($object)
public static function toArray($object): array
{
if ($object instanceof Bag) {
return $object->all();
......@@ -28,19 +20,16 @@ class BagHelper
return iterator_to_array($object);
}
if ($object === null) {
return [];
}
return is_array($object) ? $object : [$object];
}
/**
* @param array|object $object
* @param string $attr
* @param mixed|null $default
* @return mixed|null
* @throws NotFoundException
*/
public static function magicGetter($object, $attr, $default = null)
public static function magicGetter($object, string $attr, $default = null)
{
if ((is_array($object) || $object instanceof Bag) && isset($object[$attr])) {
if ((is_array($object) || $object instanceof \ArrayAccess) && isset($object[$attr])) {
return $object[$attr];
} elseif (is_object($object)) {
if (method_exists($object, $attr)) {
......@@ -61,20 +50,13 @@ class BagHelper
return $default;
}
/**
* @param array|object $object
* @param string $attr
* @param mixed $value
* @return array|object
* @throws \InvalidArgumentException
*/
public static function magicSetter(&$object, $attr, $value)
public static function magicSetter(&$object, string $attr, $value)
{
if (!is_array($object) && !is_object($object)) {
throw new \InvalidArgumentException(sprintf('Array or object expected, %s given', gettype($object)));
}
if (is_array($object)) {
if (is_array($object) || $object instanceof \ArrayAccess) {
$object[$attr] = $value;
} elseif (method_exists($object, 'set' . ucfirst($attr))) {
call_user_func([$object, 'set' . ucfirst($attr)], $value);
......
<?php
namespace Avris\Bag;
class Nested
final class Nested
{
/**
* @param array|object $object
* @param string[] $keys
* @param mixed|null $default
* @return mixed|null
*/
public static function get($object, array $keys, $default = null)
{
$current = $object;
foreach ($keys as $key) {
try {
$current = BagHelper::magicGetter($current, $key, BagHelper::THROW_EXCEPTION);
......@@ -23,12 +18,6 @@ class Nested
return $current;
}
/**
* @param array $array
* @param string[] $keys
* @param mixed $value
* @return mixed|null
*/
public static function set(array &$array, array $keys, $value)
{
if (!count($keys)) {
......@@ -54,6 +43,4 @@ class Nested
return $array;
}
}
<?php
namespace Avris\Bag;
class Set implements \IteratorAggregate, \JsonSerializable, \Countable
class Set implements \IteratorAggregate, \Countable, \JsonSerializable
{
/** @var array */
protected $values = [];
......@@ -21,34 +21,21 @@ class Set implements \IteratorAggregate, \JsonSerializable, \Countable
$this->values = array_unique($values);
}
/**
* @return string[]
*/
public function all()
{
return array_values($this->values);
}
/**
* @return int
*/
public function count()
public function count(): int
{
return count($this->values);
}
/**
* @return bool
*/
public function isEmpty()
public function isEmpty(): bool
{
return count($this->values) === 0;
}
/**
* @param mixed $value
* @return mixed
*/
protected function normalizeValue($value)
{
$callback = $this->callback;
......@@ -56,11 +43,7 @@ class Set implements \IteratorAggregate, \JsonSerializable, \Countable
return $callback ? $callback($value) : $value;
}
/**
* @param mixed $value
* @return $this
*/
public function add($value)
public function add($value): self
{
$value = $this->normalizeValue($value);
......@@ -71,11 +54,7 @@ class Set implements \IteratorAggregate, \JsonSerializable, \Countable
return $this;
}
/**
* @param array $values
* @return $this
*/
public function addMultiple(array $values)
public function addMultiple(array $values): self
{
foreach ($values as $value) {
$this->add($value);
......@@ -84,20 +63,12 @@ class Set implements \IteratorAggregate, \JsonSerializable, \Countable
return $this;
}
/**
* @param mixed $value
* @return bool
*/
public function has($value)
public function has($value): bool
{
return in_array($this->normalizeValue($value), $this->values, true);
}
/**
* @param mixed $value
* @return $this
*/
public function delete($value)
public function delete($value): self
{
$key = array_search($this->normalizeValue($value), $this->values, true);
......@@ -108,49 +79,34 @@ class Set implements \IteratorAggregate, \JsonSerializable, \Countable
return $this;
}
/**
* @return mixed
*/
public function first()
{
return reset($this->values);
}
/**
* @return mixed
*/
public function last()
{
return end($this->values);
}
public function clear()
public function clear(): self
{
$this->values = [];
return $this;
}
/**
* @return \ArrayIterator
*/
public function getIterator()
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->values);
}
/**
* @return array
*/
public function jsonSerialize()
public function jsonSerialize(): array
{
return array_values($this->values);
}
/**
* @return array
*/
public function __debugInfo()
public function __debugInfo(): array
{
return array_values($this->values);
}
......
......@@ -7,7 +7,7 @@ use PHPUnit\Framework\TestCase;
/**
* @covers \Avris\Bag\BagHelper
*/
class BagHelperTest extends TestCase
final class BagHelperTest extends TestCase
{
public function testIsArray()
{
......@@ -43,10 +43,15 @@ class BagHelperTest extends TestCase
);
$this->assertSame(
[null],
[],
BagHelper::toArray(null)
);
$this->assertSame(
[0],
BagHelper::toArray(0)
);
$this->assertSame(
['foo'],
BagHelper::toArray('foo')
......
......@@ -7,7 +7,7 @@ use PHPUnit\Framework\TestCase;
/**
* @covers \Avris\Bag\Bag
*/
class BagTest extends TestCase
final class BagTest extends TestCase
{
/** @var array */
protected $testArray;
......@@ -292,21 +292,48 @@ class BagTest extends TestCase
$bag = new Bag([
'foo' => 'bar',
'lorem' => 'ipsum',
'test' => 'foo',
'test' => 'fóó',
]);
$callback = function ($key, $value) {
return $key === 'foo' || $value === 'foo';
return $key === 'foo' || $value === 'fóó';
};
$filteredBag = $bag->filter($callback);
$this->assertInstanceOf(Bag::class, $filteredBag);
$this->assertSame([
'foo' => 'bar',
'test' => 'foo',
'test' => 'fóó',
], $filteredBag->all());
}
public function testFlatten()
{
$bag = new Bag([
'foo' => [
'bar' => 'baz',
'lorem' => 'ipsum',
],
'abc.def' => 'ghi',
'obj' => $this->testObject,
'bag' => new Bag([
'osiem' => 8,
'gay' => 'ok',
]),
]);
$flat = $bag->flatten();
$this->assertEquals(new Bag([
'foo.bar' => 'baz',
'foo.lorem' => 'ipsum',
'abc.def' => 'ghi',
'obj' => $this->testObject,
'bag.osiem' => 8,
'bag.gay' => 'ok',