diff --git a/composer.json b/composer.json index 09d4855..a2cf823 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "Affinity4\\SlimSupport\\": "src/" }, "files": [ - "./src/Support/helpers.php" + "./src/Support/helpers.php", + "./src/Collections/helpers.php" ] }, "autoload-dev": { diff --git a/src/Collections/helpers.php b/src/Collections/helpers.php new file mode 100644 index 0000000..bf69e47 --- /dev/null +++ b/src/Collections/helpers.php @@ -0,0 +1,15 @@ + + */ + public function toArray(); +} diff --git a/src/Contracts/Support/Jsonable.php b/src/Contracts/Support/Jsonable.php new file mode 100644 index 0000000..95d9890 --- /dev/null +++ b/src/Contracts/Support/Jsonable.php @@ -0,0 +1,14 @@ + + * @implements \ArrayAccess + */ +class Fluent implements Arrayable, \ArrayAccess, Jsonable, \JsonSerializable +{ + /** + * All of the attributes set on the fluent instance. + * + * @var array + */ + protected $attributes = []; + + /** + * Create a new fluent instance. + * + * @param iterable $attributes + * @return void + */ + public function __construct($attributes = []) + { + foreach ($attributes as $key => $value) { + $this->attributes[$key] = $value; + } + } + + /** + * Get an attribute from the fluent instance. + * + * @template TGetDefault + * + * @param TKey $key + * @param TGetDefault|(\Closure(): TGetDefault) $default + * @return TValue|TGetDefault + */ + public function get($key, $default = null) + { + if (array_key_exists($key, $this->attributes)) { + return $this->attributes[$key]; + } + + return value($default); + } + + /** + * Get the attributes from the fluent instance. + * + * @return array + */ + public function getAttributes() + { + return $this->attributes; + } + + /** + * Convert the fluent instance to an array. + * + * @return array + */ + public function toArray() + { + return $this->attributes; + } + + /** + * Convert the object into something JSON serializable. + * + * @return array + */ + public function jsonSerialize(): array + { + return $this->toArray(); + } + + /** + * Convert the fluent instance to JSON. + * + * @param int $options + * @return string + */ + public function toJson($options = 0) + { + return json_encode($this->jsonSerialize(), $options); + } + + /** + * Determine if the given offset exists. + * + * @param TKey $offset + * @return bool + */ + public function offsetExists($offset): bool + { + return isset($this->attributes[$offset]); + } + + /** + * Get the value for a given offset. + * + * @param TKey $offset + * @return TValue|null + */ + public function offsetGet($offset): mixed + { + return $this->get($offset); + } + + /** + * Set the value at the given offset. + * + * @param TKey $offset + * @param TValue $value + * @return void + */ + public function offsetSet($offset, $value): void + { + $this->attributes[$offset] = $value; + } + + /** + * Unset the value at the given offset. + * + * @param TKey $offset + * @return void + */ + public function offsetUnset($offset): void + { + unset($this->attributes[$offset]); + } + + /** + * Handle dynamic calls to the fluent instance to set attributes. + * + * @param TKey $method + * @param array{0: ?TValue} $parameters + * @return $this + */ + public function __call($method, $parameters) + { + $this->attributes[$method] = count($parameters) > 0 ? reset($parameters) : true; + + return $this; + } + + /** + * Dynamically retrieve the value of an attribute. + * + * @param TKey $key + * @return TValue|null + */ + public function __get($key) + { + return $this->get($key); + } + + /** + * Dynamically set the value of an attribute. + * + * @param TKey $key + * @param TValue $value + * @return void + */ + public function __set($key, $value) + { + $this->offsetSet($key, $value); + } + + /** + * Dynamically check if an attribute is set. + * + * @param TKey $key + * @return bool + */ + public function __isset($key) + { + return $this->offsetExists($key); + } + + /** + * Dynamically unset an attribute. + * + * @param TKey $key + * @return void + */ + public function __unset($key) + { + $this->offsetUnset($key); + } +} diff --git a/tests/Collections/HelperFunctionsTest.php b/tests/Collections/HelperFunctionsTest.php new file mode 100644 index 0000000..7fd032d --- /dev/null +++ b/tests/Collections/HelperFunctionsTest.php @@ -0,0 +1,17 @@ +assertSame(1, value(function () { + return 1; + })); + $this->assertSame(1, value(1)); + $this->assertSame(1, value(1, 2)); + } +} diff --git a/tests/Support/FluentTest.php b/tests/Support/FluentTest.php new file mode 100644 index 0000000..e751861 --- /dev/null +++ b/tests/Support/FluentTest.php @@ -0,0 +1,84 @@ + 'bar']); + $this->assertSame(['foo' => 'bar'], $fluent->toArray()); + } + + public function testJsonSerialize() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame(['foo' => 'bar'], $fluent->jsonSerialize()); + } + + public function testToJson() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('{"foo":"bar"}', $fluent->toJson()); + } + + public function testGetAttributes() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame(['foo' => 'bar'], $fluent->getAttributes()); + } + + public function testGet() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('bar', $fluent->get('foo')); + } + + public function testGetWithDefault() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('bar', $fluent->get('foo', 'default')); + $this->assertSame('default', $fluent->get('bar', 'default')); + } + + public function testGetWithClosure() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('bar', $fluent->get('foo', function () { + return 'default'; + })); + } + + public function testGetWithClosureAndDefault() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('default', $fluent->get('bar', function () { + return 'default'; + })); + } + + public function testGetWithCallable() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('bar', $fluent->get('foo', function () { + return 'default'; + })); + } + + public function testGetWithCallableAndDefault() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('default', $fluent->get('bar', function () { + return 'default'; + })); + } + + public function testGetViaMagicCall() + { + $fluent = new Fluent(['foo' => 'bar']); + $this->assertSame('bar', $fluent->foo); + } +} \ No newline at end of file