Skip to content

Commit

Permalink
Initial package
Browse files Browse the repository at this point in the history
  • Loading branch information
rkgrep committed May 8, 2015
1 parent e9739e2 commit e7b0966
Show file tree
Hide file tree
Showing 8 changed files with 385 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/vendor
composer.phar
composer.lock
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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).
20 changes: 20 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "rkgrep/attributable",
"description": "Fast an elegant way to make dynamic objects",
"license": "MIT",
"authors": [
{
"name": "Roman Kinyakin",
"email": "[email protected]"
}
],
"require": {
"php": ">=5.4.0"
},
"autoload": {
"psr-4": {
"rkgrep\\": "src/"
}
},
"minimum-stability": "stable"
}
18 changes: 18 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
192 changes: 192 additions & 0 deletions src/Attributable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<?php namespace rkgrep;

use Closure;

/**
* Class Attributable
*
* Original idea by Taylow Otwell
*/
trait Attributable {

/**
* All of the attributes set on the container.
*
* @var array
*/
protected $attributes = [];

/**
* Get an attribute from the container.
*
* @param string $key
* @param mixed $default
*
* @return mixed
*/
public function get($key, $default = null)
{
if (array_key_exists($key, $this->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;
}
}
43 changes: 43 additions & 0 deletions tests/AttributableTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

require __DIR__ . '/stubs/Mock.php';

class AttributableTest extends PHPUnit_Framework_TestCase {

public function testConstruct()
{
$mock = new Mock();
$this->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'));
}
}
7 changes: 7 additions & 0 deletions tests/stubs/Mock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

class Mock {

use rkgrep\Attributable;

}

0 comments on commit e7b0966

Please sign in to comment.