From 03b4898476e6913e7ecd650e7c04b456bc77aedf Mon Sep 17 00:00:00 2001 From: Oliver Mack Date: Thu, 3 May 2018 17:39:43 +0200 Subject: [PATCH] Implement `ArrayAccess` and make types `JsonSerializable` (#48) * Implementing `ArrayAccess` in `BaseType` template * Implementing `JsonSerializable` in `BaseType` template * Moved `jsonSerialize()` * Ran generator to generate new `BaseType` * Moved `ArrayAccess` methods in template to be closer to the other accessors * Added tests for `ArrayAccess` implementation * Added tests for `JsonSerializable` implementation * Added some documentation --- README.md | 18 +++++++ generator/templates/static/BaseType.php | 27 +++++++++- src/BaseType.php | 27 +++++++++- tests/BaseTypeTest.php | 67 +++++++++++++++++++++++++ 4 files changed, 137 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 62eddd6be..eed457288 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,18 @@ $localBusiness->name('Spatie'); > *All types also accept arrays of the expected data type, for example `sameAs` accepts a string or an array of strings.* +All types also implement the SPL's `ArrayAccess` for accessing the properties via array notation: + +```php +$anotherLocalBusiness = new LocalBusiness(); +var_dump(isset($anotherLocalBusiness['name'])); // => false +$anotherLocalBusiness['name'] = 'Spatie'; +var_dump(isset($anotherLocalBusiness['name'])); // => true +var_dump($anotherLocalBusiness['name']); // => 'Spatie' +unset($anotherLocalBusiness['name']); +var_dump(isset($anotherLocalBusiness['name'])); // => false +``` + Types can be converted to an array or rendered to a script. ```php @@ -68,6 +80,12 @@ $localBusiness->toScript(); echo $localBusiness; // Same output as `toScript()` ``` +Additionally, all types can be converted to a plain JSON string by just calling `json_encode()` with your object: + +```php +echo json_encode($localBusiness); +``` + There's no full API documentation for types and properties. You can refer to [the source](https://github.com/spatie/schema-org/tree/master/src) or to [the schema.org website](http://schema.org). If you don't want to break the chain of a large schema object, you can use the `if` method to conditionally modify the schema. diff --git a/generator/templates/static/BaseType.php b/generator/templates/static/BaseType.php index 1b6581dc1..720b6a580 100644 --- a/generator/templates/static/BaseType.php +++ b/generator/templates/static/BaseType.php @@ -7,7 +7,7 @@ use DateTimeInterface; use Spatie\SchemaOrg\Exceptions\InvalidProperty; -abstract class BaseType implements Type +abstract class BaseType implements Type, \ArrayAccess, \JsonSerializable { /** @var array */ protected $properties = []; @@ -57,6 +57,26 @@ public function getProperties(): array return $this->properties; } + public function offsetExists($offset) + { + return array_key_exists($offset, $this->properties); + } + + public function offsetGet($offset) + { + return $this->getProperty($offset); + } + + public function offsetSet($offset, $value) + { + $this->setProperty($offset, $value); + } + + public function offsetUnset($offset) + { + unset($this->properties[$offset]); + } + public function toArray(): array { $properties = $this->serializeProperty($this->getProperties()); @@ -94,6 +114,11 @@ public function toScript(): string return ''; } + public function jsonSerialize() + { + return $this->toArray(); + } + public function __call(string $method, array $arguments) { return $this->setProperty($method, $arguments[0] ?? ''); diff --git a/src/BaseType.php b/src/BaseType.php index 1b6581dc1..720b6a580 100644 --- a/src/BaseType.php +++ b/src/BaseType.php @@ -7,7 +7,7 @@ use DateTimeInterface; use Spatie\SchemaOrg\Exceptions\InvalidProperty; -abstract class BaseType implements Type +abstract class BaseType implements Type, \ArrayAccess, \JsonSerializable { /** @var array */ protected $properties = []; @@ -57,6 +57,26 @@ public function getProperties(): array return $this->properties; } + public function offsetExists($offset) + { + return array_key_exists($offset, $this->properties); + } + + public function offsetGet($offset) + { + return $this->getProperty($offset); + } + + public function offsetSet($offset, $value) + { + $this->setProperty($offset, $value); + } + + public function offsetUnset($offset) + { + unset($this->properties[$offset]); + } + public function toArray(): array { $properties = $this->serializeProperty($this->getProperties()); @@ -94,6 +114,11 @@ public function toScript(): string return ''; } + public function jsonSerialize() + { + return $this->toArray(); + } + public function __call(string $method, array $arguments) { return $this->setProperty($method, $arguments[0] ?? ''); diff --git a/tests/BaseTypeTest.php b/tests/BaseTypeTest.php index fb9e9abe8..5b238b088 100644 --- a/tests/BaseTypeTest.php +++ b/tests/BaseTypeTest.php @@ -186,6 +186,73 @@ public function it_can_set_a_property_via_a_magic_call_method() $this->assertEquals(['foo' => 'bar'], $type->getProperties()); } + + /** @test */ + public function it_can_use_array_access_to_set_a_property() + { + $type = new DummyType(); + + $type['foo'] = 'bar'; + + $this->assertEquals(['foo' => 'bar'], $type->getProperties()); + } + + /** @test */ + public function it_can_use_array_access_to_unset_a_property() + { + $type = new DummyType(); + + $type->setProperty('foo', 'bar'); + $type->setProperty('bar', 'baz'); + unset($type['foo']); + + $this->assertEquals(['bar' => 'baz'], $type->getProperties()); + } + + /** @test */ + public function it_can_use_array_access_to_determine_if_a_property_exists() + { + $type = new DummyType(); + + $type->setProperty('foo', 'bar'); + + $this->assertTrue(isset($type['foo'])); + $this->assertFalse(isset($type['bar'])); + } + + /** @test */ + public function it_can_use_array_access_to_get_a_property() + { + $type = new DummyType(); + + $type->setProperty('foo', 'bar'); + + $this->assertEquals('bar', $type['foo']); + } + + /** @test */ + public function it_can_be_json_serialized() + { + $type = new DummyType(); + $child = new DummyType(); + $child->setProperty('bar', 'baz'); + + $type->setProperty('foo', 'bar'); + $type->setProperty('child', $child); + + $expected = [ + '@context' => 'http://schema.org', + '@type' => 'DummyType', + 'foo' => 'bar', + 'child' => [ + '@type' => 'DummyType', + 'bar' => 'baz', + ], + ]; + + $this->assertEquals($expected, $type->jsonSerialize(), 'Return value of `jsonSerialize` is wrong'); + $this->assertEquals(json_encode($expected), json_encode($type), 'JSON representation is wrong'); + } } class DummyType extends BaseType