1
0
mirror of https://github.com/flarum/core.git synced 2025-10-18 10:16:09 +02:00

Convert the rest of the API to new action architecture

Also make some tweaks:
- Merge SerializeAction::$include and
SerializeAction::$includeAvailable into a keyed boolean array
- Set defaults for SerializeAction::$limit and $limitMax
- Rename SerializeAction::$sortAvailable to $sortFields
This commit is contained in:
Toby Zerner
2015-05-03 12:04:43 +09:30
parent 4cb9ed851d
commit 8f29679b46
37 changed files with 713 additions and 551 deletions

View File

@@ -2,46 +2,77 @@
use Flarum\Core\Repositories\UserRepositoryInterface;
use Flarum\Core\Repositories\ActivityRepositoryInterface;
use Flarum\Support\Actor;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Serializers\ActivitySerializer;
use Flarum\Api\Actions\SerializeCollectionAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class IndexAction extends BaseAction
class IndexAction extends SerializeCollectionAction
{
/**
* @var \Flarum\Core\Repositories\UserRepositoryInterface
*/
protected $users;
/**
* @var \Flarum\Core\Repositories\ActivityRepositoryInterface
*/
protected $activity;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\ActivitySerializer';
/**
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = [
'sender' => true,
'post' => true,
'post.user' => true,
'post.discussion' => true,
'post.discussion.startUser' => true,
'post.discussion.lastUser' => true
];
/**
* The relations that are linked by default.
*
* @var array
*/
public static $link = ['user'];
/**
* Instantiate the action.
*
* @param \Flarum\Core\Search\Discussions\UserSearcher $searcher
* @param \Flarum\Core\Repositories\UserRepositoryInterface $users
* @param \Flarum\Core\Repositories\ActivityRepositoryInterface $activity
*/
public function __construct(Actor $actor, UserRepositoryInterface $users, ActivityRepositoryInterface $activity)
public function __construct(UserRepositoryInterface $users, ActivityRepositoryInterface $activity)
{
$this->actor = $actor;
$this->users = $users;
$this->activity = $activity;
}
/**
* Show a user's activity feed.
* Get the activity results, ready to be serialized and assigned to the
* document response.
*
* @return \Illuminate\Http\Response
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Illuminate\Database\Eloquent\Collection
*/
protected function run(ApiParams $params)
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$start = $params->start();
$count = $params->count(20, 50);
$type = $params->get('type');
$id = $params->get('users');
$actor = $request->actor->getUser();
$user = $this->users->findOrFail($id, $this->actor->getUser());
$user = $this->users->findOrFail($request->get('users'), $actor);
$activity = $this->activity->findByUser($user->id, $this->actor->getUser(), $count, $start, $type);
// Finally, we can set up the activity serializer and use it to create
// a collection of activity results.
$serializer = new ActivitySerializer(['sender', 'post', 'post.discussion', 'post.user', 'post.discussion.startUser', 'post.discussion.lastUser'], ['user']);
$document = $this->document()->setData($serializer->collection($activity));
return $this->respondWithDocument($document);
return $this->activity->findByUser($user->id, $actor, $request->limit, $request->offset, $request->get('type'));
}
}

View File

@@ -32,14 +32,21 @@ class CreateAction extends BaseCreateAction
public static $serializer = 'Flarum\Api\Serializers\DiscussionSerializer';
/**
* The relations that are included by default.
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = ['posts', 'startUser', 'lastUser', 'startPost', 'lastPost'];
public static $include = [
'posts' => true,
'startUser' => true,
'lastUser' => true,
'startPost' => true,
'lastPost' => true
];
/**
* Initialize the action.
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
* @param \Flarum\Core\Models\Forum $forum

View File

@@ -16,7 +16,7 @@ class DeleteAction extends BaseDeleteAction
protected $bus;
/**
* Initialize the action.
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
@@ -26,9 +26,10 @@ class DeleteAction extends BaseDeleteAction
}
/**
* Delete a discussion according to input from the API request.
* Delete a discussion.
*
* @param \Flarum\Api\Request $request
* @param \Illuminate\Http\Response $response
* @return void
*/
protected function delete(Request $request, Response $response)

View File

@@ -23,46 +23,25 @@ class IndexAction extends SerializeCollectionAction
public static $serializer = 'Flarum\Api\Serializers\DiscussionSerializer';
/**
* The relations that are available to be included.
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $includeAvailable = ['startUser', 'lastUser', 'startPost', 'lastPost', 'relevantPosts'];
/**
* The relations that are included by default.
*
* @var array
*/
public static $include = ['startUser', 'lastUser'];
/**
* The maximum number of records that can be requested.
*
* @var integer
*/
public static $limitMax = 50;
/**
* The number of records included by default.
*
* @var integer
*/
public static $limit = 20;
public static $include = [
'startUser' => true,
'lastUser' => true,
'startPost' => false,
'lastPost' => false,
'relevantPosts' => false
];
/**
* The fields that are available to be sorted by.
*
* @var array
*/
public static $sortAvailable = ['lastTime', 'commentsCount', 'startTime'];
/**
* The default field to sort by.
*
* @var string
*/
public static $sort = ['lastTime' => 'desc'];
public static $sortFields = ['lastTime', 'commentsCount', 'startTime'];
/**
* Instantiate the action.

View File

@@ -12,16 +12,12 @@ class ShowAction extends SerializeResourceAction
use GetsPosts;
/**
* The discussion repository.
*
* @var DiscussionRepository
* @var \Flarum\Core\Repositories\DiscussionRepositoryInterface
*/
protected $discussions;
/**
* The post repository.
*
* @var PostRepository
* @var \Flarum\Core\Repositories\PostRepositoryInterface
*/
protected $posts;
@@ -33,23 +29,21 @@ class ShowAction extends SerializeResourceAction
public static $serializer = 'Flarum\Api\Serializers\DiscussionSerializer';
/**
* The relations that are available to be included.
*
* @var array
*/
public static $includeAvailable = [
'startUser', 'lastUser', 'startPost', 'lastPost', 'posts',
'posts.user', 'posts.user.groups', 'posts.editUser', 'posts.hideUser'
];
/**
* The relations that are included by default.
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = [
'startPost', 'lastPost', 'posts',
'posts.user', 'posts.user.groups', 'posts.editUser', 'posts.hideUser'
'startUser' => false,
'lastUser' => false,
'startPost' => true,
'lastPost' => true,
'posts' => true,
'posts.user' => true,
'posts.user.groups' => true,
'posts.editUser' => true,
'posts.hideUser' => true
];
/**
@@ -64,33 +58,20 @@ class ShowAction extends SerializeResourceAction
*
* @var array
*/
public static $sortAvailable = ['time'];
public static $sortFields = ['time'];
/**
* The default field to sort by.
* The default sort field and order to user.
*
* @var string
*/
public static $sort = ['time' => 'asc'];
/**
* The maximum number of records that can be requested.
*
* @var integer
*/
public static $limitMax = 50;
/**
* The number of records included by default.
*
* @var integer
*/
public static $limit = 20;
/**
* Instantiate the action.
*
* @param PostRepository $posts
* @param \Flarum\Core\Repositories\DiscussionRepositoryInterface $discussions
* @param \Flarum\Core\Repositories\PostRepositoryInterface $posts
*/
public function __construct(DiscussionRepositoryInterface $discussions, PostRepositoryInterface $posts)
{

View File

@@ -2,7 +2,6 @@
use Flarum\Core\Commands\EditDiscussionCommand;
use Flarum\Core\Commands\ReadDiscussionCommand;
use Flarum\Core\Exceptions\PermissionDeniedException;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\Actions\Posts\GetsPosts;
use Flarum\Api\JsonApiRequest;
@@ -12,8 +11,6 @@ use Illuminate\Contracts\Bus\Dispatcher;
class UpdateAction extends SerializeResourceAction
{
/**
* The command bus.
*
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected $bus;
@@ -30,10 +27,13 @@ class UpdateAction extends SerializeResourceAction
*
* @var array
*/
public static $include = ['addedPosts', 'addedPosts.user'];
public static $include = [
'addedPosts' => true,
'addedPosts.user' => true
];
/**
* Initialize the action.
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
@@ -46,7 +46,8 @@ class UpdateAction extends SerializeResourceAction
* Update a discussion according to input from the API request, and return
* it ready to be serialized and assigned to the JsonApi response.
*
* @param \Flarum\Api\Request $request
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Discussion
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
@@ -54,18 +55,12 @@ class UpdateAction extends SerializeResourceAction
$user = $request->actor->getUser();
$discussionId = $request->get('id');
// First, we will run the EditDiscussionCommand. This will update the
// discussion's direct properties; by default, this is just the title.
// As usual, however, we will fire an event to allow plugins to update
// additional properties.
if ($data = array_except($request->get('data'), ['readNumber'])) {
$discussion = $this->bus->dispatch(
new EditDiscussionCommand($discussionId, $user, $data)
);
}
// Next, if a read number was specified in the request, we will run the
// ReadDiscussionCommand.
if ($readNumber = $request->get('data.readNumber')) {
$state = $this->bus->dispatch(
new ReadDiscussionCommand($discussionId, $user, $readNumber)

View File

@@ -1,18 +1,29 @@
<?php namespace Flarum\Api\Actions\Groups;
use Flarum\Core\Models\Group;
use Flarum\Api\Actions\Base;
use Flarum\Api\Serializers\GroupSerializer;
use Flarum\Api\Actions\SerializeCollectionAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class Index extends Base
class IndexAction extends SerializeCollectionAction
{
protected function run()
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\GroupSerializer';
/**
* Get the groups, ready to be serialized and assigned to the document
* response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Illuminate\Database\Eloquent\Collection
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$groups = Group::get();
$serializer = new GroupSerializer;
$this->document->setData($serializer->collection($groups));
return $this->respondWithDocument();
return Group::get();
}
}

View File

@@ -1,50 +1,78 @@
<?php namespace Flarum\Api\Actions\Notifications;
use Flarum\Core\Repositories\NotificationRepositoryInterface;
use Flarum\Support\Actor;
use Flarum\Core\Exceptions\PermissionDeniedException;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Serializers\NotificationSerializer;
use Flarum\Api\Actions\SerializeCollectionAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class IndexAction extends BaseAction
class IndexAction extends SerializeCollectionAction
{
/**
* @var \Flarum\Core\Repositories\NotificationRepositoryInterface
*/
protected $notifications;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\NotificationSerializer';
/**
* The relations that are included by default.
*
* @var array
*/
public static $include = [
'sender' => true,
'subject' => true,
'subject.discussion' => true
];
/**
* The maximum number of records that can be requested.
*
* @var integer
*/
public static $limitMax = 50;
/**
* The number of records included by default.
*
* @var integer
*/
public static $limit = 10;
/**
* Instantiate the action.
*
* @param \Flarum\Core\Search\Discussions\UserSearcher $searcher
* @param \Flarum\Core\Repositories\NotificationRepositoryInterface $notifications
*/
public function __construct(Actor $actor, NotificationRepositoryInterface $notifications)
public function __construct(NotificationRepositoryInterface $notifications)
{
$this->actor = $actor;
$this->notifications = $notifications;
}
/**
* Show a user's notifications feed.
* Get the notification results, ready to be serialized and assigned to the
* document response.
*
* @return \Illuminate\Http\Response
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Illuminate\Database\Eloquent\Collection
*/
protected function run(ApiParams $params)
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$start = $params->start();
$count = $params->count(10, 50);
if (! $this->actor->isAuthenticated()) {
if (! $request->actor->isAuthenticated()) {
throw new PermissionDeniedException;
}
$user = $this->actor->getUser();
$notifications = $this->notifications->findByUser($user->id, $count, $start);
$user = $request->actor->getUser();
$user->markNotificationsAsRead()->save();
// Finally, we can set up the notification serializer and use it to create
// a collection of notification results.
$serializer = new NotificationSerializer(['sender', 'subject', 'subject.discussion']);
$document = $this->document()->setData($serializer->collection($notifications));
return $this->respondWithDocument($document);
return $this->notifications->findByUser($user->id, $request->limit, $request->offset);
}
}

View File

@@ -1,34 +1,47 @@
<?php namespace Flarum\Api\Actions\Notifications;
use Flarum\Core\Commands\ReadNotificationCommand;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Serializers\NotificationSerializer;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
use Illuminate\Contracts\Bus\Dispatcher;
class UpdateAction extends BaseAction
class UpdateAction extends SerializeResourceAction
{
/**
* Edit a discussion. Allows renaming the discussion, and updating its read
* state with regards to the current user.
*
* @return Response
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected function run(ApiParams $params)
protected $bus;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\NotificationSerializer';
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$notificationId = $params->get('id');
$user = $this->actor->getUser();
$this->bus = $bus;
}
// if ($params->get('notifications.isRead')) {
$command = new ReadNotificationCommand($notificationId, $user);
$notification = $this->dispatch($command, $params);
// }
// Presumably, the discussion was updated successfully. (One of the command
// handlers would have thrown an exception if not.) We set this
// discussion as our document's primary element.
$serializer = new NotificationSerializer;
$document = $this->document()->setData($serializer->resource($notification));
return $this->respondWithDocument($document);
/**
* Mark a notification as read, and return it ready to be serialized and
* assigned to the JsonApi response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Notification
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
return $this->bus->dispatch(
new ReadNotificationCommand($request->get('id'), $request->actor->getUser())
);
}
}

View File

@@ -2,46 +2,61 @@
use Flarum\Core\Commands\PostReplyCommand;
use Flarum\Core\Commands\ReadDiscussionCommand;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Serializers\PostSerializer;
use Flarum\Api\Actions\CreateAction as BaseCreateAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
use Illuminate\Contracts\Bus\Dispatcher;
class CreateAction extends BaseAction
class CreateAction extends BaseCreateAction
{
/**
* Reply to a discussion.
*
* @return Response
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected function run(ApiParams $params)
protected $bus;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\PostSerializer';
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$user = $this->actor->getUser();
$this->bus = $bus;
}
// We've received a request to post a reply. By default, the only
// required attributes of a post is the ID of the discussion to post in,
// the post content, and the author's user account. Let's set up a
// command with this information. We also fire an event to allow plugins
// to add data to the command.
$discussionId = $params->get('data.links.discussion.linkage.id');
$content = $params->get('data.content');
/**
* Reply to a discussion according to input from the API request.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Post
*/
protected function create(JsonApiRequest $request, JsonApiResponse $response)
{
$user = $request->actor->getUser();
$command = new PostReplyCommand($discussionId, $content, $user);
$post = $this->dispatch($command, $params);
$discussionId = $request->get('data.links.discussion.linkage.id');
$post = $this->bus->dispatch(
new PostReplyCommand($discussionId, $user, $request->get('data'))
);
// After replying, we assume that the user has seen all of the posts
// in the discussion; thus, we will mark the discussion as read if
// they are logged in.
if ($user->exists) {
$command = new ReadDiscussionCommand($discussionId, $user, $post->number);
$this->dispatch($command, $params);
$this->bus->dispatch(
new ReadDiscussionCommand($discussionId, $user, $post->number)
);
}
// Presumably, the post was created successfully. (The command handler
// would have thrown an exception if not.) We set this post as our
// document's primary element.
$serializer = new PostSerializer;
$document = $this->document()->setData($serializer->resource($post));
return $this->respondWithDocument($document, 201);
return $post;
}
}

View File

@@ -1,23 +1,39 @@
<?php namespace Flarum\Api\Actions\Posts;
use Flarum\Core\Commands\DeletePostCommand;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\DeleteAction as BaseDeleteAction;
use Flarum\Api\Request;
use Illuminate\Http\Response;
use Illuminate\Contracts\Bus\Dispatcher;
class DeleteAction extends BaseAction
class DeleteAction extends BaseDeleteAction
{
/**
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected $bus;
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$this->bus = $bus;
}
/**
* Delete a post.
*
* @return Response
* @param \Flarum\Api\Request $request
* @param \Illuminate\Http\Response $response
* @return void
*/
protected function run(ApiParams $params)
protected function delete(Request $request, Response $response)
{
$postId = $params->get('id');
$command = new DeletePostCommand($postId, $this->actor->getUser());
$this->dispatch($command, $params);
return $this->respondWithoutContent();
$this->bus->dispatch(
new DeletePostCommand($request->get('id'), $request->actor->getUser())
);
}
}

View File

@@ -1,6 +1,5 @@
<?php namespace Flarum\Api\Actions\Posts;
use Flarum\Core\Models\User;
use Flarum\Api\JsonApiRequest;
trait GetsPosts

View File

@@ -1,67 +1,75 @@
<?php namespace Flarum\Api\Actions\Posts;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Flarum\Core\Repositories\PostRepositoryInterface;
use Flarum\Support\Actor;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Serializers\PostSerializer;
use Flarum\Api\Actions\SerializeCollectionAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class IndexAction extends BaseAction
class IndexAction extends SerializeCollectionAction
{
use GetsPosts;
/**
* The post repository.
*
* @var Post
* @var \Flarum\Core\Repositories\PostRepositoryInterface
*/
protected $posts;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\PostSerializer';
/**
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = [
'user' => true,
'user.groups' => true,
'editUser' => true,
'hideUser' => true,
'discussion' => true
];
/**
* Instantiate the action.
*
* @param Post $posts
* @param \Flarum\Core\Repositories\PostRepositoryInterface $posts
*/
public function __construct(Actor $actor, PostRepositoryInterface $posts)
public function __construct(PostRepositoryInterface $posts)
{
$this->actor = $actor;
$this->posts = $posts;
}
/**
* Show posts from a discussion, or by providing an array of IDs.
*
* @return Response
*/
protected function run(ApiParams $params)
* Get the post results, ready to be serialized and assigned to the
* document response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Illuminate\Database\Eloquent\Collection
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$postIds = (array) $params->get('ids');
$include = ['user', 'user.groups', 'editUser', 'hideUser', 'discussion'];
$user = $this->actor->getUser();
$postIds = (array) $request->get('ids');
$user = $request->actor->getUser();
if (count($postIds)) {
$posts = $this->posts->findByIds($postIds, $user);
} else {
if ($discussionId = $params->get('discussions')) {
if ($discussionId = $request->get('discussions')) {
$where['discussion_id'] = $discussionId;
}
if ($userId = $params->get('users')) {
if ($userId = $request->get('users')) {
$where['user_id'] = $userId;
}
$posts = $this->getPosts($params, $where, $user);
$posts = $this->getPosts($request, $where);
}
if (! count($posts)) {
throw new ModelNotFoundException;
}
// Finally, we can set up the post serializer and use it to create
// a post resource or collection, depending on how many posts were
// requested.
$serializer = new PostSerializer($include);
$document = $this->document()->setData($serializer->collection($posts->load($include)));
return $this->respondWithDocument($document);
return $posts;
}
}

View File

@@ -2,41 +2,57 @@
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Flarum\Core\Repositories\PostRepositoryInterface;
use Flarum\Support\Actor;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Serializers\PostSerializer;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class ShowAction extends BaseAction
class ShowAction extends SerializeResourceAction
{
/**
* @var \Flarum\Core\Repositories\PostRepositoryInterface
*/
protected $posts;
public function __construct(Actor $actor, PostRepositoryInterface $posts)
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\PostSerializer';
/**
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = [
'user' => true,
'editUser' => true,
'hideUser' => true,
'discussion' => false
];
/**
* Instantiate the action.
*
* @param \Flarum\Core\Repositories\PostRepositoryInterface $posts
*/
public function __construct(PostRepositoryInterface $posts)
{
$this->actor = $actor;
$this->posts = $posts;
}
/**
* Show a single post by ID.
*
* @return Response
*/
protected function run(ApiParams $params)
* Get a single post, ready to be serialized and assigned to the JsonApi
* response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Discussion
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$id = $params->get('id');
$posts = $this->posts->findOrFail($id, $this->actor->getUser());
$include = $params->included(['discussion', 'replyTo']);
$relations = array_merge(['user', 'editUser', 'hideUser'], $include);
$posts->load($relations);
// Finally, we can set up the post serializer and use it to create
// a post resource or collection, depending on how many posts were
// requested.
$serializer = new PostSerializer($relations);
$document = $this->document()->setData($serializer->resource($posts->first()));
return $this->respondWithDocument($document);
return $this->posts->findOrFail($request->get('id'), $request->actor->getUser());
}
}

View File

@@ -1,34 +1,47 @@
<?php namespace Flarum\Api\Actions\Posts;
use Flarum\Core\Commands\EditPostCommand;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Serializers\PostSerializer;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
use Illuminate\Contracts\Bus\Dispatcher;
class UpdateAction extends BaseAction
class UpdateAction extends SerializeResourceAction
{
/**
* Edit a post. Allows revision of content, and hiding/unhiding.
*
* @return Response
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected function run(ApiParams $params)
protected $bus;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\PostSerializer';
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$postId = $params->get('id');
$this->bus = $bus;
}
// EditPost is a single command because we don't want to allow partial
// updates (i.e. if we were to run one command and then another, if the
// second one failed, the first one would still have succeeded.)
$command = new EditPostCommand($postId, $this->actor->getUser());
$this->hydrate($command, $params->get('data'));
$post = $this->dispatch($command, $params);
// Presumably, the post was updated successfully. (The command handler
// would have thrown an exception if not.) We set this post as our
// document's primary element.
$serializer = new PostSerializer;
$document = $this->document()->setData($serializer->resource($post));
return $this->respondWithDocument($document);
/**
* Update a post according to input from the API request, and return it
* ready to be serialized and assigned to the JsonApi response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Post
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
return $this->bus->dispatch(
new EditPostCommand($request->get('id'), $request->actor->getUser(), $request->get('data'))
);
}
}

View File

@@ -16,21 +16,15 @@ abstract class SerializeAction implements ActionInterface
public static $serializer;
/**
* The relations that are available to be included.
*
* @var array
*/
public static $includeAvailable = [];
/**
* The relations that are included by default.
* The relationships that are available to be included (keys), and which
* ones are included by default (boolean values).
*
* @var array
*/
public static $include = [];
/**
* The relations that are linked by default.
* The relationships that are linked by default.
*
* @var array
*/
@@ -41,24 +35,24 @@ abstract class SerializeAction implements ActionInterface
*
* @var integer
*/
public static $limitMax;
public static $limitMax = 50;
/**
* The number of records included by default.
*
* @var integer
*/
public static $limit;
public static $limit = 20;
/**
* The fields that are available to be sorted by.
*
* @var array
*/
public static $sortAvailable = [];
public static $sortFields = [];
/**
* The default field to sort by.
* The default sort field and order to user.
*
* @var string
*/
@@ -110,7 +104,7 @@ abstract class SerializeAction implements ActionInterface
*/
protected static function buildJsonApiRequest(Request $request)
{
$request = new JsonApiRequest($request->input, $request->actor, $request->httpRequest);
$request = new JsonApiRequest($request->input, $request->actor, $request->http);
$criteria = new Criteria($request->input);
@@ -132,7 +126,7 @@ abstract class SerializeAction implements ActionInterface
*/
protected static function sanitizeInclude(array $include)
{
return array_intersect($include, static::$includeAvailable) ?: static::$include;
return array_intersect($include, array_keys(static::$include)) ?: array_keys(array_filter(static::$include));
}
/**
@@ -144,7 +138,7 @@ abstract class SerializeAction implements ActionInterface
*/
protected static function sanitizeSort(array $sort)
{
return array_intersect_key($sort, array_flip(static::$sortAvailable)) ?: static::$sort;
return array_intersect_key($sort, array_flip(static::$sortFields)) ?: static::$sort;
}
/**

View File

@@ -1,36 +1,57 @@
<?php namespace Flarum\Api\Actions\Users;
use Flarum\Core\Commands\RegisterUserCommand;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Serializers\UserSerializer;
use Flarum\Api\Actions\CreateAction as BaseCreateAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
use Illuminate\Contracts\Bus\Dispatcher;
class CreateAction extends BaseAction
class CreateAction extends BaseCreateAction
{
/**
* Register a user.
* The command bus.
*
* @return Response
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected function run(ApiParams $params)
protected $bus;
/**
* The default forum instance.
*
* @var \Flarum\Core\Models\Forum
*/
protected $forum;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\UserSerializer';
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
* @param \Flarum\Core\Models\Forum $forum
*/
public function __construct(Dispatcher $bus, Forum $forum)
{
// We've received a request to register a user. By default, the only
// required attributes of a user is the username, email, and password.
// Let's set up a command with this information. We also fire an event
// to allow plugins to add data to the command.
$username = $params->get('data.username');
$email = $params->get('data.email');
$password = $params->get('data.password');
$this->bus = $bus;
$this->forum = $forum;
}
$command = new RegisterUserCommand($username, $email, $password, $this->actor->getUser(), app('flarum.forum'));
$user = $this->dispatch($command, $params);
// Presumably, the user was created successfully. (The command handler
// would have thrown an exception if not.) We set this post as our
// document's primary element.
$serializer = new UserSerializer;
$document = $this->document()->setData($serializer->resource($user));
return $this->respondWithDocument($document, 201);
/**
* Register a user according to input from the API request.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\User
*/
protected function create(JsonApiRequest $request, JsonApiResponse $response)
{
return $this->bus->dispatch(
new RegisterUserCommand($request->actor->getUser(), $this->forum, $request->get('data'))
);
}
}

View File

@@ -1,23 +1,41 @@
<?php namespace Flarum\Api\Actions\Users;
use Flarum\Core\Commands\DeleteUserCommand;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\DeleteAction as BaseDeleteAction;
use Flarum\Api\Request;
use Illuminate\Http\Response;
use Illuminate\Contracts\Bus\Dispatcher;
class DeleteAction extends BaseAction
class DeleteAction extends BaseDeleteAction
{
/**
* The command bus.
*
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected $bus;
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$this->bus = $bus;
}
/**
* Delete a user.
*
* @return Response
* @param \Flarum\Api\Request $request
* @param \Illuminate\Http\Response $response
* @return void
*/
protected function run(ApiParams $params)
protected function delete(Request $request, Response $response)
{
$userId = $params->get('id');
$command = new DeleteUserCommand($userId, $this->actor->getUser());
$this->dispatch($command, $params);
return $this->respondWithoutContent();
$this->bus->dispatch(
new DeleteUserCommand($request->get('id'), $request->actor->getUser())
);
}
}

View File

@@ -2,12 +2,11 @@
use Flarum\Core\Search\Users\UserSearchCriteria;
use Flarum\Core\Search\Users\UserSearcher;
use Flarum\Support\Actor;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Serializers\UserSerializer;
use Flarum\Api\Actions\SerializeCollectionAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class IndexAction extends BaseAction
class IndexAction extends SerializeCollectionAction
{
/**
* The user searcher.
@@ -21,59 +20,59 @@ class IndexAction extends BaseAction
*
* @param \Flarum\Core\Search\Discussions\UserSearcher $searcher
*/
public function __construct(Actor $actor, UserSearcher $searcher)
public function __construct(UserSearcher $searcher)
{
$this->actor = $actor;
$this->searcher = $searcher;
}
/**
* Show a list of users.
* The name of the serializer class to output results with.
*
* @return \Illuminate\Http\Response
* @var string
*/
protected function run(ApiParams $params)
public static $serializer = 'Flarum\Api\Serializers\UserSerializer';
/**
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = [
'groups' => true
];
/**
* The fields that are available to be sorted by.
*
* @var array
*/
public static $sortFields = ['username', 'postsCount', 'discussionsCount', 'lastSeenTime', 'joinTime'];
/**
* Get the user results, ready to be serialized and assigned to the
* document response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Illuminate\Database\Eloquent\Collection
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$query = $params->get('q');
$start = $params->start();
$include = $params->included(['groups']);
$count = $params->count(20, 50);
$sort = $params->sort(['', 'username', 'posts', 'discussions', 'lastActive', 'created']);
$criteria = new UserSearchCriteria(
$request->actor->getUser(),
$request->get('q'),
$request->sort
);
$relations = array_merge(['groups'], $include);
// Set up the user searcher with our search criteria, and get the
// requested range of results with the necessary relations loaded.
$criteria = new UserSearchCriteria($this->actor->getUser(), $query, $sort['field'], $sort['order']);
$results = $this->searcher->search($criteria, $count, $start, $relations);
$document = $this->document();
$results = $this->searcher->search($criteria, $request->limit, $request->offset, $request->include);
if (($total = $results->getTotal()) !== null) {
$document->addMeta('total', $total);
$response->content->addMeta('total', $total);
}
// If there are more results, then we need to construct a URL to the
// next results page and add that to the metadata. We do this by
// compacting all of the valid query parameters which have been
// specified.
if ($results->areMoreResults()) {
$start += $count;
$include = implode(',', $include);
$sort = $sort['string'];
$input = array_filter(compact('query', 'sort', 'start', 'count', 'include'));
$moreUrl = $this->buildUrl('users.index', [], $input);
} else {
$moreUrl = '';
}
$document->addMeta('moreUrl', $moreUrl);
// $response->content->addMeta('moreUrl', $moreUrl);
// Finally, we can set up the discussion serializer and use it to create
// a collection of discussion results.
$serializer = new UserSerializer($relations);
$document->setData($serializer->collection($results->getUsers()));
return $this->respondWithDocument($document);
return $results->getUsers();
}
}

View File

@@ -1,44 +1,60 @@
<?php namespace Flarum\Api\Actions\Users;
use Flarum\Core\Repositories\UserRepositoryInterface;
use Flarum\Support\Actor;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Serializers\UserSerializer;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
class ShowAction extends BaseAction
class ShowAction extends SerializeResourceAction
{
protected $actor;
/**
* @var \Flarum\Core\Repositories\UserRepositoryInterface
*/
protected $users;
public function __construct(Actor $actor, UserRepositoryInterface $users)
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\UserSerializer';
/**
* The relationships that are available to be included, and which ones are
* included by default.
*
* @var array
*/
public static $include = [
'groups' => true
];
/**
* Instantiate the action.
*
* @param \Flarum\Core\Repositories\UserRepositoryInterface $users
*/
public function __construct(UserRepositoryInterface $users)
{
$this->actor = $actor;
$this->users = $users;
}
/**
* Show a single user.
* Get a single user, ready to be serialized and assigned to the JsonApi
* response.
*
* @return Response
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Discussion
*/
public function run(ApiParams $params)
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
$id = $params->get('id');
$id = $request->get('id');
if (! is_numeric($id)) {
$id = $this->users->getIdForUsername($id);
}
$user = $this->users->findOrFail($id, $this->actor->getUser());
// Set up the user serializer, which we will use to create the
// document's primary resource. We will specify that we want the
// 'groups' relation to be included by default.
$serializer = new UserSerializer(['groups']);
$document = $this->document()->setData($serializer->resource($user));
return $this->respondWithDocument($document);
return $this->users->findOrFail($id, $request->actor->getUser());
}
}

View File

@@ -1,35 +1,47 @@
<?php namespace Flarum\Api\Actions\Users;
use Flarum\Core\Commands\EditUserCommand;
use Flarum\Api\Actions\ApiParams;
use Flarum\Api\Actions\BaseAction;
use Flarum\Api\Serializers\UserSerializer;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
use Illuminate\Contracts\Bus\Dispatcher;
class UpdateAction extends BaseAction
class UpdateAction extends SerializeResourceAction
{
/**
* Edit a user. Allows renaming the user, changing their email, and setting
* their password.
*
* @return Response
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected function run(ApiParams $params)
protected $bus;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\UserSerializer';
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$userId = $params->get('id');
$this->bus = $bus;
}
// EditUser is a single command because we don't want to allow partial
// updates (i.e. if we were to run one command and then another, if the
// second one failed, the first one would still have succeeded.)
$command = new EditUserCommand($userId, $this->actor->getUser());
$this->hydrate($command, $params->get('data'));
$user = $this->dispatch($command, $params);
// Presumably, the user was updated successfully. (The command handler
// would have thrown an exception if not.) We set this user as our
// document's primary element.
$serializer = new UserSerializer;
$document = $this->document()->setData($serializer->resource($user));
return $this->respondWithDocument($document);
/**
* Update a user according to input from the API request, and return it
* ready to be serialized and assigned to the JsonApi response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\Post
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
return $this->bus->dispatch(
new EditUserCommand($request->get('id'), $request->actor->getUser(), $request->get('data'))
);
}
}

View File

@@ -1,25 +1,47 @@
<?php namespace Flarum\Api\Actions\Users;
use Flarum\Api\Actions\BaseAction;
use Flarum\Core\Commands\UploadAvatarCommand;
use Flarum\Api\Serializers\UserSerializer;
use Illuminate\Http\Request;
use Flarum\Api\Actions\SerializeResourceAction;
use Flarum\Api\JsonApiRequest;
use Flarum\Api\JsonApiResponse;
use Illuminate\Contracts\Bus\Dispatcher;
class UploadAvatarAction extends BaseAction
class UploadAvatarAction extends SerializeResourceAction
{
public function handle(Request $request, $routeParams = [])
/**
* @var \Illuminate\Contracts\Bus\Dispatcher
*/
protected $bus;
/**
* The name of the serializer class to output results with.
*
* @var string
*/
public static $serializer = 'Flarum\Api\Serializers\UserSerializer';
/**
* Instantiate the action.
*
* @param \Illuminate\Contracts\Bus\Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$userId = array_get($routeParams, 'id');
$file = $request->file('avatar');
$this->bus = $bus;
}
$user = $this->dispatch(
new UploadAvatarCommand($userId, $file, $this->actor->getUser()),
$routeParams
/**
* Upload an avatar for a user, and return the user ready to be serialized
* and assigned to the JsonApi response.
*
* @param \Flarum\Api\JsonApiRequest $request
* @param \Flarum\Api\JsonApiResponse $response
* @return \Flarum\Core\Models\User
*/
protected function data(JsonApiRequest $request, JsonApiResponse $response)
{
return $this->bus->dispatch(
new UploadAvatarCommand($request->get('id'), $request->http->file('avatar'), $request->actor->getUser())
);
$serializer = new UserSerializer;
$document = $this->document()->setData($serializer->resource($user));
return $this->respondWithDocument($document);
}
}

View File

@@ -1,17 +0,0 @@
<?php namespace Flarum\Api\Events;
class WillRespondWithDocument
{
public $document;
public $statusCode;
public $headers;
public function __construct($document, &$statusCode, &$headers)
{
$this->document = $document;
$this->statusCode = $statusCode;
$this->headers = $headers;
}
}

View File

@@ -9,17 +9,17 @@ class Request
public $actor;
public $httpRequest;
public $http;
public function __construct(array $input, Actor $actor, IlluminateRequest $httpRequest = null)
public function __construct(array $input, Actor $actor, IlluminateRequest $http = null)
{
$this->input = $input;
$this->actor = $actor;
$this->httpRequest = $httpRequest;
$this->http = $http;
}
public function get($key, $default = null)
{
return isset($this->input[$key]) ? $this->input[$key] : $default;
return array_get($this->input, $key, $default);
}
}