diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f87cd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/vendor +composer.phar +composer.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f60bbe0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - hhvm + +before_script: + - travis_retry composer self-update + - travis_retry composer install --prefer-source --no-interaction --dev + +script: phpunit diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1868b3 --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +## Attributable trait + +> **Note:** Original idea by Taylor Otwell in [Laravel Framework](https://github.com/laravel/framework). + +The trait is used to provide fast and elegant way to work with objects. + +## Installation + +Install the package with composer. +```` +composer require rkgrep/attributable +```` + +Apply the trait to any class you need. + +````php +class Foo { + + use rkgrep\Attributable; + +} +```` + +## Usage + +Assign internal variables via property or method call + +````php +$foo->var1 = 1; +$foo->var2(2); +```` + +Access variables via property + +````php +echo $foo->var1; +echo $foo->var2; +```` + +Provide fallback value via `get` method + +````php +$foo->get('var4', 'fallback'); +$foo->get('var5', function() { return 'closure result'; }); +```` + +Get all internal variables via `getAttributes` method + +````php +$all = $foo->getAttributes(); +```` + +Method call without arguments assigns `true` + +````php +$foo->viewable(); +true == $foo->viewable; +```` + +Chain methods for fast assignment + +````php +$user->first_name('John')->last_name('Doe')->admin(); +```` + +## Interfaces + +Any class with `Attributable` trait applied implements `ArrayAccess` and `JsonSerializable`. +If you use *illuminate/support* package you can also apply `Arrayable` and `Jsonable` interfaces. + +````php +class Bar implements ArrayAccess, JsonSerializable, Arrayable, Jsonable { + use rkgrep\Attributable; +} + +$bar = new Bar(); +$bar->value('test'); + +$arrayValue = $bar['value']; +$bar['value'] = 'new'; +$json = json_encode($bar); // returns '{"value": "new"}' + +$array = $bar->toArray(); +$json = $bar->toJson(); +```` + +## License + +**Attributable** package is open-sourced package licensed under the [MIT license](http://opensource.org/licenses/MIT). \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..9b3e303 --- /dev/null +++ b/composer.json @@ -0,0 +1,20 @@ +{ + "name": "rkgrep/attributable", + "description": "Fast an elegant way to make dynamic objects", + "license": "MIT", + "authors": [ + { + "name": "Roman Kinyakin", + "email": "1@grep.su" + } + ], + "require": { + "php": ">=5.4.0" + }, + "autoload": { + "psr-4": { + "rkgrep\\": "src/" + } + }, + "minimum-stability": "stable" +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..3347b75 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,18 @@ + + + + + ./tests/ + + + diff --git a/src/Attributable.php b/src/Attributable.php new file mode 100644 index 0000000..54add41 --- /dev/null +++ b/src/Attributable.php @@ -0,0 +1,192 @@ +attributes)) + { + return $this->attributes[$key]; + } + + return $default instanceof Closure ? $default() : $default; + } + + /** + * Get the attributes from the container. + * + * @return array + */ + public function getAttributes() + { + return $this->attributes; + } + + /** + * Convert the Attributable instance to an array. + * + * @return array + */ + public function toArray() + { + return $this->attributes; + } + + /** + * Determine if the given offset exists. + * + * @param string $offset + * + * @return bool + */ + public function offsetExists($offset) + { + return isset($this->{$offset}); + } + + /** + * Get the value for a given offset. + * + * @param string $offset + * + * @return mixed + */ + public function offsetGet($offset) + { + return $this->{$offset}; + } + + /** + * Set the value at the given offset. + * + * @param string $offset + * @param mixed $value + * + * @return void + */ + public function offsetSet($offset, $value) + { + $this->{$offset} = $value; + } + + /** + * Unset the value at the given offset. + * + * @param string $offset + * + * @return void + */ + public function offsetUnset($offset) + { + unset($this->{$offset}); + } + + /** + * Dynamically retrieve the value of an attribute. + * + * @param string $key + * + * @return mixed + */ + public function __get($key) + { + return $this->get($key); + } + + /** + * Dynamically set the value of an attribute. + * + * @param string $key + * @param mixed $value + * + * @return void + */ + public function __set($key, $value) + { + $this->attributes[$key] = $value; + } + + /** + * Dynamically check if an attribute is set. + * + * @param string $key + * + * @return void + */ + public function __isset($key) + { + return isset($this->attributes[$key]); + } + + /** + * Dynamically unset an attribute. + * + * @param string $key + * + * @return void + */ + public function __unset($key) + { + unset($this->attributes[$key]); + } + + + /** + * Convert the object into something JSON serializable. + * + * @return array + */ + public function jsonSerialize() + { + return $this->toArray(); + } + + /** + * Convert the Attributable instance to JSON. + * + * @param int $options + * + * @return string + */ + public function toJson($options = 0) + { + return json_encode($this->toArray(), $options); + } + + /** + * Handle dynamic calls to the container to set attributes. + * + * @param string $method + * @param array $parameters + * + * @return $this + */ + public function __call($method, $parameters) + { + $this->attributes[$method] = count($parameters) > 0 ? $parameters[0] : true; + + return $this; + } +} diff --git a/tests/AttributableTest.php b/tests/AttributableTest.php new file mode 100644 index 0000000..0d1603d --- /dev/null +++ b/tests/AttributableTest.php @@ -0,0 +1,43 @@ +assertEmpty($mock->toArray()); + } + + public function testSetAndGet() + { + $mock = new Mock(); + + $mock->foo = 'bar'; + + $this->assertEquals('bar', $mock->get('foo')); + $this->assertEquals('bar', $mock->foo); + $this->assertNull($mock->get('baz')); + } + + public function testIsset() + { + $mock = new Mock(); + + $mock->foo = 'bar'; + $this->assertTrue(isset($mock->foo)); + $this->assertFalse(isset($mock->baz)); + } + + public function testCall() + { + $mock = new Mock(); + + $mock->foo(); + $this->assertTrue($mock->get('foo')); + + $mock->foo('bar'); + $this->assertEquals('bar', $mock->get('foo')); + } +} diff --git a/tests/stubs/Mock.php b/tests/stubs/Mock.php new file mode 100644 index 0000000..0e9935a --- /dev/null +++ b/tests/stubs/Mock.php @@ -0,0 +1,7 @@ +