diff --git a/src/AbstractSerializerRegistry.php b/src/AbstractSerializerRegistry.php new file mode 100644 index 0000000..ddc05d2 --- /dev/null +++ b/src/AbstractSerializerRegistry.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\JsonApi; + +use RuntimeException; + +abstract class AbstractSerializerRegistry implements SerializerRegistryInterface +{ + /** + * @var array + */ + protected $serializers = []; + + /** + * Instantiate serializer from the serializable object. + * + * @param object $serializable + * @return \Tobscure\JsonApi\SerializerInterface + */ + public function getFromSerializable($serializable) + { + $class = get_class($serializable); + + if (! isset($this->serializers[$class])) { + throw new RuntimeException("Serializer with name `{$class}` is not exists"); + } + + return new $this->serializers[$class](); + } +} diff --git a/src/PolymorphicCollection.php b/src/PolymorphicCollection.php new file mode 100644 index 0000000..54b9b2c --- /dev/null +++ b/src/PolymorphicCollection.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\JsonApi; + +class PolymorphicCollection implements ElementInterface +{ + /** + * @var array + */ + protected $resources = []; + + /** + * Create a new collection instance. + * + * @param mixed $data + * @param \Tobscure\JsonApi\SerializerRegistryInterface $serializers + */ + public function __construct($data, SerializerRegistryInterface $serializers) + { + $this->resources = $this->buildResources($data, $serializers); + } + + /** + * Convert an array of raw data to Resource objects. + * + * @param mixed $data + * @param \Tobscure\JsonApi\SerializerRegistryInterface $serializers + * @return \Tobscure\JsonApi\Resource[] + */ + protected function buildResources($data, SerializerRegistryInterface $serializers) + { + $resources = []; + + foreach ($data as $resource) { + if (! ($resource instanceof Resource)) { + $resource = new Resource($resource, $serializers->getFromSerializable($resource)); + } + + $resources[] = $resource; + } + + return $resources; + } + + /** + * {@inheritdoc} + */ + public function getResources() + { + return $this->resources; + } + + /** + * Set the resources array. + * + * @param array $resources + * + * @return void + */ + public function setResources($resources) + { + $this->resources = $resources; + } + + /** + * Request a relationship to be included for all resources. + * + * @param string|array $relationships + * + * @return $this + */ + public function with($relationships) + { + foreach ($this->resources as $resource) { + $resource->with($relationships); + } + + return $this; + } + + /** + * Request a restricted set of fields. + * + * @param array|null $fields + * + * @return $this + */ + public function fields($fields) + { + foreach ($this->resources as $resource) { + $resource->fields($fields); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function toArray() + { + return array_map(function (Resource $resource) { + return $resource->toArray(); + }, $this->resources); + } + + /** + * {@inheritdoc} + */ + public function toIdentifier() + { + return array_map(function (Resource $resource) { + return $resource->toIdentifier(); + }, $this->resources); + } +} diff --git a/src/PolymorphicResource.php b/src/PolymorphicResource.php new file mode 100644 index 0000000..8c3128e --- /dev/null +++ b/src/PolymorphicResource.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\JsonApi; + +use Tobscure\JsonApi\Resource as JsonApiResource; + +class PolymorphicResource extends JsonApiResource +{ + /** + * @param mixed $data + * @param \Tobscure\JsonApi\SerializerRegistryInterface $serializers + */ + public function __construct($data, SerializerRegistryInterface $serializers) + { + parent::__construct($data, $serializers->getFromSerializable($data)); + } +} diff --git a/src/SerializerRegistryInterface.php b/src/SerializerRegistryInterface.php new file mode 100644 index 0000000..e77b1e2 --- /dev/null +++ b/src/SerializerRegistryInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\JsonApi; + +interface SerializerRegistryInterface +{ + /** + * Instantiate serializer from the serializable object. + * + * @param object $serializable + * @return \Tobscure\JsonApi\SerializerInterface + */ + public function getFromSerializable($serializable); +} diff --git a/tests/PolymorphicCollectionTest.php b/tests/PolymorphicCollectionTest.php new file mode 100644 index 0000000..c26ad4d --- /dev/null +++ b/tests/PolymorphicCollectionTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Element; + +use Tobscure\JsonApi\PolymorphicCollection; +use Tobscure\JsonApi\PolymorphicResource; +use Tobscure\Tests\JsonApi\AbstractTestCase; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Bike; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Car; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Garage; +use Tobscure\Tests\JsonApi\Stubs\Serializers\VehicleSerializerRegistry; + +class PolymorphicCollectionTest extends AbstractTestCase +{ + public function testToArrayReturnsArrayOfResources() + { + $car = new Car(1); + $bike = new Bike(2); + $garage = new Garage(4, [$car, $bike]); + $serializerRegistry = new VehicleSerializerRegistry(); + + $collection = new PolymorphicCollection($garage->vehicles, $serializerRegistry); + + $resource1 = new PolymorphicResource($car, $serializerRegistry); + $resource2 = new PolymorphicResource($bike, $serializerRegistry); + $this->assertSame([$resource1->toArray(), $resource2->toArray()], $collection->toArray()); + } + + public function testToArrayReturnsArrayOfPolymorphicResources() + { + $car = new Car(1); + $bike = new Bike(2); + $garage = new Garage(4, [$car, $bike]); + $serializerRegistry = new VehicleSerializerRegistry(); + + $collection = new PolymorphicCollection($garage->vehicles, $serializerRegistry); + + $resources = $collection->getResources(); + $this->assertSame('cars', $resources[0]->getType()); + $this->assertSame('bikes', $resources[1]->getType()); + } + + public function testToIdentifierReturnsArrayOfResourceIdentifiers() + { + $car = new Car(1); + $bike = new Bike(2); + $garage = new Garage(4, [$car, $bike]); + $serializerRegistry = new VehicleSerializerRegistry(); + + $collection = new PolymorphicCollection($garage->vehicles, $serializerRegistry); + + $resource1 = new PolymorphicResource($car, $serializerRegistry); + $resource2 = new PolymorphicResource($bike, $serializerRegistry); + $this->assertSame([$resource1->toIdentifier(), $resource2->toIdentifier()], $collection->toIdentifier()); + } +} diff --git a/tests/PolymorphicResourceTest.php b/tests/PolymorphicResourceTest.php new file mode 100644 index 0000000..d3f5737 --- /dev/null +++ b/tests/PolymorphicResourceTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Element; + +use Tobscure\JsonApi\PolymorphicResource; +use Tobscure\Tests\JsonApi\AbstractTestCase; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Bike; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Car; +use Tobscure\Tests\JsonApi\Stubs\Serializers\VehicleSerializerRegistry; + +class PolymorphicResourceTest extends AbstractTestCase +{ + public function testPolymorphicResourceType() + { + $car = new Car(123); + $bike = new Bike(234); + $serializerRegistry = new VehicleSerializerRegistry(); + + $resource1 = new PolymorphicResource($car, $serializerRegistry); + $resource2 = new PolymorphicResource($bike, $serializerRegistry); + + $this->assertSame('cars', $resource1->getType()); + $this->assertSame('bikes', $resource2->getType()); + } +} diff --git a/tests/Stubs/Serializables/Bike.php b/tests/Stubs/Serializables/Bike.php new file mode 100644 index 0000000..fd1a6f3 --- /dev/null +++ b/tests/Stubs/Serializables/Bike.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializables; + +class Bike +{ + public $id; + + public $name = 'Bike'; + + public function __construct($id) + { + $this->id = $id; + } +} diff --git a/tests/Stubs/Serializables/Car.php b/tests/Stubs/Serializables/Car.php new file mode 100644 index 0000000..e80b488 --- /dev/null +++ b/tests/Stubs/Serializables/Car.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializables; + +class Car +{ + public $id; + + public $name = 'Car'; + + public function __construct($id) + { + $this->id = $id; + } +} diff --git a/tests/Stubs/Serializables/Garage.php b/tests/Stubs/Serializables/Garage.php new file mode 100644 index 0000000..efa87f0 --- /dev/null +++ b/tests/Stubs/Serializables/Garage.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializables; + +class Garage +{ + public $id; + + public $vehicles = []; + + public function __construct($id, array $vehicles = []) + { + $this->id = $id; + $this->vehicles = $vehicles; + } +} diff --git a/tests/Stubs/Serializables/GarageSerializer.php b/tests/Stubs/Serializables/GarageSerializer.php new file mode 100644 index 0000000..553de8c --- /dev/null +++ b/tests/Stubs/Serializables/GarageSerializer.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializers; + +use Tobscure\JsonApi\AbstractSerializer; +use Tobscure\JsonApi\PolymorphicCollection; +use Tobscure\JsonApi\Relationship; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Garage; + +class GarageSerializer extends AbstractSerializer +{ + protected $type = 'garages'; + + public function getAttributes($garage, array $fields = null) + { + return []; + } + + public function vehicles(Garage $garage) + { + $element = new PolymorphicCollection( + $garage->vehicles, + new VehicleSerializerRegistry() + ); + + return new Relationship($element); + } +} diff --git a/tests/Stubs/Serializers/BikeSerializer.php b/tests/Stubs/Serializers/BikeSerializer.php new file mode 100644 index 0000000..ca7451a --- /dev/null +++ b/tests/Stubs/Serializers/BikeSerializer.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializers; + +use Tobscure\JsonApi\AbstractSerializer; + +class BikeSerializer extends AbstractSerializer +{ + protected $type = 'bikes'; + + public function getAttributes($bike, array $fields = null) + { + return [ + 'name' => $bike->name, + ]; + } +} diff --git a/tests/Stubs/Serializers/CarSerializer.php b/tests/Stubs/Serializers/CarSerializer.php new file mode 100644 index 0000000..005f72f --- /dev/null +++ b/tests/Stubs/Serializers/CarSerializer.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializers; + +use Tobscure\JsonApi\AbstractSerializer; + +class CarSerializer extends AbstractSerializer +{ + protected $type = 'cars'; + + public function getAttributes($car, array $fields = null) + { + return [ + 'name' => $car->name, + ]; + } +} diff --git a/tests/Stubs/Serializers/VehicleSerializerRegistry.php b/tests/Stubs/Serializers/VehicleSerializerRegistry.php new file mode 100644 index 0000000..23d9a65 --- /dev/null +++ b/tests/Stubs/Serializers/VehicleSerializerRegistry.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\JsonApi\Stubs\Serializers; + +use Tobscure\JsonApi\AbstractSerializerRegistry; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Bike; +use Tobscure\Tests\JsonApi\Stubs\Serializables\Car; + +class VehicleSerializerRegistry extends AbstractSerializerRegistry +{ + protected $serializers = [ + Car::class => CarSerializer::class, + Bike::class => BikeSerializer::class, + ]; +}