mirror of
https://github.com/flarum/core.git
synced 2025-08-05 16:07:34 +02:00
feat: context current endpoint helpers
This commit is contained in:
@@ -42,7 +42,7 @@ class FlagResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
public function query(Context $context): object
|
public function query(Context $context): object
|
||||||
{
|
{
|
||||||
if ($context->collection instanceof self && $context->endpoint instanceof Endpoint\Index) {
|
if ($context->listing(self::class)) {
|
||||||
$query = Flag::query()->groupBy('post_id');
|
$query = Flag::query()->groupBy('post_id');
|
||||||
|
|
||||||
$this->scope($query, $context);
|
$this->scope($query, $context);
|
||||||
@@ -60,7 +60,7 @@ class FlagResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
public function newModel(Context $context): object
|
public function newModel(Context $context): object
|
||||||
{
|
{
|
||||||
if ($context->collection instanceof self && $context->endpoint instanceof Endpoint\Create) {
|
if ($context->creating(self::class)) {
|
||||||
Flag::unguard();
|
Flag::unguard();
|
||||||
|
|
||||||
return Flag::query()->firstOrNew([
|
return Flag::query()->firstOrNew([
|
||||||
@@ -118,7 +118,7 @@ class FlagResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
Schema\Relationship\ToOne::make('post')
|
Schema\Relationship\ToOne::make('post')
|
||||||
->includable()
|
->includable()
|
||||||
->writable(fn (Flag $flag, FlarumContext $context) => $context->endpoint instanceof Endpoint\Create)
|
->writable(fn (Flag $flag, FlarumContext $context) => $context->creating())
|
||||||
->set(function (Flag $flag, Post $post, FlarumContext $context) {
|
->set(function (Flag $flag, Post $post, FlarumContext $context) {
|
||||||
if (! ($post instanceof CommentPost)) {
|
if (! ($post instanceof CommentPost)) {
|
||||||
throw new InvalidParameterException;
|
throw new InvalidParameterException;
|
||||||
|
@@ -13,7 +13,7 @@ class UserResourceFields
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
Schema\Str::make('subscription')
|
Schema\Str::make('subscription')
|
||||||
->writable(fn (Discussion $discussion, Context $context) => $context->endpoint instanceof Endpoint\Update && ! $context->getActor()->isGuest())
|
->writable(fn (Discussion $discussion, Context $context) => $context->updating() && ! $context->getActor()->isGuest())
|
||||||
->nullable()
|
->nullable()
|
||||||
->get(fn (Discussion $discussion) => $discussion->state?->subscription)
|
->get(fn (Discussion $discussion) => $discussion->state?->subscription)
|
||||||
->set(function (Discussion $discussion, ?string $subscription, Context $context) {
|
->set(function (Discussion $discussion, ?string $subscription, Context $context) {
|
||||||
|
@@ -35,10 +35,7 @@ class TagResource extends AbstractDatabaseResource
|
|||||||
{
|
{
|
||||||
$query->whereVisibleTo($context->getActor());
|
$query->whereVisibleTo($context->getActor());
|
||||||
|
|
||||||
if ($context->collection instanceof self && (
|
if ($context->listing(self::class) || $context->showing(self::class)) {
|
||||||
$context->endpoint instanceof Endpoint\Index
|
|
||||||
|| $context->endpoint instanceof Endpoint\Show
|
|
||||||
)) {
|
|
||||||
$query->withStateFor($context->getActor());
|
$query->withStateFor($context->getActor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,7 +140,7 @@ class TagResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
public function saving(object $model, Context $context): ?object
|
public function saving(object $model, Context $context): ?object
|
||||||
{
|
{
|
||||||
if (! $context->endpoint instanceof Endpoint\Create) {
|
if (! $context->creating(self::class)) {
|
||||||
$this->events->dispatch(
|
$this->events->dispatch(
|
||||||
new Saving($model, $context->getActor(), $context->body())
|
new Saving($model, $context->getActor(), $context->body())
|
||||||
);
|
);
|
||||||
|
@@ -7,13 +7,23 @@ use Flarum\Search\SearchResults;
|
|||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Tobyz\JsonApiServer\Context as BaseContext;
|
use Tobyz\JsonApiServer\Context as BaseContext;
|
||||||
|
use Tobyz\JsonApiServer\Resource\Collection;
|
||||||
use Tobyz\JsonApiServer\Resource\Resource;
|
use Tobyz\JsonApiServer\Resource\Resource;
|
||||||
|
|
||||||
class Context extends BaseContext
|
class Context extends BaseContext
|
||||||
{
|
{
|
||||||
protected ?SearchResults $search = null;
|
protected ?SearchResults $search = null;
|
||||||
protected int|string|null $modelId = null;
|
protected int|string|null $modelId = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data passed internally when reusing resource endpoint logic.
|
||||||
|
*/
|
||||||
protected array $internal = [];
|
protected array $internal = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters mutated on the current instance.
|
||||||
|
* Useful for passing information between different field callbacks.
|
||||||
|
*/
|
||||||
protected array $parameters = [];
|
protected array $parameters = [];
|
||||||
|
|
||||||
public function withModelId(int|string|null $id): static
|
public function withModelId(int|string|null $id): static
|
||||||
@@ -67,4 +77,29 @@ class Context extends BaseContext
|
|||||||
{
|
{
|
||||||
return $this->parameters[$key] ?? $default;
|
return $this->parameters[$key] ?? $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function creating(string|null $resource = null): bool
|
||||||
|
{
|
||||||
|
return $this->endpoint instanceof Endpoint\Create && (! $resource || is_a($this->collection, $resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updating(string|null $resource = null): bool
|
||||||
|
{
|
||||||
|
return $this->endpoint instanceof Endpoint\Update && (! $resource || is_a($this->collection, $resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleting(string|null $resource = null): bool
|
||||||
|
{
|
||||||
|
return $this->endpoint instanceof Endpoint\Delete && (! $resource || is_a($this->collection, $resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showing(string|null $resource = null): bool
|
||||||
|
{
|
||||||
|
return $this->endpoint instanceof Endpoint\Show && (! $resource || is_a($this->collection, $resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listing(string|null $resource = null): bool
|
||||||
|
{
|
||||||
|
return $this->endpoint instanceof Endpoint\Index && (! $resource || is_a($this->collection, $resource));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ class AccessTokenResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
public function newModel(\Tobyz\JsonApiServer\Context $context): object
|
public function newModel(\Tobyz\JsonApiServer\Context $context): object
|
||||||
{
|
{
|
||||||
if ($context->endpoint instanceof Endpoint\Create && $context->collection instanceof self) {
|
if ($context->creating(self::class)) {
|
||||||
$token = DeveloperAccessToken::make($context->getActor()->id);
|
$token = DeveloperAccessToken::make($context->getActor()->id);
|
||||||
$token->last_activity_at = null;
|
$token->last_activity_at = null;
|
||||||
return $token;
|
return $token;
|
||||||
|
@@ -105,7 +105,7 @@ class DiscussionResource extends AbstractDatabaseResource
|
|||||||
Schema\Str::make('title')
|
Schema\Str::make('title')
|
||||||
->requiredOnCreate()
|
->requiredOnCreate()
|
||||||
->writable(function (Discussion $discussion, Context $context) {
|
->writable(function (Discussion $discussion, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create
|
return $context->creating()
|
||||||
|| $context->getActor()->can('rename', $discussion);
|
|| $context->getActor()->can('rename', $discussion);
|
||||||
})
|
})
|
||||||
->minLength(3)
|
->minLength(3)
|
||||||
@@ -145,7 +145,7 @@ class DiscussionResource extends AbstractDatabaseResource
|
|||||||
Schema\Boolean::make('isHidden')
|
Schema\Boolean::make('isHidden')
|
||||||
->visible(fn (Discussion $discussion) => $discussion->hidden_at !== null)
|
->visible(fn (Discussion $discussion) => $discussion->hidden_at !== null)
|
||||||
->writable(function (Discussion $discussion, Context $context) {
|
->writable(function (Discussion $discussion, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Update
|
return $context->updating()
|
||||||
&& $context->getActor()->can('hide', $discussion);
|
&& $context->getActor()->can('hide', $discussion);
|
||||||
})
|
})
|
||||||
->set(function (Discussion $discussion, bool $value, Context $context) {
|
->set(function (Discussion $discussion, bool $value, Context $context) {
|
||||||
@@ -168,7 +168,7 @@ class DiscussionResource extends AbstractDatabaseResource
|
|||||||
return $discussion->state?->last_read_post_number;
|
return $discussion->state?->last_read_post_number;
|
||||||
})
|
})
|
||||||
->writable(function (Discussion $discussion, Context $context) {
|
->writable(function (Discussion $discussion, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Update;
|
return $context->updating();
|
||||||
})
|
})
|
||||||
->set(function (Discussion $discussion, int $value, Context $context) {
|
->set(function (Discussion $discussion, int $value, Context $context) {
|
||||||
if ($readNumber = Arr::get($context->body(), 'data.attributes.lastReadPostNumber')) {
|
if ($readNumber = Arr::get($context->body(), 'data.attributes.lastReadPostNumber')) {
|
||||||
@@ -194,11 +194,11 @@ class DiscussionResource extends AbstractDatabaseResource
|
|||||||
->type('posts'),
|
->type('posts'),
|
||||||
Schema\Relationship\ToMany::make('posts')
|
Schema\Relationship\ToMany::make('posts')
|
||||||
->withLinkage(function (Context $context) {
|
->withLinkage(function (Context $context) {
|
||||||
return $context->collection instanceof self && $context->endpoint instanceof Endpoint\Show;
|
return $context->showing(self::class);
|
||||||
})
|
})
|
||||||
->includable()
|
->includable()
|
||||||
->get(function (Discussion $discussion, Context $context) {
|
->get(function (Discussion $discussion, Context $context) {
|
||||||
$showingDiscussion = $context->collection instanceof self && $context->endpoint instanceof Endpoint\Show;
|
$showingDiscussion = $context->showing(self::class);
|
||||||
|
|
||||||
if (! $showingDiscussion) {
|
if (! $showingDiscussion) {
|
||||||
return fn () => $discussion->posts->all();
|
return fn () => $discussion->posts->all();
|
||||||
@@ -235,7 +235,7 @@ class DiscussionResource extends AbstractDatabaseResource
|
|||||||
return $allPosts;
|
return $allPosts;
|
||||||
}),
|
}),
|
||||||
Schema\Relationship\ToOne::make('mostRelevantPost')
|
Schema\Relationship\ToOne::make('mostRelevantPost')
|
||||||
->visible(fn (Discussion $model, Context $context) => $context->endpoint instanceof Endpoint\Index)
|
->visible(fn (Discussion $model, Context $context) => $context->listing())
|
||||||
->includable()
|
->includable()
|
||||||
->type('posts'),
|
->type('posts'),
|
||||||
Schema\Relationship\ToOne::make('hideUser')
|
Schema\Relationship\ToOne::make('hideUser')
|
||||||
@@ -284,7 +284,7 @@ class DiscussionResource extends AbstractDatabaseResource
|
|||||||
/** @param Discussion $model */
|
/** @param Discussion $model */
|
||||||
protected function saveModel(Model $model, \Tobyz\JsonApiServer\Context $context): void
|
protected function saveModel(Model $model, \Tobyz\JsonApiServer\Context $context): void
|
||||||
{
|
{
|
||||||
if ($context->endpoint instanceof Endpoint\Create) {
|
if ($context->creating()) {
|
||||||
$model->newQuery()->getConnection()->transaction(function () use ($model, $context) {
|
$model->newQuery()->getConnection()->transaction(function () use ($model, $context) {
|
||||||
$model->save();
|
$model->save();
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ class NotificationResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
public function query(\Tobyz\JsonApiServer\Context $context): object
|
public function query(\Tobyz\JsonApiServer\Context $context): object
|
||||||
{
|
{
|
||||||
if ($context->collection instanceof self && $context->endpoint instanceof Endpoint\Index) {
|
if ($context->listing(self::class)) {
|
||||||
/** @var Pagination $pagination */
|
/** @var Pagination $pagination */
|
||||||
$pagination = ($context->endpoint->paginationResolver)($context);
|
$pagination = ($context->endpoint->paginationResolver)($context);
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ class PostResource extends AbstractDatabaseResource
|
|||||||
|
|
||||||
public function newModel(\Tobyz\JsonApiServer\Context $context): object
|
public function newModel(\Tobyz\JsonApiServer\Context $context): object
|
||||||
{
|
{
|
||||||
if ($context->endpoint instanceof Endpoint\Create && $context->collection instanceof self) {
|
if ($context->creating(self::class)) {
|
||||||
$post = new CommentPost();
|
$post = new CommentPost();
|
||||||
|
|
||||||
$post->user_id = $context->getActor()->id;
|
$post->user_id = $context->getActor()->id;
|
||||||
@@ -149,7 +149,7 @@ class PostResource extends AbstractDatabaseResource
|
|||||||
Schema\Integer::make('number'),
|
Schema\Integer::make('number'),
|
||||||
Schema\DateTime::make('createdAt')
|
Schema\DateTime::make('createdAt')
|
||||||
->writable(function (Post $post, Context $context) {
|
->writable(function (Post $post, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create
|
return $context->creating()
|
||||||
&& $context->getActor()->isAdmin();
|
&& $context->getActor()->isAdmin();
|
||||||
})
|
})
|
||||||
->default(fn () => Carbon::now()),
|
->default(fn () => Carbon::now()),
|
||||||
@@ -159,9 +159,9 @@ class PostResource extends AbstractDatabaseResource
|
|||||||
Schema\Str::make('content')
|
Schema\Str::make('content')
|
||||||
->requiredOnCreate()
|
->requiredOnCreate()
|
||||||
->writable(function (Post $post, Context $context) {
|
->writable(function (Post $post, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create || (
|
return $context->creating() || (
|
||||||
$post instanceof CommentPost
|
$post instanceof CommentPost
|
||||||
&& $context->endpoint instanceof Endpoint\Update
|
&& $context->updating()
|
||||||
&& $context->getActor()->can('edit', $post)
|
&& $context->getActor()->can('edit', $post)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -172,9 +172,9 @@ class PostResource extends AbstractDatabaseResource
|
|||||||
})
|
})
|
||||||
->set(function (Post $post, string $value, Context $context) {
|
->set(function (Post $post, string $value, Context $context) {
|
||||||
if ($post instanceof CommentPost) {
|
if ($post instanceof CommentPost) {
|
||||||
if ($context->endpoint instanceof Endpoint\Create) {
|
if ($context->creating()) {
|
||||||
$post->setContentAttribute($value, $context->getActor());
|
$post->setContentAttribute($value, $context->getActor());
|
||||||
} elseif ($context->endpoint instanceof Endpoint\Update) {
|
} elseif ($context->updating()) {
|
||||||
$post->revise($value, $context->getActor());
|
$post->revise($value, $context->getActor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ class PostResource extends AbstractDatabaseResource
|
|||||||
Schema\Boolean::make('isHidden')
|
Schema\Boolean::make('isHidden')
|
||||||
->visible(fn (Post $post) => $post->hidden_at !== null)
|
->visible(fn (Post $post) => $post->hidden_at !== null)
|
||||||
->writable(function (Post $post, Context $context) {
|
->writable(function (Post $post, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Update
|
return $context->updating()
|
||||||
&& $context->getActor()->can('hide', $post);
|
&& $context->getActor()->can('hide', $post);
|
||||||
})
|
})
|
||||||
->set(function (Post $post, bool $value, Context $context) {
|
->set(function (Post $post, bool $value, Context $context) {
|
||||||
|
@@ -124,7 +124,7 @@ class UserResource extends AbstractDatabaseResource
|
|||||||
->minLength(3)
|
->minLength(3)
|
||||||
->maxLength(30)
|
->maxLength(30)
|
||||||
->writable(function (User $user, Context $context) {
|
->writable(function (User $user, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create
|
return $context->creating()
|
||||||
|| $context->getActor()->can('editCredentials', $user);
|
|| $context->getActor()->can('editCredentials', $user);
|
||||||
})
|
})
|
||||||
->set(function (User $user, string $value) {
|
->set(function (User $user, string $value) {
|
||||||
@@ -146,7 +146,7 @@ class UserResource extends AbstractDatabaseResource
|
|||||||
|| $context->getActor()->id === $user->id;
|
|| $context->getActor()->id === $user->id;
|
||||||
})
|
})
|
||||||
->writable(function (User $user, Context $context) {
|
->writable(function (User $user, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create
|
return $context->creating()
|
||||||
|| $context->getActor()->can('editCredentials', $user)
|
|| $context->getActor()->can('editCredentials', $user)
|
||||||
|| $context->getActor()->id === $user->id;
|
|| $context->getActor()->id === $user->id;
|
||||||
})
|
})
|
||||||
@@ -171,9 +171,7 @@ class UserResource extends AbstractDatabaseResource
|
|||||||
})
|
})
|
||||||
->writable(fn (User $user, Context $context) => $context->getActor()->isAdmin())
|
->writable(fn (User $user, Context $context) => $context->getActor()->isAdmin())
|
||||||
->set(function (User $user, $value, Context $context) {
|
->set(function (User $user, $value, Context $context) {
|
||||||
$editing = $context->endpoint instanceof Endpoint\Update;
|
if (! empty($value) && ($context->updating() || $context->getActor()->isAdmin())) {
|
||||||
|
|
||||||
if (! empty($value) && ($editing || $context->getActor()->isAdmin())) {
|
|
||||||
$user->activate();
|
$user->activate();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -185,7 +183,7 @@ class UserResource extends AbstractDatabaseResource
|
|||||||
->minLength(8)
|
->minLength(8)
|
||||||
->visible(false)
|
->visible(false)
|
||||||
->writable(function (User $user, Context $context) {
|
->writable(function (User $user, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create
|
return $context->creating()
|
||||||
|| $context->getActor()->can('editCredentials', $user);
|
|| $context->getActor()->can('editCredentials', $user);
|
||||||
})
|
})
|
||||||
->set(function (User $user, ?string $value) {
|
->set(function (User $user, ?string $value) {
|
||||||
@@ -195,7 +193,7 @@ class UserResource extends AbstractDatabaseResource
|
|||||||
Schema\Str::make('token')
|
Schema\Str::make('token')
|
||||||
->visible(false)
|
->visible(false)
|
||||||
->writable(function (User $user, Context $context) {
|
->writable(function (User $user, Context $context) {
|
||||||
return $context->endpoint instanceof Endpoint\Create;
|
return $context->creating();
|
||||||
})
|
})
|
||||||
->set(function (User $user, ?string $value, Context $context) {
|
->set(function (User $user, ?string $value, Context $context) {
|
||||||
if ($value) {
|
if ($value) {
|
||||||
@@ -273,7 +271,7 @@ class UserResource extends AbstractDatabaseResource
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
Schema\Relationship\ToMany::make('groups')
|
Schema\Relationship\ToMany::make('groups')
|
||||||
->writable(fn (User $user, Context $context) => $context->endpoint instanceof Endpoint\Update && $context->getActor()->can('editGroups', $user))
|
->writable(fn (User $user, Context $context) => $context->updating() && $context->getActor()->can('editGroups', $user))
|
||||||
->includable()
|
->includable()
|
||||||
->get(function (User $user, Context $context) {
|
->get(function (User $user, Context $context) {
|
||||||
if ($context->getActor()->can('viewHiddenGroups')) {
|
if ($context->getActor()->can('viewHiddenGroups')) {
|
||||||
|
Reference in New Issue
Block a user