Update for new tobscure/json-api relationship handling

This commit is contained in:
Toby Zerner 2015-10-30 11:03:38 +10:30
parent e1315d27a4
commit 95e3ff8fa8
13 changed files with 165 additions and 219 deletions

View File

@ -1,58 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* 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;
}
}

View File

@ -1,35 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* 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;
}
}

View File

@ -1,35 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* 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;
}
}

View File

@ -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;
}
/**

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -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');
}
/**

View File

@ -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];
});
}

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -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;
}
/**