Skip to content

Commit

Permalink
Implement ArrayAccess and make types JsonSerializable (#48)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
olivermack authored and sebastiandedeyne committed May 3, 2018
1 parent c81a5cd commit 03b4898
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 2 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
27 changes: 26 additions & 1 deletion generator/templates/static/BaseType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -94,6 +114,11 @@ public function toScript(): string
return '<script type="application/ld+json">'.json_encode($this->toArray(), JSON_UNESCAPED_UNICODE).'</script>';
}

public function jsonSerialize()
{
return $this->toArray();
}

public function __call(string $method, array $arguments)
{
return $this->setProperty($method, $arguments[0] ?? '');
Expand Down
27 changes: 26 additions & 1 deletion src/BaseType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -94,6 +114,11 @@ public function toScript(): string
return '<script type="application/ld+json">'.json_encode($this->toArray(), JSON_UNESCAPED_UNICODE).'</script>';
}

public function jsonSerialize()
{
return $this->toArray();
}

public function __call(string $method, array $arguments)
{
return $this->setProperty($method, $arguments[0] ?? '');
Expand Down
67 changes: 67 additions & 0 deletions tests/BaseTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 03b4898

Please sign in to comment.