diff --git a/AbstractPropertyAccessor.php b/AbstractPropertyAccessor.php index d1b9b09..2fef975 100644 --- a/AbstractPropertyAccessor.php +++ b/AbstractPropertyAccessor.php @@ -16,64 +16,6 @@ abstract class AbstractPropertyAccessor implements \ArrayAccess, \IteratorAggregate { - /** - * ArrayAccess::offsetSet() - * - * @param mixed - * @param mixed - */ - public function offsetSet($name, $value) - { - if (!property_exists($this, $name)) { - throw new \InvalidArgumentException( - sprintf('The attribute "%s" does not exists.', $name) - ); - } - return $this->{$name} = $value; - } - - /** - * ArrayAccess::offsetGet() - * - * @param mixed - * @return mixed - */ - public function offsetGet($name) - { - if (!property_exists($this, $name)) { - throw new \InvalidArgumentException( - sprintf('The attribute "%s" does not exists.', $name) - ); - } - return $this->{$name}; - } - - /** - * ArrayAccess::offsetUnset() - * - * @param mixed - */ - public function offsetUnset($name) - { - if (!property_exists($this, $name)) { - throw new \InvalidArgumentException( - sprintf('The attribute "%s" does not exists.', $name) - ); - } - $this->{$name} = null; - } - - /** - * ArrayAccess::offsetExists() - * - * @param mixed - * @return bool - */ - public function offsetExists($name) - { - return (property_exists($this, $name) && !is_null($this->{$name})); - } - /** * 引数なしの場合は全てのプロパティを配列で返します。 * 引数ありの場合は全てのプロパティを引数の配列からセットして$thisを返します。 @@ -90,10 +32,20 @@ public function properties() $properties = func_get_arg(0); if (!is_array($properties) && !($properties instanceof \Traversable)) { throw new \InvalidArgumentException( - 'The properties is not Array and not Traversable.'); + sprintf('The properties is not an Array and not Traversable. type:%s', + is_object($properties) + ? get_class($properties) + : gettype($properties) + ) + ); } foreach ($properties as $name => $value) { - $this->offsetSet($name, $value); + if (!property_exists($this, $name)) { + throw new \InvalidArgumentException( + sprintf('The property "%s" does not exists.', $name) + ); + } + $this->{$name} = $value; } return $this; } @@ -101,38 +53,45 @@ public function properties() } /** - * IteratorAggregate::getIterator() + * ArrayAccess::offsetExists() * - * @return \ArrayIterator + * @param string プロパティ名 + * @return bool */ - public function getIterator() + public function offsetExists($name) { - return new \ArrayIterator($this->properties()); + return (property_exists($this, $name) && $this->{$name} !== null); } /** - * 配列に変換して返します。 + * __isset * - * @return array + * @param string プロパティ名 + * @return bool */ - public function toArray() + public function __isset($name) { - return $this->properties(); + return $this->offsetExists($name); } /** - * magic setter + * ArrayAccess::offsetGet() * * @param string プロパティ名 - * @param mixed プロパティ値 + * @return mixed */ - public function __set($name, $value) + public function offsetGet($name) { - $this->offsetSet($name, $value); + if (!property_exists($this, $name)) { + throw new \InvalidArgumentException( + sprintf('The property "%s" does not exists.', $name) + ); + } + return $this->{$name}; } /** - * magic getter + * __get * * @param string プロパティ名 */ @@ -142,18 +101,49 @@ public function __get($name) } /** - * magic isset + * ArrayAccess::offsetSet() + * + * @param mixed + * @param mixed + */ + public function offsetSet($name, $value) + { + if (!property_exists($this, $name)) { + throw new \InvalidArgumentException( + sprintf('The property "%s" does not exists.', $name) + ); + } + return $this->{$name} = $value; + } + + /** + * __set * * @param string プロパティ名 - * @return bool + * @param mixed プロパティ値 */ - public function __isset($name) + public function __set($name, $value) { - return $this->offsetExists($name); + $this->offsetSet($name, $value); + } + + /** + * ArrayAccess::offsetUnset() + * + * @param mixed + */ + public function offsetUnset($name) + { + if (!property_exists($this, $name)) { + throw new \InvalidArgumentException( + sprintf('The property "%s" does not exists.', $name) + ); + } + $this->{$name} = null; } /** - * magic unset + * __unset * * @param string プロパティ名 */ @@ -164,21 +154,44 @@ public function __unset($name) /** * __toString + * + * @return string */ public function __toString() { return var_export($this->properties(), true); } + /** + * IteratorAggregate::getIterator() + * + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->properties()); + } + /** * __sleep * - * @param void - * @return void + * @return array */ public function __sleep() { - return array_keys($this->properties(), true); + return array_keys($this->properties()); + } + + /** + * __clone + */ + public function __clone() + { + foreach ($this->properties() as $name => $value) { + if (is_object($value)) { + $this->{$name} = clone $value; + } + } } /** @@ -187,11 +200,21 @@ public function __sleep() * @param array * @return object */ - public static function __set_state($attributes) + public static function __set_state($properties) { $instance = new static(); - $instance->properties($attributes); + $instance->properties($properties); return $instance; } + /** + * 配列に変換して返します。 + * + * @return array + */ + public function toArray() + { + return $this->properties(); + } + } diff --git a/Tests/AbstractPropertyAccessorTest.php b/Tests/AbstractPropertyAccessorTest.php index 7c092d9..4bcbbd4 100644 --- a/Tests/AbstractPropertyAccessorTest.php +++ b/Tests/AbstractPropertyAccessorTest.php @@ -18,11 +18,14 @@ class AbstractPropertyAccessorTest extends \PHPUnit_Framework_TestCase { - public function testOffsetSet() + public function testOffsetExists() { $test = new Test(); - $test->offsetSet('string', 'Foo'); - $this->assertEquals('Foo', $test->string); + $test->string = 'Foo'; + $test->null = null; + $this->assertTrue($test->offsetExists('string')); + $this->assertFalse($test->offsetExists('null')); + $this->assertFalse($test->offsetExists('not_defined_property')); } public function testOffsetGet() @@ -35,19 +38,26 @@ public function testOffsetGet() /** * @expectedException \InvalidArgumentException */ - public function testRaiseExceptionWhenSetUndefinedProperty() + public function testOffsetGetRaiseInvalidArgumentException() { $test = new Test(); - $test->offsetSet('not_defined_attribute', 'Foo'); + $test->offsetGet('not_defined_property'); + } + + public function testOffsetSet() + { + $test = new Test(); + $test->offsetSet('string', 'Foo'); + $this->assertEquals('Foo', $test->string); } /** * @expectedException \InvalidArgumentException */ - public function testRaiseExceptionWhenGetUndefinedProperty() + public function testOffsetSetRaiseInvalidArgumentException() { $test = new Test(); - $test->offsetGet('not_defined_attribute'); + $test->offsetSet('not_defined_property', 'Foo'); } public function testOffsetUnset() @@ -59,25 +69,18 @@ public function testOffsetUnset() $this->assertEmpty($test->string); } - public function testOffsetExists() - { - $test = new Test(); - $test->string = 'Foo'; - $test->null = null; - $this->assertTrue($test->offsetExists('string')); - $this->assertFalse($test->offsetExists('null')); - $this->assertFalse($test->offsetExists('not_defined_attribute')); - } - public function testArrayAccess() { + $now = new \DateTime(); $test = new Test(); $test['string' ] = 'Foo'; $test['null' ] = null; $test['boolean'] = true; + $test['datetime'] = $now; $this->assertEquals('Foo', $test['string']); $this->assertNull($test['null']); $this->assertTrue($test['boolean']); + $this->assertSame($now, $test['datetime']); } public function testIssetArrayAccess() @@ -87,7 +90,7 @@ public function testIssetArrayAccess() $test->null = null; $this->assertTrue(isset($test['string'])); $this->assertFalse(isset($test['null'])); - $this->assertFalse(isset($test['not_defined_attribute'])); + $this->assertFalse(isset($test['not_defined_property'])); } public function testIssetPropertyAccess() @@ -97,7 +100,7 @@ public function testIssetPropertyAccess() $test->null = null; $this->assertTrue(isset($test->string)); $this->assertFalse(isset($test->null)); - $this->assertFalse(isset($test->not_defined_attribute)); + $this->assertFalse(isset($test->not_defined_property)); } public function testUnsetArrayAccess() @@ -138,10 +141,12 @@ public function testIsNullPropertyAccess() public function testTraversable() { + $now = new \DateTime(); $test = new Test(); $test->string = 'Foo'; $test->null = null; $test->boolean = true; + $test->datetime = $now; foreach ($test as $name => $value) { switch ($name) { case 'string': @@ -153,6 +158,9 @@ public function testTraversable() case 'boolean': $this->assertTrue($value); break; + case 'datetime': + $this->assertSame($now, $value); + break; } } } @@ -163,7 +171,10 @@ public function testSerialize() $test->string = 'Foo'; $test->null = null; $test->boolean = true; - $this->assertEquals($test, unserialize(serialize($test))); + $test->datetime = new \DateTime(); + $serialized = serialize($test); + $this->assertEquals($test, unserialize($serialized)); + $this->assertNotSame($test, unserialize($serialized)); } public function testVarExport() @@ -172,8 +183,22 @@ public function testVarExport() $test->string = 'Foo'; $test->null = null; $test->boolean = true; + $test->datetime = new \DateTime(); eval('$exported = ' . var_export($test, true) . ';'); $this->assertEquals($test, $exported); + $this->assertNotSame($test, $exported); + } + + public function testClone() + { + $test = new Test(); + $test->string = 'Foo'; + $test->null = null; + $test->boolean = true; + $test->datetime = new \DateTime(); + $cloned = clone $test; + $this->assertEquals($test->datetime, $cloned->datetime); + $this->assertNotSame($test->datetime, $cloned->datetime); } } @@ -183,4 +208,5 @@ class Test extends AbstractPropertyAccessor protected $string; protected $null; protected $boolean; + protected $datetime; } diff --git a/composer.json b/composer.json index 5ec8fdf..4b730f0 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "homepage": "https://github.com/k-holy/volcanus-database", "type": "library", "description": "database abstraction layer", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "authors": [ {