From 95e3ff8fa82b7138ab3d3701cc33d4e339135d27 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Fri, 30 Oct 2015 11:03:38 +1030 Subject: [PATCH] Update for new tobscure/json-api relationship handling --- src/Api/Relationship/BuilderTrait.php | 58 -------- src/Api/Relationship/HasManyBuilder.php | 35 ----- src/Api/Relationship/HasOneBuilder.php | 35 ----- src/Api/Serializer/AbstractSerializer.php | 129 +++++++++++++----- .../Serializer/DiscussionBasicSerializer.php | 36 ++--- src/Api/Serializer/DiscussionSerializer.php | 6 +- src/Api/Serializer/ForumSerializer.php | 6 +- src/Api/Serializer/GroupSerializer.php | 6 +- src/Api/Serializer/NotificationSerializer.php | 18 +-- src/Api/Serializer/PostBasicSerializer.php | 12 +- src/Api/Serializer/PostSerializer.php | 24 ++-- src/Api/Serializer/UserBasicSerializer.php | 6 +- src/Event/GetApiRelationship.php | 13 +- 13 files changed, 165 insertions(+), 219 deletions(-) delete mode 100644 src/Api/Relationship/BuilderTrait.php delete mode 100644 src/Api/Relationship/HasManyBuilder.php delete mode 100644 src/Api/Relationship/HasOneBuilder.php diff --git a/src/Api/Relationship/BuilderTrait.php b/src/Api/Relationship/BuilderTrait.php deleted file mode 100644 index adf5ef6de..000000000 --- a/src/Api/Relationship/BuilderTrait.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Api\Relationship; - -use Flarum\Core\User; -use Illuminate\Contracts\Container\Container; - -trait BuilderTrait -{ - /** - * @var Container - */ - protected $container; - - /** - * @var string|\Closure - */ - protected $relation; - - /** - * @var User - */ - protected $actor; - - /** - * {@inheritdoc} - */ - protected function getRelationshipData($model) - { - $relation = $this->relation; - - if (is_object($model)) { - return $model->$relation; - } elseif (is_array($model)) { - return $model[$relation]; - } - } - - /** - * {@inheritdoc} - */ - protected function resolveSerializerClass($class) - { - $serializer = $this->container->make($class); - - $serializer->setActor($this->actor); - - return $serializer; - } -} diff --git a/src/Api/Relationship/HasManyBuilder.php b/src/Api/Relationship/HasManyBuilder.php deleted file mode 100644 index d7af2e8cc..000000000 --- a/src/Api/Relationship/HasManyBuilder.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Api\Relationship; - -use Flarum\Core\User; -use Illuminate\Contracts\Container\Container; -use Tobscure\JsonApi\Relationship\AbstractHasManyBuilder; - -class HasManyBuilder extends AbstractHasManyBuilder -{ - use BuilderTrait; - - /** - * @param string|\Closure|\Tobscure\JsonApi\SerializerInterface $serializer - * @param string|\Closure $relation - * @param User $actor - * @param Container $container - */ - public function __construct($serializer, $relation, User $actor, Container $container) - { - parent::__construct($serializer); - - $this->relation = $relation; - $this->container = $container; - $this->actor = $actor; - } -} diff --git a/src/Api/Relationship/HasOneBuilder.php b/src/Api/Relationship/HasOneBuilder.php deleted file mode 100644 index 72e72329c..000000000 --- a/src/Api/Relationship/HasOneBuilder.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Api\Relationship; - -use Flarum\Core\User; -use Illuminate\Contracts\Container\Container; -use Tobscure\JsonApi\Relationship\AbstractHasOneBuilder; - -class HasOneBuilder extends AbstractHasOneBuilder -{ - use BuilderTrait; - - /** - * @param string|\Closure|\Tobscure\JsonApi\SerializerInterface $serializer - * @param string|\Closure $relation - * @param User $actor - * @param Container $container - */ - public function __construct($serializer, $relation, User $actor, Container $container) - { - parent::__construct($serializer); - - $this->relation = $relation; - $this->container = $container; - $this->actor = $actor; - } -} diff --git a/src/Api/Serializer/AbstractSerializer.php b/src/Api/Serializer/AbstractSerializer.php index 333c2ffce..5628b920f 100644 --- a/src/Api/Serializer/AbstractSerializer.php +++ b/src/Api/Serializer/AbstractSerializer.php @@ -17,11 +17,16 @@ use Flarum\Event\PrepareApiAttributes; use Flarum\Event\GetApiRelationship; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Events\Dispatcher; +use InvalidArgumentException; use LogicException; use Tobscure\JsonApi\AbstractSerializer as BaseAbstractSerializer; use Flarum\Api\Relationship\HasOneBuilder; use Flarum\Api\Relationship\HasManyBuilder; +use Tobscure\JsonApi\Collection; +use Tobscure\JsonApi\Relationship; use Tobscure\JsonApi\Relationship\BuilderInterface; +use Tobscure\JsonApi\Resource; +use Tobscure\JsonApi\SerializerInterface; abstract class AbstractSerializer extends BaseAbstractSerializer { @@ -96,77 +101,139 @@ abstract class AbstractSerializer extends BaseAbstractSerializer /** * {@inheritdoc} */ - public function getRelationshipBuilder($name) + public function getRelationship($model, $name) { - if ($relationship = $this->getCustomRelationship($name)) { + if ($relationship = $this->getCustomRelationship($model, $name)) { return $relationship; } - return parent::getRelationshipBuilder($name); + return parent::getRelationship($model, $name); } /** * Get a custom relationship. * + * @param mixed $model * @param string $name - * @return BuilderInterface|null + * @return Relationship|null */ - protected function getCustomRelationship($name) + protected function getCustomRelationship($model, $name) { - $builder = static::$dispatcher->until( - new GetApiRelationship($this, $name) + $relationship = static::$dispatcher->until( + new GetApiRelationship($this, $name, $model) ); - if ($builder && ! ($builder instanceof BuilderInterface)) { + if ($relationship && ! ($relationship instanceof Relationship)) { throw new LogicException('GetApiRelationship handler must return an instance of ' - . BuilderInterface::class); + . Relationship::class); } - return $builder; + return $relationship; } /** * Get a relationship builder for a has-one relationship. * + * @param mixed $model * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer * @param string|Closure|null $relation - * @return HasOneBuilder + * @return Relationship */ - public function hasOne($serializer, $relation = null) + public function hasOne($model, $serializer, $relation = null) { - if (is_null($relation)) { - $relation = $this->getRelationCaller(); - } - - return new HasOneBuilder($serializer, $relation, $this->actor, static::$container); + return $this->buildRelationship($model, $serializer, $relation); } /** * Get a relationship builder for a has-many relationship. * + * @param mixed $model * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer - * @param string|Closure|null $relation - * @return HasManyBuilder + * @param string|null $relation + * @return Relationship */ - public function hasMany($serializer, $relation = null) + public function hasMany($model, $serializer, $relation = null) { - if (is_null($relation)) { - $relation = $this->getRelationCaller(); - } - - return new HasManyBuilder($serializer, $relation, $this->actor, static::$container); + return $this->buildRelationship($model, $serializer, $relation, true); } /** - * Guess the name of a relation from the stack trace. - * - * @return string + * @param mixed $model + * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer + * @param string|null $relation + * @param bool $many + * @return Relationship */ - protected function getRelationCaller() + protected function buildRelationship($model, $serializer, $relation = null, $many = false) { - list(, , $caller) = debug_backtrace(false, 3); + if (is_null($relation)) { + list(, , $caller) = debug_backtrace(false, 3); - return $caller['function']; + $relation = $caller['function']; + } + + $data = $this->getRelationshipData($model, $relation); + + if ($data) { + $serializer = $this->resolveSerializer($serializer, $model, $data); + + $type = $many ? Collection::class : Resource::class; + + $element = new $type($data, $serializer); + + return new Relationship($element); + } + } + + /** + * @param mixed $model + * @return mixed + */ + protected function getRelationshipData($model, $relation) + { + if (is_object($model)) { + return $model->$relation; + } elseif (is_array($model)) { + return $model[$relation]; + } + } + + /** + * @param mixed $serializer + * @param mixed $model + * @param mixed $data + * @return SerializerInterface + * @throws InvalidArgumentException + */ + protected function resolveSerializer($serializer, $model, $data) + { + if ($serializer instanceof Closure) { + $serializer = call_user_func($serializer, $model, $data); + } + + if (is_string($serializer)) { + $serializer = $this->resolveSerializerClass($serializer); + } + + if (! ($serializer instanceof SerializerInterface)) { + throw new InvalidArgumentException('Serializer must be an instance of ' + .SerializerInterface::class); + } + + return $serializer; + } + + /** + * @param string $class + * @return object + */ + protected function resolveSerializerClass($class) + { + $serializer = static::$container->make($class); + + $serializer->setActor($this->actor); + + return $serializer; } /** diff --git a/src/Api/Serializer/DiscussionBasicSerializer.php b/src/Api/Serializer/DiscussionBasicSerializer.php index ddd2721e9..52ca0e191 100644 --- a/src/Api/Serializer/DiscussionBasicSerializer.php +++ b/src/Api/Serializer/DiscussionBasicSerializer.php @@ -39,50 +39,50 @@ class DiscussionBasicSerializer extends AbstractSerializer } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function startUser() + protected function startUser($discussion) { - return $this->hasOne('Flarum\Api\Serializer\UserBasicSerializer'); + return $this->hasOne($discussion, 'Flarum\Api\Serializer\UserBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function startPost() + protected function startPost($discussion) { - return $this->hasOne('Flarum\Api\Serializer\PostBasicSerializer'); + return $this->hasOne($discussion, 'Flarum\Api\Serializer\PostBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function lastUser() + protected function lastUser($discussion) { - return $this->hasOne('Flarum\Api\Serializer\UserBasicSerializer'); + return $this->hasOne($discussion, 'Flarum\Api\Serializer\UserBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function lastPost() + protected function lastPost($discussion) { - return $this->hasOne('Flarum\Api\Serializer\PostBasicSerializer'); + return $this->hasOne($discussion, 'Flarum\Api\Serializer\PostBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasManyBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function posts() + protected function posts($discussion) { - return $this->hasMany('Flarum\Api\Serializer\PostSerializer'); + return $this->hasMany($discussion, 'Flarum\Api\Serializer\PostSerializer'); } /** - * @return \Flarum\Api\Relationship\HasManyBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function relevantPosts() + protected function relevantPosts($discussion) { - return $this->hasMany('Flarum\Api\Serializer\PostBasicSerializer'); + return $this->hasMany($discussion, 'Flarum\Api\Serializer\PostBasicSerializer'); } } diff --git a/src/Api/Serializer/DiscussionSerializer.php b/src/Api/Serializer/DiscussionSerializer.php index 092a14b3a..b12f9df3d 100644 --- a/src/Api/Serializer/DiscussionSerializer.php +++ b/src/Api/Serializer/DiscussionSerializer.php @@ -65,10 +65,10 @@ class DiscussionSerializer extends DiscussionBasicSerializer } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function hideUser() + protected function hideUser($discussion) { - return $this->hasOne('Flarum\Api\Serializer\UserSerializer'); + return $this->hasOne($discussion, 'Flarum\Api\Serializer\UserSerializer'); } } diff --git a/src/Api/Serializer/ForumSerializer.php b/src/Api/Serializer/ForumSerializer.php index 933317e9e..4d14f6691 100644 --- a/src/Api/Serializer/ForumSerializer.php +++ b/src/Api/Serializer/ForumSerializer.php @@ -88,10 +88,10 @@ class ForumSerializer extends AbstractSerializer } /** - * @return \Flarum\Api\Relationship\HasManyBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function groups() + protected function groups($model) { - return $this->hasMany('Flarum\Api\Serializer\GroupSerializer'); + return $this->hasMany($model, 'Flarum\Api\Serializer\GroupSerializer'); } } diff --git a/src/Api/Serializer/GroupSerializer.php b/src/Api/Serializer/GroupSerializer.php index 99e0f0434..00f8b16fa 100644 --- a/src/Api/Serializer/GroupSerializer.php +++ b/src/Api/Serializer/GroupSerializer.php @@ -56,11 +56,11 @@ class GroupSerializer extends AbstractSerializer } /** - * @return \Flarum\Api\Relationship\HasManyBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function permissions() + protected function permissions($group) { - return $this->hasMany('Flarum\Api\Serializers\PermissionSerializer'); + return $this->hasMany($group, 'Flarum\Api\Serializers\PermissionSerializer'); } /** diff --git a/src/Api/Serializer/NotificationSerializer.php b/src/Api/Serializer/NotificationSerializer.php index dcdd78370..30874aa33 100644 --- a/src/Api/Serializer/NotificationSerializer.php +++ b/src/Api/Serializer/NotificationSerializer.php @@ -51,27 +51,27 @@ class NotificationSerializer extends AbstractSerializer } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function user() + protected function user($notification) { - return $this->hasOne('Flarum\Api\Serializer\UserBasicSerializer'); + return $this->hasOne($notification, 'Flarum\Api\Serializer\UserBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function sender() + protected function sender($notification) { - return $this->hasOne('Flarum\Api\Serializer\UserBasicSerializer'); + return $this->hasOne($notification, 'Flarum\Api\Serializer\UserBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function subject() + protected function subject($notification) { - return $this->hasOne(function ($notification) { + return $this->hasOne($notification, function ($notification) { return static::$subjectSerializers[$notification->type]; }); } diff --git a/src/Api/Serializer/PostBasicSerializer.php b/src/Api/Serializer/PostBasicSerializer.php index c7abb3d82..4ee550615 100644 --- a/src/Api/Serializer/PostBasicSerializer.php +++ b/src/Api/Serializer/PostBasicSerializer.php @@ -51,18 +51,18 @@ class PostBasicSerializer extends AbstractSerializer } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function user() + protected function user($post) { - return $this->hasOne('Flarum\Api\Serializer\UserBasicSerializer'); + return $this->hasOne($post, 'Flarum\Api\Serializer\UserBasicSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function discussion() + protected function discussion($post) { - return $this->hasOne('Flarum\Api\Serializer\DiscussionBasicSerializer'); + return $this->hasOne($post, 'Flarum\Api\Serializer\DiscussionBasicSerializer'); } } diff --git a/src/Api/Serializer/PostSerializer.php b/src/Api/Serializer/PostSerializer.php index 9844fa256..43941f72c 100644 --- a/src/Api/Serializer/PostSerializer.php +++ b/src/Api/Serializer/PostSerializer.php @@ -69,34 +69,34 @@ class PostSerializer extends PostBasicSerializer } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function user() + protected function user($post) { - return $this->hasOne('Flarum\Api\Serializer\UserSerializer'); + return $this->hasOne($post, 'Flarum\Api\Serializer\UserSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function discussion() + protected function discussion($post) { - return $this->hasOne('Flarum\Api\Serializer\DiscussionSerializer'); + return $this->hasOne($post, 'Flarum\Api\Serializer\DiscussionSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function editUser() + protected function editUser($post) { - return $this->hasOne('Flarum\Api\Serializer\UserSerializer'); + return $this->hasOne($post, 'Flarum\Api\Serializer\UserSerializer'); } /** - * @return \Flarum\Api\Relationship\HasOneBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function hideUser() + protected function hideUser($post) { - return $this->hasOne('Flarum\Api\Serializer\UserSerializer'); + return $this->hasOne($post, 'Flarum\Api\Serializer\UserSerializer'); } } diff --git a/src/Api/Serializer/UserBasicSerializer.php b/src/Api/Serializer/UserBasicSerializer.php index 668e757c1..74bde6b81 100644 --- a/src/Api/Serializer/UserBasicSerializer.php +++ b/src/Api/Serializer/UserBasicSerializer.php @@ -40,10 +40,10 @@ class UserBasicSerializer extends AbstractSerializer } /** - * @return \Flarum\Api\Relationship\HasManyBuilder + * @return \Tobscure\JsonApi\Relationship */ - protected function groups() + protected function groups($user) { - return $this->hasMany('Flarum\Api\Serializer\GroupSerializer'); + return $this->hasMany($user, 'Flarum\Api\Serializer\GroupSerializer'); } } diff --git a/src/Event/GetApiRelationship.php b/src/Event/GetApiRelationship.php index 323cf0e63..562c332c1 100644 --- a/src/Event/GetApiRelationship.php +++ b/src/Event/GetApiRelationship.php @@ -16,8 +16,8 @@ use Flarum\Api\Serializer\AbstractSerializer; * Get an API serializer relationship. * * This event is fired when a relationship is to be included on an API document. - * If a handler wishes to control the given relationship, then it should return - * an instance of `Tobscure\JsonApi\Relationship\BuilderInterface`. + * If a handler wishes to fulfil the given relationship, then it should return + * an instance of `Tobscure\JsonApi\Relationship`. * * @see AbstractSerializer::hasOne() * @see AbstractSerializer::hasMany() @@ -35,14 +35,21 @@ class GetApiRelationship */ public $relationship; + /** + * @var mixed + */ + public $model; + /** * @param AbstractSerializer $serializer * @param string $relationship + * @param mixed $model */ - public function __construct(AbstractSerializer $serializer, $relationship) + public function __construct(AbstractSerializer $serializer, $relationship, $model) { $this->serializer = $serializer; $this->relationship = $relationship; + $this->model = $model; } /**