mirror of
https://github.com/flarum/core.git
synced 2025-10-18 18:26:07 +02:00
Upgrade to L5 + huge refactor + more. closes #2
New stuff: - Signup + email confirmation. - Updated authentication strategy with remember cookies. closes #5 - New search system with some example gambits! This is cool - check out the source. Fulltext drivers will be implemented as decorators overriding the EloquentPostRepository’s findByContent method. - Lay down the foundation for bootstrapping the Ember app. - Update Web layer’s asset manager to properly publish CSS/JS files. - Console commands to run installation migrations and seeds. Refactoring: - New structure: move models, repositories, commands, and events into their own namespaces, rather than grouping by entity. - All events are classes. - Use L5 middleware and command bus implementations. - Clearer use of repositories and the Active Record pattern. Repositories are used only for retrieval of ActiveRecord objects, and then save/delete operations are called directly on those ActiveRecords. This way, we don’t over-abstract at the cost of Eloquent magic, but testing is still easy. - Refactor of Web layer so that it uses the Actions routing architecture. - “Actor” concept instead of depending on Laravel’s Auth. - General cleanup!
This commit is contained in:
89
src/Api/Actions/ApiParams.php
Normal file
89
src/Api/Actions/ApiParams.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php namespace Flarum\Api\Actions;
|
||||
|
||||
class ApiParams
|
||||
{
|
||||
protected $params;
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return array_get($this->params, $key, $default);
|
||||
}
|
||||
|
||||
public function range($key, $default = null, $min = null, $max = null)
|
||||
{
|
||||
$value = (int) $this->get($key, $default);
|
||||
|
||||
if (! is_null($min)) {
|
||||
$value = max($value, $min);
|
||||
}
|
||||
if (! is_null($max)) {
|
||||
$value = min($value, $max);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function included($available)
|
||||
{
|
||||
$requested = explode(',', $this->get('include'));
|
||||
return array_intersect((array) $available, $requested);
|
||||
}
|
||||
|
||||
// public function explodeIds($ids)
|
||||
// {
|
||||
// return array_unique(array_map('intval', array_filter(explode(',', $ids))));
|
||||
// }
|
||||
|
||||
public function in($key, $options)
|
||||
{
|
||||
$value = $this->get($key);
|
||||
|
||||
if (array_key_exists($key, $options)) {
|
||||
return $options[$key];
|
||||
}
|
||||
if (! in_array($value, $options)) {
|
||||
$value = reset($options);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function sort($options)
|
||||
{
|
||||
$criteria = (string) $this->get('sort', '');
|
||||
$order = null;
|
||||
|
||||
if ($criteria && $criteria[0] == '-') {
|
||||
$order = 'desc';
|
||||
$criteria = substr($criteria, 1);
|
||||
}
|
||||
|
||||
if (! in_array($criteria, $options)) {
|
||||
$criteria = reset($options);
|
||||
}
|
||||
|
||||
if ($criteria && ! $order) {
|
||||
$order = 'asc';
|
||||
}
|
||||
|
||||
return [
|
||||
'field' => $criteria,
|
||||
'order' => $order,
|
||||
'string' => ($order == 'desc' ? '-' : '').$criteria
|
||||
];
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
return $this->range('start', 0, 0);
|
||||
}
|
||||
|
||||
public function count($default, $max = 100)
|
||||
{
|
||||
return $this->range('count', $default, 1, $max);
|
||||
}
|
||||
}
|
130
src/Api/Actions/BaseAction.php
Normal file
130
src/Api/Actions/BaseAction.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php namespace Flarum\Api\Actions;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Tobscure\JsonApi\Document;
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Flarum\Api\Events\CommandWillBeDispatched;
|
||||
use Flarum\Api\Events\WillRespondWithDocument;
|
||||
use Flarum\Web\Actions\Action;
|
||||
use Config;
|
||||
use App;
|
||||
use Response;
|
||||
|
||||
abstract class BaseAction extends Action
|
||||
{
|
||||
abstract protected function run(ApiParams $params);
|
||||
|
||||
public function __construct(Actor $actor, Dispatcher $bus)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
$this->bus = $bus;
|
||||
}
|
||||
|
||||
public function handle(Request $request, $routeParams = [])
|
||||
{
|
||||
$this->registerErrorHandlers(); // @todo convert to middleware and add to route group?
|
||||
|
||||
$params = array_merge($request->all(), $routeParams);
|
||||
|
||||
return $this->call($params);
|
||||
}
|
||||
|
||||
public function call($params = [])
|
||||
{
|
||||
$params = new ApiParams($params);
|
||||
|
||||
return $this->run($params);
|
||||
}
|
||||
|
||||
public function hydrate($object, $params)
|
||||
{
|
||||
foreach ($params as $k => $v) {
|
||||
$object->$k = $v;
|
||||
}
|
||||
}
|
||||
|
||||
protected function dispatch($command, $params)
|
||||
{
|
||||
$this->event(new CommandWillBeDispatched($command, $params));
|
||||
return $this->bus->dispatch($command);
|
||||
}
|
||||
|
||||
protected function event($event)
|
||||
{
|
||||
event($event);
|
||||
}
|
||||
|
||||
public function document()
|
||||
{
|
||||
return new Document;
|
||||
}
|
||||
|
||||
protected function buildUrl($route, $params = [], $input = [])
|
||||
{
|
||||
$url = route('flarum.api.'.$route, $params);
|
||||
$queryString = $input ? '?'.http_build_query($input) : '';
|
||||
|
||||
return $url.$queryString;
|
||||
}
|
||||
|
||||
protected function respondWithoutContent($statusCode = 204, $headers = [])
|
||||
{
|
||||
return Response::make('', $statusCode, $headers);
|
||||
}
|
||||
|
||||
protected function respondWithArray($array, $statusCode = 200, $headers = [])
|
||||
{
|
||||
return Response::json($array, $statusCode, $headers);
|
||||
}
|
||||
|
||||
protected function respondWithDocument($document, $statusCode = 200, $headers = [])
|
||||
{
|
||||
$headers['Content-Type'] = 'application/vnd.api+json';
|
||||
|
||||
$this->event(new WillRespondWithDocument($document, $statusCode, $headers));
|
||||
|
||||
return $this->respondWithArray($document->toArray(), $statusCode, $headers);
|
||||
}
|
||||
|
||||
protected function registerErrorHandlers()
|
||||
{
|
||||
// if (! Config::get('app.debug')) {
|
||||
// App::error(function ($exception, $code) {
|
||||
// return $this->respondWithError('ApplicationError', $code);
|
||||
// });
|
||||
// }
|
||||
|
||||
// App::error(function (ModelNotFoundException $exception) {
|
||||
// return $this->respondWithError('ResourceNotFound', 404);
|
||||
// });
|
||||
|
||||
// App::error(function (ValidationFailureException $exception) {
|
||||
// $errors = [];
|
||||
// foreach ($exception->getErrors()->getMessages() as $field => $messages) {
|
||||
// $errors[] = [
|
||||
// 'code' => 'ValidationFailure',
|
||||
// 'detail' => implode("\n", $messages),
|
||||
// 'path' => $field
|
||||
// ];
|
||||
// }
|
||||
// return $this->respondWithErrors($errors, 422);
|
||||
// });
|
||||
}
|
||||
|
||||
protected function respondWithErrors($errors, $httpCode = 500)
|
||||
{
|
||||
return Response::json(['errors' => $errors], $httpCode);
|
||||
}
|
||||
|
||||
protected function respondWithError($error, $httpCode = 500, $detail = null)
|
||||
{
|
||||
$error = ['code' => $error];
|
||||
|
||||
if ($detail) {
|
||||
$error['detail'] = $detail;
|
||||
}
|
||||
|
||||
return $this->respondWithErrors([$error], $httpCode);
|
||||
}
|
||||
}
|
41
src/Api/Actions/Discussions/CreateAction.php
Normal file
41
src/Api/Actions/Discussions/CreateAction.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php namespace Flarum\Api\Actions\Discussions;
|
||||
|
||||
use Flarum\Core\Commands\StartDiscussionCommand;
|
||||
use Flarum\Core\Commands\ReadDiscussionCommand;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Serializers\DiscussionSerializer;
|
||||
|
||||
class CreateAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Start a new discussion.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
// By default, the only required attributes of a discussion are the
|
||||
// title and the content. We'll extract these from the rbaseequest data
|
||||
// and pass them through to the StartDiscussionCommand.
|
||||
$title = $params->get('discussions.title');
|
||||
$content = $params->get('discussions.content');
|
||||
$user = $this->actor->getUser();
|
||||
|
||||
$command = new StartDiscussionCommand($title, $content, $user, app('flarum.forum'));
|
||||
$discussion = $this->dispatch($command, $params);
|
||||
|
||||
// After creating the discussion, 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($discussion->id, $user, 1);
|
||||
$this->dispatch($command, $params);
|
||||
}
|
||||
|
||||
$serializer = new DiscussionSerializer(['posts']);
|
||||
$document = $this->document()->setPrimaryElement($serializer->resource($discussion));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
23
src/Api/Actions/Discussions/DeleteAction.php
Normal file
23
src/Api/Actions/Discussions/DeleteAction.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php namespace Flarum\Api\Actions\Discussions;
|
||||
|
||||
use Flarum\Core\Commands\DeleteDiscussionCommand;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
|
||||
class DeleteAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Delete a discussion.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$discussionId = $params->get('id');
|
||||
|
||||
$command = new DeleteDiscussionCommand($discussionId, $this->actor->getUser());
|
||||
$this->dispatch($command, $params);
|
||||
|
||||
return $this->respondWithoutContent();
|
||||
}
|
||||
}
|
81
src/Api/Actions/Discussions/IndexAction.php
Normal file
81
src/Api/Actions/Discussions/IndexAction.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php namespace Flarum\Api\Actions\Discussions;
|
||||
|
||||
use Flarum\Core\Search\Discussions\DiscussionSearchCriteria;
|
||||
use Flarum\Core\Search\Discussions\DiscussionSearcher;
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Serializers\DiscussionSerializer;
|
||||
|
||||
class IndexAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* The discussion searcher.
|
||||
*
|
||||
* @var DiscussionSearcher
|
||||
*/
|
||||
protected $searcher;
|
||||
|
||||
/**
|
||||
* Instantiate the action.
|
||||
*
|
||||
* @param DiscussionSearcher $searcher
|
||||
*/
|
||||
public function __construct(Actor $actor, DiscussionSearcher $searcher)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
$this->searcher = $searcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of discussions.
|
||||
*
|
||||
* @todo custom rate limit for this function? determined by if $key was valid?
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$query = $params->get('q');
|
||||
$start = $params->start();
|
||||
$include = $params->included(['startPost', 'lastPost', 'relevantPosts']);
|
||||
$count = $params->count(20, 50);
|
||||
$sort = $params->sort(['', 'lastPost', 'replies', 'created']);
|
||||
|
||||
$relations = array_merge(['startUser', 'lastUser'], $include);
|
||||
|
||||
// Set up the discussion finder with our search criteria, and get the
|
||||
// requested range of results with the necessary relations loaded.
|
||||
$criteria = new DiscussionSearchCriteria($this->actor->getUser(), $query, $sort['field'], $sort['order']);
|
||||
$load = array_merge($relations, ['state']);
|
||||
|
||||
$results = $this->searcher->search($criteria, $count, $start, $load);
|
||||
|
||||
$document = $this->document();
|
||||
|
||||
if (($total = $results->getTotal()) !== null) {
|
||||
$document->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('discussions.index', [], $input);
|
||||
} else {
|
||||
$moreUrl = '';
|
||||
}
|
||||
$document->addMeta('moreUrl', $moreUrl);
|
||||
|
||||
// Finally, we can set up the discussion serializer and use it to create
|
||||
// a collection of discussion results.
|
||||
$serializer = new DiscussionSerializer($relations);
|
||||
$document->setPrimaryElement($serializer->collection($results->getDiscussions()));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
70
src/Api/Actions/Discussions/ShowAction.php
Normal file
70
src/Api/Actions/Discussions/ShowAction.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php namespace Flarum\Api\Actions\Discussions;
|
||||
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Flarum\Core\Repositories\DiscussionRepositoryInterface as DiscussionRepository;
|
||||
use Flarum\Core\Repositories\PostRepositoryInterface as PostRepository;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Actions\Posts\GetsPostsForDiscussion;
|
||||
use Flarum\Api\Serializers\DiscussionSerializer;
|
||||
|
||||
class ShowAction extends BaseAction
|
||||
{
|
||||
use GetsPostsForDiscussion;
|
||||
|
||||
/**
|
||||
* The discussion repository.
|
||||
*
|
||||
* @var DiscussionRepository
|
||||
*/
|
||||
protected $discussions;
|
||||
|
||||
/**
|
||||
* The post repository.
|
||||
*
|
||||
* @var PostRepository
|
||||
*/
|
||||
protected $posts;
|
||||
|
||||
/**
|
||||
* Instantiate the action.
|
||||
*
|
||||
* @param PostRepository $posts
|
||||
*/
|
||||
public function __construct(Actor $actor, DiscussionRepository $discussions, PostRepository $posts)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
$this->discussions = $discussions;
|
||||
$this->posts = $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a single discussion.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$include = $params->included(['startPost', 'lastPost', 'posts']);
|
||||
|
||||
$discussion = $this->discussions->findOrFail($params->get('id'), $this->actor->getUser());
|
||||
|
||||
if (in_array('posts', $include)) {
|
||||
$relations = ['user', 'user.groups', 'editUser', 'hideUser'];
|
||||
$discussion->posts = $this->getPostsForDiscussion($params, $discussion->id)->load($relations);
|
||||
|
||||
$include = array_merge($include, array_map(function ($relation) {
|
||||
return 'posts.'.$relation;
|
||||
}, $relations));
|
||||
}
|
||||
|
||||
// Set up the discussion serializer, which we will use to create the
|
||||
// document's primary resource. As well as including the requested
|
||||
// relations, we will specify that we want the 'posts' relation to be
|
||||
// linked so that a list of post IDs will show up in the response.
|
||||
$serializer = new DiscussionSerializer($include, ['posts']);
|
||||
$document = $this->document()->setPrimaryElement($serializer->resource($discussion));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
54
src/Api/Actions/Discussions/UpdateAction.php
Normal file
54
src/Api/Actions/Discussions/UpdateAction.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php namespace Flarum\Api\Actions\Discussions;
|
||||
|
||||
use Flarum\Core\Commands\EditDiscussionCommand;
|
||||
use Flarum\Core\Commands\ReadDiscussionCommand;
|
||||
use Flarum\Core\Exceptions\PermissionDeniedException;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Serializers\DiscussionSerializer;
|
||||
|
||||
class UpdateAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Edit a discussion. Allows renaming the discussion, and updating its read
|
||||
* state with regards to the current user.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$discussionId = $params->get('id');
|
||||
$user = $this->actor->getUser();
|
||||
|
||||
// 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($params->get('discussions'), ['readNumber'])) {
|
||||
$command = new EditDiscussionCommand($discussionId, $user);
|
||||
$this->hydrate($command, $params->get('discussions'));
|
||||
$discussion = $this->dispatch($command, $params);
|
||||
}
|
||||
|
||||
// Next, if a read number was specified in the request, we will run the
|
||||
// ReadDiscussionCommand.
|
||||
//
|
||||
// @todo Currently, if the user doesn't have permission to edit a
|
||||
// discussion, they're unable to update their readNumber because a
|
||||
// PermissionsDeniedException is thrown by the
|
||||
// EditDiscussionCommand above. So this needs to be extracted into
|
||||
// its own endpoint.
|
||||
if ($readNumber = $params->get('discussions.readNumber')) {
|
||||
$command = new ReadDiscussionCommand($discussionId, $user, $readNumber);
|
||||
$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 DiscussionSerializer(['addedPosts', 'addedPosts.user']);
|
||||
$document = $this->document()->setPrimaryElement($serializer->resource($discussion));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
18
src/Api/Actions/Groups/IndexAction.php
Normal file
18
src/Api/Actions/Groups/IndexAction.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php namespace Flarum\Api\Actions\Groups;
|
||||
|
||||
use Flarum\Core\Models\Group;
|
||||
use Flarum\Api\Actions\Base;
|
||||
use Flarum\Api\Serializers\GroupSerializer;
|
||||
|
||||
class Index extends Base
|
||||
{
|
||||
protected function run()
|
||||
{
|
||||
$groups = Group::get();
|
||||
|
||||
$serializer = new GroupSerializer;
|
||||
$this->document->setPrimaryElement($serializer->collection($groups));
|
||||
|
||||
return $this->respondWithDocument();
|
||||
}
|
||||
}
|
47
src/Api/Actions/Posts/CreateAction.php
Normal file
47
src/Api/Actions/Posts/CreateAction.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php namespace Flarum\Api\Actions\Posts;
|
||||
|
||||
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;
|
||||
|
||||
class CreateAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Reply to a discussion.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$user = $this->actor->getUser();
|
||||
|
||||
// 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('posts.links.discussion');
|
||||
$content = $params->get('posts.content');
|
||||
|
||||
$command = new PostReplyCommand($discussionId, $content, $user);
|
||||
$post = $this->dispatch($command, $params);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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()->setPrimaryElement($serializer->resource($post));
|
||||
|
||||
return $this->respondWithDocument($document, 201);
|
||||
}
|
||||
}
|
23
src/Api/Actions/Posts/DeleteAction.php
Normal file
23
src/Api/Actions/Posts/DeleteAction.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php namespace Flarum\Api\Actions\Posts;
|
||||
|
||||
use Flarum\Core\Commands\DeletePostCommand;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
|
||||
class DeleteAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Delete a post.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$postId = $params->get('id');
|
||||
|
||||
$command = new DeletePostCommand($postId, $this->actor->getUser());
|
||||
$this->dispatch($command, $params);
|
||||
|
||||
return $this->respondWithoutContent();
|
||||
}
|
||||
}
|
31
src/Api/Actions/Posts/GetsPostsForDiscussion.php
Normal file
31
src/Api/Actions/Posts/GetsPostsForDiscussion.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php namespace Flarum\Api\Actions\Posts;
|
||||
|
||||
use Flarum\Core\Repositories\PostRepositoryInterface;
|
||||
use Flarum\Core\Models\User;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
|
||||
trait GetsPostsForDiscussion
|
||||
{
|
||||
protected function getPostsForDiscussion(ApiParams $params, $discussionId)
|
||||
{
|
||||
$sort = $params->sort(['time']);
|
||||
$count = $params->count(20, 50);
|
||||
$user = $this->actor->getUser();
|
||||
|
||||
if (($near = $params->get('near')) > 1) {
|
||||
$start = $this->posts->getIndexForNumber($discussionId, $near, $user);
|
||||
$start = max(0, $start - $count / 2);
|
||||
} else {
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
return $this->posts->findByDiscussion(
|
||||
$discussionId,
|
||||
$user,
|
||||
$sort['field'],
|
||||
$sort['order'] ?: 'asc',
|
||||
$count,
|
||||
$start
|
||||
);
|
||||
}
|
||||
}
|
62
src/Api/Actions/Posts/IndexAction.php
Normal file
62
src/Api/Actions/Posts/IndexAction.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php namespace Flarum\Api\Actions\Posts;
|
||||
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Flarum\Core\Repositories\PostRepositoryInterface;
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Serializers\PostSerializer;
|
||||
|
||||
class IndexAction extends BaseAction
|
||||
{
|
||||
use GetsPostsForDiscussion;
|
||||
|
||||
/**
|
||||
* The post repository.
|
||||
*
|
||||
* @var Post
|
||||
*/
|
||||
protected $posts;
|
||||
|
||||
/**
|
||||
* Instantiate the action.
|
||||
*
|
||||
* @param Post $posts
|
||||
*/
|
||||
public function __construct(Actor $actor, 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)
|
||||
{
|
||||
$postIds = (array) $params->get('ids');
|
||||
$include = ['user', 'user.groups', 'editUser', 'hideUser'];
|
||||
$user = $this->actor->getUser();
|
||||
|
||||
if (count($postIds)) {
|
||||
$posts = $this->posts->findByIds($postIds, $user);
|
||||
} else {
|
||||
$discussionId = $params->get('discussions');
|
||||
$posts = $this->getPostsForDiscussion($params, $discussionId, $user);
|
||||
}
|
||||
|
||||
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()->setPrimaryElement($serializer->collection($posts->load($include)));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
42
src/Api/Actions/Posts/ShowAction.php
Normal file
42
src/Api/Actions/Posts/ShowAction.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php namespace Flarum\Api\Actions\Posts;
|
||||
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Flarum\Core\Repositories\PostRepositoryInterface;
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Serializers\PostSerializer;
|
||||
|
||||
class ShowAction extends BaseAction
|
||||
{
|
||||
protected $posts;
|
||||
|
||||
public function __construct(Actor $actor, PostRepositoryInterface $posts)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
$this->posts = $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a single post by ID.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$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()->setPrimaryElement($serializer->resource($posts->first()));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
34
src/Api/Actions/Posts/UpdateAction.php
Normal file
34
src/Api/Actions/Posts/UpdateAction.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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;
|
||||
|
||||
class UpdateAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Edit a post. Allows revision of content, and hiding/unhiding.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$postId = $params->get('id');
|
||||
|
||||
// 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('posts'));
|
||||
$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()->setPrimaryElement($serializer->resource($post));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
43
src/Api/Actions/TokenAction.php
Normal file
43
src/Api/Actions/TokenAction.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php namespace Flarum\Api\Actions;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Flarum\Core\Commands\GenerateAccessTokenCommand;
|
||||
use Flarum\Core\Repositories\UserRepositoryInterface;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
|
||||
class TokenAction extends BaseAction
|
||||
{
|
||||
protected $users;
|
||||
|
||||
public function __construct(UserRepositoryInterface $users, Dispatcher $bus)
|
||||
{
|
||||
$this->users = $users;
|
||||
$this->bus = $bus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log in and return a token.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function run(ApiParams $params)
|
||||
{
|
||||
$identification = $params->get('identification');
|
||||
$password = $params->get('password');
|
||||
|
||||
$user = $this->users->findByIdentification($identification);
|
||||
|
||||
if (! $user || ! $user->checkPassword($password)) {
|
||||
return $this->respondWithError('invalidLogin', 401);
|
||||
}
|
||||
|
||||
$command = new GenerateAccessTokenCommand($user->id);
|
||||
$token = $this->dispatch($command, $params);
|
||||
|
||||
return new JsonResponse([
|
||||
'token' => $token->id,
|
||||
'userId' => $user->id
|
||||
]);
|
||||
}
|
||||
}
|
36
src/Api/Actions/Users/CreateAction.php
Normal file
36
src/Api/Actions/Users/CreateAction.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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;
|
||||
|
||||
class CreateAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Register a user.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
// 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('users.username');
|
||||
$email = $params->get('users.email');
|
||||
$password = $params->get('users.password');
|
||||
|
||||
$command = new RegisterUserCommand($username, $email, $password, $this->actor->getUser());
|
||||
$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()->setPrimaryElement($serializer->resource($user));
|
||||
|
||||
return $this->respondWithDocument($document, 201);
|
||||
}
|
||||
}
|
23
src/Api/Actions/Users/DeleteAction.php
Normal file
23
src/Api/Actions/Users/DeleteAction.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php namespace Flarum\Api\Actions\Users;
|
||||
|
||||
use Flarum\Core\Commands\DeleteUserCommand;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
|
||||
class DeleteAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Delete a user.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$userId = $params->get('id');
|
||||
|
||||
$command = new DeleteUserCommand($userId, $this->actor->getUser());
|
||||
$this->dispatch($command, $params);
|
||||
|
||||
return $this->respondWithoutContent();
|
||||
}
|
||||
}
|
83
src/Api/Actions/Users/IndexAction.php
Normal file
83
src/Api/Actions/Users/IndexAction.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php namespace Flarum\Api\Actions\Users;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\Users\UserFinder;
|
||||
use Flarum\Api\Actions\Base;
|
||||
use Flarum\Api\Serializers\UserSerializer;
|
||||
|
||||
class IndexAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* The user finder.
|
||||
*
|
||||
* @var UserFinder
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
/**
|
||||
* Instantiate the action.
|
||||
*
|
||||
* @param UserFinder $finder
|
||||
*/
|
||||
public function __construct(UserFinder $finder)
|
||||
{
|
||||
$this->finder = $finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of users.
|
||||
*
|
||||
* @todo custom rate limit for this function? determined by if $key was valid?
|
||||
* @return Response
|
||||
*/
|
||||
protected function run()
|
||||
{
|
||||
$query = $this->input('q');
|
||||
$key = $this->input('key');
|
||||
$sort = $this->sort(['', 'username', 'posts', 'discussions', 'lastActive', 'created']);
|
||||
$start = $this->start();
|
||||
$count = $this->count(50, 100);
|
||||
$include = $this->included(['groups']);
|
||||
$relations = array_merge(['groups'], $include);
|
||||
|
||||
// Set up the user finder with our search criteria, and get the
|
||||
// requested range of results with the necessary relations loaded.
|
||||
$this->finder->setUser(User::current());
|
||||
$this->finder->setQuery($query);
|
||||
$this->finder->setSort($sort['by']);
|
||||
$this->finder->setOrder($sort['order']);
|
||||
$this->finder->setKey($key);
|
||||
|
||||
$users = $this->finder->results($count, $start);
|
||||
$users->load($relations);
|
||||
|
||||
if (($total = $this->finder->getCount()) !== null) {
|
||||
$this->document->addMeta('total', $total);
|
||||
}
|
||||
if (($key = $this->finder->getKey()) !== null) {
|
||||
$this->document->addMeta('key', $key);
|
||||
}
|
||||
|
||||
// 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 ($this->finder->areMoreResults()) {
|
||||
$start += $count;
|
||||
$include = implode(',', $include);
|
||||
$sort = $sort['string'];
|
||||
$input = array_filter(compact('query', 'key', 'sort', 'start', 'count', 'include'));
|
||||
$moreUrl = $this->buildUrl('users.index', [], $input);
|
||||
} else {
|
||||
$moreUrl = '';
|
||||
}
|
||||
$this->document->addMeta('moreUrl', $moreUrl);
|
||||
|
||||
// Finally, we can set up the user serializer and use it to create
|
||||
// a collection of user results.
|
||||
$serializer = new UserSerializer($relations);
|
||||
$this->document->setPrimaryElement($serializer->collection($users));
|
||||
|
||||
return $this->respondWithDocument();
|
||||
}
|
||||
}
|
38
src/Api/Actions/Users/ShowAction.php
Normal file
38
src/Api/Actions/Users/ShowAction.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php namespace Flarum\Api\Actions\Users;
|
||||
|
||||
use Flarum\Core\Repositories\UserRepositoryInterface;
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Flarum\Api\Actions\ApiParams;
|
||||
use Flarum\Api\Actions\BaseAction;
|
||||
use Flarum\Api\Serializers\UserSerializer;
|
||||
|
||||
class ShowAction extends BaseAction
|
||||
{
|
||||
protected $actor;
|
||||
|
||||
protected $users;
|
||||
|
||||
public function __construct(Actor $actor, UserRepositoryInterface $users)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a single user.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function run(ApiParams $params)
|
||||
{
|
||||
$user = $this->users->findOrFail($params->get('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()->setPrimaryElement($serializer->resource($user));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
35
src/Api/Actions/Users/UpdateAction.php
Normal file
35
src/Api/Actions/Users/UpdateAction.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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;
|
||||
|
||||
class UpdateAction extends BaseAction
|
||||
{
|
||||
/**
|
||||
* Edit a user. Allows renaming the user, changing their email, and setting
|
||||
* their password.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function run(ApiParams $params)
|
||||
{
|
||||
$userId = $params->get('id');
|
||||
|
||||
// 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('users'));
|
||||
$this->dispatch($command);
|
||||
|
||||
// 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()->setPrimaryElement($serializer->resource($user));
|
||||
|
||||
return $this->respondWithDocument($document);
|
||||
}
|
||||
}
|
29
src/Api/ApiServiceProvider.php
Normal file
29
src/Api/ApiServiceProvider.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php namespace Flarum\Api;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Flarum\Api\Serializers\BaseSerializer;
|
||||
|
||||
class ApiServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
include __DIR__.'/routes.php';
|
||||
|
||||
BaseSerializer::setActor($this->app['Flarum\Core\Support\Actor']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('Flarum\Core\Support\Actor');
|
||||
}
|
||||
}
|
14
src/Api/Events/CommandWillBeDispatched.php
Normal file
14
src/Api/Events/CommandWillBeDispatched.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php namespace Flarum\Api\Events;
|
||||
|
||||
class CommandWillBeDispatched
|
||||
{
|
||||
public $command;
|
||||
|
||||
public $params;
|
||||
|
||||
public function __construct($command, $params)
|
||||
{
|
||||
$this->command = $command;
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
17
src/Api/Events/SerializeAttributes.php
Normal file
17
src/Api/Events/SerializeAttributes.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php namespace Flarum\Api\Events;
|
||||
|
||||
class SerializeAttributes
|
||||
{
|
||||
public $serializer;
|
||||
|
||||
public $model;
|
||||
|
||||
public $attributes;
|
||||
|
||||
public function __construct($serializer, $model, &$attributes)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
$this->model = $model;
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
}
|
23
src/Api/Events/SerializeRelationship.php
Normal file
23
src/Api/Events/SerializeRelationship.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php namespace Flarum\Api\Events;
|
||||
|
||||
class SerializeRelationship
|
||||
{
|
||||
public $serializer;
|
||||
|
||||
public $model;
|
||||
|
||||
public $type;
|
||||
|
||||
public $name;
|
||||
|
||||
public $relations;
|
||||
|
||||
public function __construct($serializer, $model, $type, $name, $relations)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
$this->model = $model;
|
||||
$this->type = $type;
|
||||
$this->name = $name;
|
||||
$this->relations = $relations;
|
||||
}
|
||||
}
|
17
src/Api/Events/WillRespondWithDocument.php
Normal file
17
src/Api/Events/WillRespondWithDocument.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
29
src/Api/Middleware/LoginWithHeaderMiddleware.php
Normal file
29
src/Api/Middleware/LoginWithHeaderMiddleware.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php namespace Flarum\Api\Middleware;
|
||||
|
||||
use Flarum\Core\Models\AccessToken;
|
||||
use Flarum\Core\Support\Actor;
|
||||
use Closure;
|
||||
|
||||
class LoginWithHeaderMiddleware
|
||||
{
|
||||
protected $actor;
|
||||
|
||||
protected $prefix = 'Token ';
|
||||
|
||||
public function __construct(Actor $actor)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
}
|
||||
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$header = $request->headers->get('authorization');
|
||||
if (starts_with($header, $this->prefix) &&
|
||||
($token = substr($header, strlen($this->prefix))) &&
|
||||
($accessToken = AccessToken::where('id', $token)->first())) {
|
||||
$this->actor->setUser($accessToken->user);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
19
src/Api/Serializers/ActivitySerializer.php
Normal file
19
src/Api/Serializers/ActivitySerializer.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\Activity;
|
||||
use Event;
|
||||
|
||||
class ActivitySerializer extends BaseSerializer {
|
||||
|
||||
public function serialize(Activity $activity)
|
||||
{
|
||||
$serialized = [
|
||||
'id' => (int) $activity->id
|
||||
];
|
||||
|
||||
Event::fire('flarum.api.serialize.activity', [&$serialized]);
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
}
|
62
src/Api/Serializers/BaseSerializer.php
Normal file
62
src/Api/Serializers/BaseSerializer.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Tobscure\JsonApi\SerializerAbstract;
|
||||
use Flarum\Api\Events\SerializeAttributes;
|
||||
use Flarum\Api\Events\SerializeRelationship;
|
||||
use Flarum\Core\Support\Actor;
|
||||
|
||||
/**
|
||||
* A base serializer to call Flarum events at common serialization points.
|
||||
*/
|
||||
abstract class BaseSerializer extends SerializerAbstract
|
||||
{
|
||||
/**
|
||||
* The actor who is requesting the serialized objects.
|
||||
*
|
||||
* @var \Flarum\Core\Support\Actor
|
||||
*/
|
||||
protected static $actor;
|
||||
|
||||
/**
|
||||
* Set the actor who is requesting the serialized objects.
|
||||
*
|
||||
* @param \Flarum\Core\Support\Actor $actor
|
||||
* @return void
|
||||
*/
|
||||
public static function setActor(Actor $actor)
|
||||
{
|
||||
static::$actor = $actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire an event to allow custom serialization of attributes.
|
||||
*
|
||||
* @param mixed $model The model to serialize.
|
||||
* @param array $attributes Attributes that have already been serialized.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributesEvent($model, $attributes = [])
|
||||
{
|
||||
event(new SerializeAttributes($this, $model, $attributes));
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire an event to allow for custom links and includes.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $arguments
|
||||
* @return void
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if ($link = starts_with($name, 'link') || starts_with($name, 'include')) {
|
||||
$model = isset($arguments[0]) ? $arguments[0] : null;
|
||||
$relations = isset($arguments[1]) ? $arguments[1] : null;
|
||||
$type = $link ? 'link' : 'include';
|
||||
$name = substr($name, strlen($type));
|
||||
return event(new SerializeRelationship($this, $model, $type, $name, $relations), null, true);
|
||||
}
|
||||
}
|
||||
}
|
44
src/Api/Serializers/DiscussionBasicSerializer.php
Normal file
44
src/Api/Serializers/DiscussionBasicSerializer.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\Discussion;
|
||||
|
||||
class DiscussionBasicSerializer extends BaseSerializer
|
||||
{
|
||||
/**
|
||||
* The resource type.
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'discussions';
|
||||
|
||||
/**
|
||||
* Serialize attributes of a Discussion model for JSON output.
|
||||
*
|
||||
* @param Discussion $discussion The Discussion model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(Discussion $discussion)
|
||||
{
|
||||
$attributes = [
|
||||
'id' => (int) $discussion->id,
|
||||
'title' => $discussion->title,
|
||||
];
|
||||
|
||||
return $this->attributesEvent($discussion, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL templates where this resource and its related resources can
|
||||
* be accessed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function href()
|
||||
{
|
||||
$href = [
|
||||
'discussions' => $this->action('DiscussionsController@show', ['id' => '{discussions.id}']),
|
||||
'posts' => $this->action('PostsController@indexForDiscussion', ['id' => '{discussions.id}'])
|
||||
];
|
||||
|
||||
return $this->hrefEvent($href);
|
||||
}
|
||||
}
|
145
src/Api/Serializers/DiscussionSerializer.php
Normal file
145
src/Api/Serializers/DiscussionSerializer.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\Discussion;
|
||||
use Flarum\Core\Models\DiscussionState;
|
||||
|
||||
class DiscussionSerializer extends DiscussionBasicSerializer
|
||||
{
|
||||
/**
|
||||
* Default relations to include.
|
||||
* @var array
|
||||
*/
|
||||
protected $include = ['startUser', 'lastUser'];
|
||||
|
||||
/**
|
||||
* Serialize attributes of a Discussion model for JSON output.
|
||||
*
|
||||
* @param Discussion $discussion The Discussion model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(Discussion $discussion)
|
||||
{
|
||||
$attributes = parent::attributes($discussion);
|
||||
|
||||
$user = static::$actor->getUser();
|
||||
$state = $discussion->stateFor($user);
|
||||
|
||||
$attributes += [
|
||||
'commentsCount' => (int) $discussion->comments_count,
|
||||
'startTime' => $discussion->start_time->toRFC3339String(),
|
||||
'lastTime' => $discussion->last_time ? $discussion->last_time->toRFC3339String() : null,
|
||||
'lastPostNumber' => $discussion->last_post_number,
|
||||
'canReply' => $discussion->can($user, 'reply'),
|
||||
'canEdit' => $discussion->can($user, 'edit'),
|
||||
'canDelete' => $discussion->can($user, 'delete'),
|
||||
|
||||
'readTime' => $state && $state->read_time ? $state->read_time->toRFC3339String() : null,
|
||||
'readNumber' => $state ? (int) $state->read_number : 0
|
||||
];
|
||||
|
||||
$this->attributesEvent($discussion, $attributes);
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection containing a discussion's viewable post IDs.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @return Tobscure\JsonApi\Collection
|
||||
*/
|
||||
public function linkPosts(Discussion $discussion)
|
||||
{
|
||||
$user = static::$actor->getUser();
|
||||
|
||||
return (new PostBasicSerializer)->collection($discussion->posts()->whereCan($user, 'view')->orderBy('time', 'asc')->ids());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection containing a discussion's viewable posts. Assumes that
|
||||
* the discussion model's posts attributes has been filled.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Collection
|
||||
*/
|
||||
public function includePosts(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new PostSerializer($relations))->collection($discussion->posts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection containing a discussion's relevant posts. Assumes that
|
||||
* the discussion model's relevantPosts attributes has been filled (this
|
||||
* happens in the DiscussionFinder.)
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Collection
|
||||
*/
|
||||
public function includeRelevantPosts(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new PostBasicSerializer($relations))->collection($discussion->relevantPosts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a discussion's start user.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeStartUser(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new UserBasicSerializer($relations))->resource($discussion->startUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a discussion's starting post.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeStartPost(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new PostBasicSerializer($relations))->resource($discussion->startPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a discussion's last user.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeLastUser(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new UserBasicSerializer($relations))->resource($discussion->lastUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a discussion's last post.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeLastPost(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new PostBasicSerializer($relations))->resource($discussion->lastPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a discussion's list of posts that have been
|
||||
* added during this request.
|
||||
*
|
||||
* @param Discussion $discussion
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Collection
|
||||
*/
|
||||
public function includeAddedPosts(Discussion $discussion, $relations)
|
||||
{
|
||||
return (new PostBasicSerializer($relations))->collection($discussion->getAddedPosts());
|
||||
}
|
||||
}
|
48
src/Api/Serializers/GroupSerializer.php
Normal file
48
src/Api/Serializers/GroupSerializer.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\Group;
|
||||
|
||||
class GroupSerializer extends BaseSerializer
|
||||
{
|
||||
/**
|
||||
* The name to use for Flarum events.
|
||||
* @var string
|
||||
*/
|
||||
protected static $eventName = 'Group';
|
||||
|
||||
/**
|
||||
* The resource type.
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'groups';
|
||||
|
||||
/**
|
||||
* Serialize attributes of a Group model for JSON output.
|
||||
*
|
||||
* @param Group $group The Group model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(Group $group)
|
||||
{
|
||||
$attributes = [
|
||||
'id' => (int) $group->id,
|
||||
'name' => $group->name
|
||||
];
|
||||
|
||||
return $this->attributesEvent($group, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL templates where this resource and its related resources can
|
||||
* be accessed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function href()
|
||||
{
|
||||
return [
|
||||
'groups' => $this->action('GroupsController@show', ['id' => '{groups.id}']),
|
||||
'users' => $this->action('UsersController@indexForGroup', ['id' => '{groups.id}'])
|
||||
];
|
||||
}
|
||||
}
|
90
src/Api/Serializers/PostBasicSerializer.php
Normal file
90
src/Api/Serializers/PostBasicSerializer.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\Post;
|
||||
|
||||
class PostBasicSerializer extends BaseSerializer
|
||||
{
|
||||
/**
|
||||
* The name to use for Flarum events.
|
||||
* @var string
|
||||
*/
|
||||
protected static $eventName = 'PostBasic';
|
||||
|
||||
/**
|
||||
* The resource type.
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'posts';
|
||||
|
||||
/**
|
||||
* Default relations to link.
|
||||
* @var array
|
||||
*/
|
||||
protected $link = ['discussion'];
|
||||
|
||||
/**
|
||||
* Default relations to include.
|
||||
* @var array
|
||||
*/
|
||||
protected $include = ['user'];
|
||||
|
||||
/**
|
||||
* Serialize attributes of a Post model for JSON output.
|
||||
*
|
||||
* @param Post $post The Post model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(Post $post)
|
||||
{
|
||||
$attributes = [
|
||||
'id' => (int) $post->id,
|
||||
'number' => (int) $post->number,
|
||||
'time' => $post->time->toRFC3339String(),
|
||||
'type' => $post->type
|
||||
];
|
||||
|
||||
if ($post->type === 'comment') {
|
||||
$attributes['content'] = str_limit($post->content, 200);
|
||||
} else {
|
||||
$attributes['content'] = json_encode($post->content);
|
||||
}
|
||||
|
||||
return $this->attributesEvent($post, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL templates where this resource and its related resources can
|
||||
* be accessed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function href()
|
||||
{
|
||||
return [
|
||||
'posts' => $this->action('PostsController@show', ['id' => '{posts.id}'])
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's user.
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeUser(Post $post, $relations)
|
||||
{
|
||||
return (new UserBasicSerializer($relations))->resource($post->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's discussion ID.
|
||||
*
|
||||
* @param Post $post
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function linkDiscussion(Post $post)
|
||||
{
|
||||
return (new DiscussionBasicSerializer)->resource($post->discussion_id);
|
||||
}
|
||||
}
|
108
src/Api/Serializers/PostSerializer.php
Normal file
108
src/Api/Serializers/PostSerializer.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\Post;
|
||||
use Flarum\Core\Models\User;
|
||||
|
||||
class PostSerializer extends PostBasicSerializer
|
||||
{
|
||||
/**
|
||||
* Default relations to link.
|
||||
* @var array
|
||||
*/
|
||||
protected $link = ['discussion'];
|
||||
|
||||
/**
|
||||
* Default relations to include.
|
||||
* @var array
|
||||
*/
|
||||
protected $include = ['user', 'editUser', 'hideUser'];
|
||||
|
||||
/**
|
||||
* Serialize attributes of a Post model for JSON output.
|
||||
*
|
||||
* @param Post $post The Post model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(Post $post)
|
||||
{
|
||||
$attributes = parent::attributes($post);
|
||||
$user = static::$actor->getUser();
|
||||
|
||||
unset($attributes['content']);
|
||||
|
||||
$canEdit = $post->can($user, 'edit');
|
||||
|
||||
if ($post->type === 'comment') {
|
||||
$attributes['contentHtml'] = $post->content_html;
|
||||
if ($canEdit) {
|
||||
$attributes['content'] = $post->content;
|
||||
}
|
||||
} else {
|
||||
$attributes['content'] = json_encode($post->content);
|
||||
}
|
||||
|
||||
if ($post->edit_time) {
|
||||
$attributes['editTime'] = $post->edit_time->toRFC3339String();
|
||||
}
|
||||
|
||||
if ($post->hide_time) {
|
||||
$attributes['isHidden'] = true;
|
||||
$attributes['hideTime'] = $post->hide_time->toRFC3339String();
|
||||
}
|
||||
|
||||
$attributes += [
|
||||
'canEdit' => $canEdit,
|
||||
'canDelete' => $post->can($user, 'delete')
|
||||
];
|
||||
|
||||
return $this->attributesEvent($post, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's user.
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeUser(Post $post, $relations = [])
|
||||
{
|
||||
return (new UserSerializer($relations))->resource($post->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's discussion.
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeDiscussion(Post $post, $relations = [])
|
||||
{
|
||||
return (new DiscussionBasicSerializer($relations))->resource($post->discussion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's edit user.
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeEditUser(Post $post, $relations = [])
|
||||
{
|
||||
return (new UserBasicSerializer($relations))->resource($post->editUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's hide user.
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeHideUser(Post $post, $relations = [])
|
||||
{
|
||||
return (new UserBasicSerializer($relations))->resource($post->hideUser);
|
||||
}
|
||||
}
|
50
src/Api/Serializers/UserBasicSerializer.php
Normal file
50
src/Api/Serializers/UserBasicSerializer.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\User;
|
||||
|
||||
class UserBasicSerializer extends BaseSerializer
|
||||
{
|
||||
/**
|
||||
* The name to use for Flarum events.
|
||||
* @var string
|
||||
*/
|
||||
protected static $eventName = 'UserBasic';
|
||||
|
||||
/**
|
||||
* The resource type.
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'users';
|
||||
|
||||
/**
|
||||
* Serialize attributes of a User model for JSON output.
|
||||
*
|
||||
* @param User $user The User model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(User $user)
|
||||
{
|
||||
$attributes = [
|
||||
'id' => (int) $user->id,
|
||||
'username' => $user->username,
|
||||
'avatarUrl' => $user->avatar_url
|
||||
];
|
||||
|
||||
return $this->attributesEvent($user, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL templates where this resource and its related resources can
|
||||
* be accessed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function href()
|
||||
{
|
||||
$href = [
|
||||
'users' => $this->action('UsersController@show', ['id' => '{users.id}'])
|
||||
];
|
||||
|
||||
return $this->hrefEvent($href);
|
||||
}
|
||||
}
|
69
src/Api/Serializers/UserSerializer.php
Normal file
69
src/Api/Serializers/UserSerializer.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core\Models\User;
|
||||
|
||||
class UserSerializer extends UserBasicSerializer
|
||||
{
|
||||
/**
|
||||
* The name to use for Flarum events.
|
||||
* @var string
|
||||
*/
|
||||
protected static $eventName = 'User';
|
||||
|
||||
/**
|
||||
* Default relations to include.
|
||||
* @var array
|
||||
*/
|
||||
protected $include = ['groups'];
|
||||
|
||||
/**
|
||||
* Serialize attributes of a User model for JSON output.
|
||||
*
|
||||
* @param User $user The User model to serialize.
|
||||
* @return array
|
||||
*/
|
||||
protected function attributes(User $user)
|
||||
{
|
||||
$attributes = parent::attributes($user);
|
||||
|
||||
$actorUser = static::$actor->getUser();
|
||||
$canEdit = $user->can($actorUser, 'edit');
|
||||
|
||||
$attributes += [
|
||||
'joinTime' => $user->join_time ? $user->join_time->toRFC3339String() : null,
|
||||
'lastSeenTime' => $user->last_seen_time ? $user->last_seen_time->toRFC3339String() : null,
|
||||
'discussionsCount' => (int) $user->discussions_count,
|
||||
'postsCount' => (int) $user->posts_count,
|
||||
'canEdit' => $canEdit,
|
||||
'canDelete' => $user->can($actorUser, 'delete'),
|
||||
];
|
||||
|
||||
if ($canEdit) {
|
||||
$attributes += [
|
||||
'isActivated' => $user->is_activated,
|
||||
'email' => $user->email,
|
||||
'isConfirmed' => $user->is_confirmed
|
||||
];
|
||||
}
|
||||
|
||||
if ($user->id === $actorUser->id) {
|
||||
$attributes += [
|
||||
'readTime' => $user->read_time ? $user->read_time->toRFC3339String() : null,
|
||||
];
|
||||
}
|
||||
|
||||
return $this->attributesEvent($user, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection containing a user's groups.
|
||||
*
|
||||
* @param User $user
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Collection
|
||||
*/
|
||||
protected function includeGroups(User $user, $relations)
|
||||
{
|
||||
return (new GroupSerializer($relations))->collection($user->groups);
|
||||
}
|
||||
}
|
182
src/Api/routes.php
Normal file
182
src/Api/routes.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
$action = function ($class) {
|
||||
return function () use ($class) {
|
||||
$action = $this->app->make($class);
|
||||
$request = $this->app['request']->instance();
|
||||
$parameters = $this->app['router']->current()->parameters();
|
||||
return $action->handle($request, $parameters);
|
||||
};
|
||||
};
|
||||
|
||||
Route::group(['prefix' => 'api', 'middleware' => 'Flarum\Api\Middleware\LoginWithHeaderMiddleware'], function () use ($action) {
|
||||
|
||||
Route::post('token', [
|
||||
'as' => 'flarum.api.token',
|
||||
'uses' => $action('Flarum\Api\Actions\TokenAction')
|
||||
]);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Users
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// List users
|
||||
Route::get('users', [
|
||||
'as' => 'flarum.api.users.index',
|
||||
'uses' => $action('Flarum\Api\Actions\Users\IndexAction')
|
||||
]);
|
||||
|
||||
// Register a user
|
||||
Route::post('users', [
|
||||
'as' => 'flarum.api.users.create',
|
||||
'uses' => $action('Flarum\Api\Actions\Users\CreateAction')
|
||||
]);
|
||||
|
||||
// Get a single user
|
||||
Route::get('users/{id}', [
|
||||
'as' => 'flarum.api.users.show',
|
||||
'uses' => $action('Flarum\Api\Actions\Users\ShowAction')
|
||||
]);
|
||||
|
||||
// Edit a user
|
||||
Route::put('users/{id}', [
|
||||
'as' => 'flarum.api.users.update',
|
||||
'uses' => $action('Flarum\Api\Actions\Users\UpdateAction')
|
||||
]);
|
||||
|
||||
// Delete a user
|
||||
Route::delete('users/{id}', [
|
||||
'as' => 'flarum.api.users.delete',
|
||||
'uses' => $action('Flarum\Api\Actions\Users\DeleteAction')
|
||||
]);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Activity
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// List activity
|
||||
Route::get('activity', [
|
||||
'as' => 'flarum.api.activity.index',
|
||||
'uses' => $action('Flarum\Api\Actions\Activity\IndexAction')
|
||||
]);
|
||||
|
||||
// List notifications for the current user
|
||||
Route::get('notifications', [
|
||||
'as' => 'flarum.api.notifications.index',
|
||||
'uses' => $action('Flarum\Api\Actions\Notifications\IndexAction')
|
||||
]);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Discussions
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// List discussions
|
||||
Route::get('discussions', [
|
||||
'as' => 'flarum.api.discussions.index',
|
||||
'uses' => $action('Flarum\Api\Actions\Discussions\IndexAction')
|
||||
]);
|
||||
|
||||
// Create a discussion
|
||||
Route::post('discussions', [
|
||||
'as' => 'flarum.api.discussions.create',
|
||||
'uses' => $action('Flarum\Api\Actions\Discussions\CreateAction')
|
||||
]);
|
||||
|
||||
// Show a single discussion
|
||||
Route::get('discussions/{id}', [
|
||||
'as' => 'flarum.api.discussions.show',
|
||||
'uses' => $action('Flarum\Api\Actions\Discussions\ShowAction')
|
||||
]);
|
||||
|
||||
// Edit a discussion
|
||||
Route::put('discussions/{id}', [
|
||||
'as' => 'flarum.api.discussions.update',
|
||||
'uses' => $action('Flarum\Api\Actions\Discussions\UpdateAction')
|
||||
]);
|
||||
|
||||
// Delete a discussion
|
||||
Route::delete('discussions/{id}', [
|
||||
'as' => 'flarum.api.discussions.delete',
|
||||
'uses' => $action('Flarum\Api\Actions\Discussions\DeleteAction')
|
||||
]);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Posts
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// List posts, usually for a discussion
|
||||
Route::get('posts', [
|
||||
'as' => 'flarum.api.posts.index',
|
||||
'uses' => $action('Flarum\Api\Actions\Posts\IndexAction')
|
||||
]);
|
||||
|
||||
// Create a post
|
||||
// @todo consider 'discussions/{id}/links/posts'?
|
||||
Route::post('posts', [
|
||||
'as' => 'flarum.api.posts.create',
|
||||
'uses' => $action('Flarum\Api\Actions\Posts\CreateAction')
|
||||
]);
|
||||
|
||||
// Show a single or multiple posts by ID
|
||||
Route::get('posts/{id}', [
|
||||
'as' => 'flarum.api.posts.show',
|
||||
'uses' => $action('Flarum\Api\Actions\Posts\ShowAction')
|
||||
]);
|
||||
|
||||
// Edit a post
|
||||
Route::put('posts/{id}', [
|
||||
'as' => 'flarum.api.posts.update',
|
||||
'uses' => $action('Flarum\Api\Actions\Posts\UpdateAction')
|
||||
]);
|
||||
|
||||
// Delete a post
|
||||
Route::delete('posts/{id}', [
|
||||
'as' => 'flarum.api.posts.delete',
|
||||
'uses' => $action('Flarum\Api\Actions\Posts\DeleteAction')
|
||||
]);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Groups
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// List groups
|
||||
Route::get('groups', [
|
||||
'as' => 'flarum.api.groups.index',
|
||||
'uses' => $action('Flarum\Api\Actions\Groups\IndexAction')
|
||||
]);
|
||||
|
||||
// Create a group
|
||||
Route::post('groups', [
|
||||
'as' => 'flarum.api.groups.create',
|
||||
'uses' => $action('Flarum\Api\Actions\Groups\CreateAction')
|
||||
]);
|
||||
|
||||
// Show a single group
|
||||
Route::get('groups/{id}', [
|
||||
'as' => 'flarum.api.groups.show',
|
||||
'uses' => $action('Flarum\Api\Actions\Groups\ShowAction')
|
||||
]);
|
||||
|
||||
// Edit a group
|
||||
Route::put('groups/{id}', [
|
||||
'as' => 'flarum.api.groups.update',
|
||||
'uses' => $action('Flarum\Api\Actions\Groups\UpdateAction')
|
||||
]);
|
||||
|
||||
// Delete a group
|
||||
Route::delete('groups/{id}', [
|
||||
'as' => 'flarum.api.groups.delete',
|
||||
'uses' => $action('Flarum\Api\Actions\Groups\DeleteAction')
|
||||
]);
|
||||
|
||||
});
|
Reference in New Issue
Block a user