1
0
mirror of https://github.com/flarum/core.git synced 2025-08-03 15:07:53 +02:00

test: phpstan

This commit is contained in:
Sami Mazouz
2024-03-08 18:27:18 +01:00
parent 4a9985da8e
commit e0f8f53b7b
42 changed files with 223 additions and 279 deletions

View File

@@ -28,6 +28,9 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Tobyz\JsonApiServer\Context;
/**
* @extends AbstractDatabaseResource<Flag>
*/
class FlagResource extends AbstractDatabaseResource
{
public function __construct(

View File

@@ -18,7 +18,7 @@ use Flarum\Sticky\Event\DiscussionWasUnstickied;
class DiscussionResourceFields
{
public function __invoke()
public function __invoke(): array
{
return [
Schema\Boolean::make('isSticky')

View File

@@ -17,7 +17,6 @@ class PinStickiedDiscussionsToTop
{
public function __invoke(DatabaseSearchState $state, SearchCriteria $criteria): void
{
return;
if ($criteria->sortIsDefault && ! $state->isFulltextSearch()) {
$query = $state->getQuery();

View File

@@ -31,6 +31,7 @@ use Flarum\Tags\Search\HideHiddenTagsFromAllDiscussionsPage;
use Flarum\Tags\Search\TagSearcher;
use Flarum\Tags\Tag;
use Flarum\Tags\Utf8SlugDriver;
use Illuminate\Database\Eloquent\Builder;
return [
(new Extend\Frontend('forum'))
@@ -107,7 +108,8 @@ return [
function (Endpoint\Index|Endpoint\Show|Endpoint\Create $endpoint) {
return $endpoint
->addDefaultInclude(['tags', 'tags.parent'])
->eagerLoadWhere('tags', function ($query, Context $context) {
->eagerLoadWhere('tags', function (Builder $query, Context $context, array $relations) {
/** @var Builder<Tag> $query */
$query->withStateFor($context->getActor());
});
}

View File

@@ -9,6 +9,7 @@
namespace Flarum\Tags\Api\Resource;
use Flarum\Api\Context as FlarumContext;
use Flarum\Api\Endpoint;
use Flarum\Api\Resource\AbstractDatabaseResource;
use Flarum\Api\Schema;
@@ -21,6 +22,9 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Tobyz\JsonApiServer\Context;
/**
* @extends AbstractDatabaseResource<Tag>
*/
class TagResource extends AbstractDatabaseResource
{
public function __construct(
@@ -107,7 +111,7 @@ class TagResource extends AbstractDatabaseResource
->writable(),
Schema\Boolean::make('isRestricted')
->writableOnUpdate()
->visible(fn (Tag $tag, Context $context) => $context->getActor()->isAdmin()),
->visible(fn (Tag $tag, FlarumContext $context) => $context->getActor()->isAdmin()),
Schema\Str::make('backgroundUrl')
->get(fn (Tag $tag) => $tag->background_path),
Schema\Str::make('backgroundMode'),
@@ -119,14 +123,14 @@ class TagResource extends AbstractDatabaseResource
->get(fn (Tag $tag) => (bool) $tag->parent_id),
Schema\DateTime::make('lastPostedAt'),
Schema\Boolean::make('canStartDiscussion')
->get(fn (Tag $tag, Context $context) => $context->getActor()->can('startDiscussion', $tag)),
->get(fn (Tag $tag, FlarumContext $context) => $context->getActor()->can('startDiscussion', $tag)),
Schema\Boolean::make('canAddToDiscussion')
->get(fn (Tag $tag, Context $context) => $context->getActor()->can('addToDiscussion', $tag)),
->get(fn (Tag $tag, FlarumContext $context) => $context->getActor()->can('addToDiscussion', $tag)),
Schema\Relationship\ToOne::make('parent')
->type('tags')
->includable()
->writable(fn (Tag $tag, Context $context) => (bool) Arr::get($context->body(), 'attributes.isPrimary')),
->writable(fn (Tag $tag, FlarumContext $context) => (bool) Arr::get($context->body(), 'attributes.isPrimary')),
Schema\Relationship\ToMany::make('children')
->type('tags')
->includable(),

View File

@@ -9,6 +9,7 @@
namespace Flarum\Api\Controller;
use Flarum\Api\JsonApi;
use Flarum\Foundation\ValidationException;
use Flarum\Locale\TranslatorInterface;
use Flarum\Settings\SettingsRepositoryInterface;
@@ -23,12 +24,13 @@ class UploadFaviconController extends UploadImageController
protected string $filenamePrefix = 'favicon';
public function __construct(
JsonApi $api,
SettingsRepositoryInterface $settings,
Factory $filesystemFactory,
protected TranslatorInterface $translator,
protected ImageManager $imageManager
) {
parent::__construct($settings, $filesystemFactory);
parent::__construct($api, $settings, $filesystemFactory);
}
protected function makeImage(UploadedFileInterface $file): EncodedImageInterface

View File

@@ -9,6 +9,7 @@
namespace Flarum\Api\Controller;
use Flarum\Api\JsonApi;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Filesystem\Factory;
use Intervention\Image\ImageManager;
@@ -21,11 +22,12 @@ class UploadLogoController extends UploadImageController
protected string $filenamePrefix = 'logo';
public function __construct(
JsonApi $api,
SettingsRepositoryInterface $settings,
Factory $filesystemFactory,
protected ImageManager $imageManager
) {
parent::__construct($settings, $filesystemFactory);
parent::__construct($api, $settings, $filesystemFactory);
}
protected function makeImage(UploadedFileInterface $file): EncodedImageInterface

View File

@@ -12,6 +12,7 @@ namespace Flarum\Api\Endpoint\Concerns;
use Closure;
use Flarum\Http\RequestUtil;
use Tobyz\JsonApiServer\Context;
use Tobyz\JsonApiServer\Resource\AbstractResource;
use Tobyz\JsonApiServer\Schema\Sort;
trait ExtractsListingParams
@@ -109,6 +110,10 @@ trait ExtractsListingParams
public function getAvailableSorts(Context $context): array
{
if (! $context->collection instanceof AbstractResource) {
return [];
}
$asc = collect($context->collection->resolveSorts())
->filter(fn (Sort $field) => $field->isVisible($context))
->pluck('name')

View File

@@ -17,14 +17,8 @@ use Tobyz\JsonApiServer\Context;
trait HasAuthorization
{
/**
* @var bool|(Closure(mixed, Context): bool)
*/
protected bool|Closure $authenticated = false;
/**
* @var null|string|Closure(mixed, Context): string
*/
protected null|string|Closure $ability = null;
protected bool $admin = false;
@@ -67,9 +61,9 @@ trait HasAuthorization
return $this->ability;
}
return (bool) (isset($context->model)
return isset($context->model)
? ($this->ability)($context->model, $context)
: ($this->ability)($context));
: ($this->ability)($context);
}
/**

View File

@@ -9,6 +9,9 @@
namespace Flarum\Api\Endpoint;
/**
* @mixin \Tobyz\JsonApiServer\Endpoint\Endpoint
*/
interface EndpointInterface
{
//

View File

@@ -9,35 +9,22 @@
namespace Flarum\Api\Resource;
use Flarum\Api\Context as FlarumContext;
use Flarum\Api\Resource\Concerns\Bootable;
use Flarum\Api\Resource\Concerns\Extendable;
use Flarum\Api\Resource\Concerns\HasSortMap;
use Flarum\Api\Resource\Contracts\{
Countable,
Creatable,
Deletable,
Findable,
Listable,
Paginatable,
Resource,
Updatable
};
use Flarum\Foundation\DispatchEventsTrait;
use Flarum\User\User;
use Illuminate\Database\Eloquent\Model;
use RuntimeException;
use Tobyz\JsonApiServer\Context;
use Tobyz\JsonApiServer\Laravel\EloquentResource as BaseResource;
abstract class AbstractDatabaseResource extends BaseResource implements
Resource,
Findable,
Listable,
Countable,
Paginatable,
Creatable,
Updatable,
Deletable
{
/**
* @template M of Model
* @extends BaseResource<M, FlarumContext>
*/
abstract class AbstractDatabaseResource extends BaseResource {
use Bootable;
use Extendable;
use HasSortMap;
@@ -47,6 +34,7 @@ abstract class AbstractDatabaseResource extends BaseResource implements
abstract public function model(): string;
/** @inheritDoc */
public function newModel(Context $context): object
{
return new ($this->model());
@@ -97,41 +85,79 @@ abstract class AbstractDatabaseResource extends BaseResource implements
$this->dispatchEventsFor($model, $context->getActor());
}
/**
* @param M $model
* @param FlarumContext $context
* @return M|null
*/
public function creating(object $model, Context $context): ?object
{
return $model;
}
/**
* @param M $model
* @param FlarumContext $context
* @return M|null
*/
public function updating(object $model, Context $context): ?object
{
return $model;
}
/**
* @param M $model
* @param FlarumContext $context
* @return M|null
*/
public function saving(object $model, Context $context): ?object
{
return $model;
}
/**
* @param M $model
* @param FlarumContext $context
* @return M|null
*/
public function saved(object $model, Context $context): ?object
{
return $model;
}
/**
* @param M $model
* @param FlarumContext $context
* @return M|null
*/
public function created(object $model, Context $context): ?object
{
return $model;
}
/**
* @param M $model
* @param FlarumContext $context
* @return M|null
*/
public function updated(object $model, Context $context): ?object
{
return $model;
}
/**
* @param M $model
* @param FlarumContext $context
*/
public function deleting(object $model, Context $context): void
{
//
}
/**
* @param M $model
* @param FlarumContext $context
*/
public function deleted(object $model, Context $context): void
{
//
@@ -144,11 +170,17 @@ abstract class AbstractDatabaseResource extends BaseResource implements
}
}
/**
* @param FlarumContext $context
*/
public function mutateDataBeforeValidation(Context $context, array $data): array
{
return $data;
}
/**
* @param FlarumContext $context
*/
public function results(object $query, Context $context): iterable
{
if ($results = $context->getSearchResults()) {
@@ -158,6 +190,9 @@ abstract class AbstractDatabaseResource extends BaseResource implements
return $query->get();
}
/**
* @param FlarumContext $context
*/
public function count(object $query, Context $context): ?int
{
if ($results = $context->getSearchResults()) {

View File

@@ -9,14 +9,17 @@
namespace Flarum\Api\Resource;
use Flarum\Api\Context;
use Flarum\Api\Resource\Concerns\Bootable;
use Flarum\Api\Resource\Concerns\Extendable;
use Flarum\Api\Resource\Concerns\HasSortMap;
use Flarum\Api\Resource\Contracts\Collection;
use Flarum\Api\Resource\Contracts\Resource;
use Tobyz\JsonApiServer\Resource\AbstractResource as BaseResource;
abstract class AbstractResource extends BaseResource implements Resource, Collection
/**
* @template M of object
* @extends BaseResource<M, Context>
*/
abstract class AbstractResource extends BaseResource
{
use Bootable;
use Extendable;

View File

@@ -24,6 +24,9 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Jenssegers\Agent\Agent;
/**
* @extends AbstractDatabaseResource<AccessToken>
*/
class AccessTokenResource extends AbstractDatabaseResource
{
public function __construct(

View File

@@ -15,9 +15,9 @@ use Illuminate\Contracts\Validation\Factory;
trait Bootable
{
protected readonly JsonApi $api;
protected readonly Dispatcher $events;
protected readonly Factory $validation;
protected JsonApi $api;
protected Dispatcher $events;
protected Factory $validation;
/**
* Avoids polluting the constructor of the resource with dependencies.

View File

@@ -11,13 +11,13 @@ namespace Flarum\Api\Resource\Concerns;
trait Extendable
{
private static array $endpointModifiers = [];
private static array $fieldModifiers = [];
private static array $sortModifiers = [];
protected static array $endpointModifiers = [];
protected static array $fieldModifiers = [];
protected static array $sortModifiers = [];
private ?array $cachedEndpoints = null;
private ?array $cachedFields = null;
private ?array $cachedSorts = null;
protected ?array $cachedEndpoints = null;
protected ?array $cachedFields = null;
protected ?array $cachedSorts = null;
public static function mutateEndpoints(callable $modifier): void
{

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Attachable as BaseAttachable;
interface Attachable extends BaseAttachable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Collection as BaseCollection;
interface Collection extends BaseCollection
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Countable as BaseCountable;
interface Countable extends BaseCountable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Creatable as BaseCreatable;
interface Creatable extends BaseCreatable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Deletable as BaseDeletable;
interface Deletable extends BaseDeletable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Findable as BaseFindable;
interface Findable extends BaseFindable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Listable as BaseListable;
interface Listable extends BaseListable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Paginatable as BasePaginatable;
interface Paginatable extends BasePaginatable
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Resource as BaseResource;
interface Resource extends BaseResource
{
//
}

View File

@@ -1,17 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Api\Resource\Contracts;
use Tobyz\JsonApiServer\Resource\Updatable as BaseUpdatable;
interface Updatable extends BaseUpdatable
{
//
}

View File

@@ -28,6 +28,9 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
/**
* @extends AbstractDatabaseResource<Discussion>
*/
class DiscussionResource extends AbstractDatabaseResource
{
public function __construct(
@@ -213,6 +216,9 @@ class DiscussionResource extends AbstractDatabaseResource
return fn () => $discussion->posts->all();
}
/** @var Endpoint\Show $endpoint */
$endpoint = $context->endpoint;
$actor = $context->getActor();
$limit = PostResource::$defaultLimit;
@@ -221,7 +227,7 @@ class DiscussionResource extends AbstractDatabaseResource
$offset = $this->posts->getIndexForNumber($discussion->id, $near, $actor);
$offset = max(0, $offset - $limit / 2);
} else {
$offset = $context->endpoint->extractOffsetValue($context, $context->endpoint->defaultExtracts($context));
$offset = $endpoint->extractOffsetValue($context, $endpoint->defaultExtracts($context));
}
$posts = $discussion->posts()
@@ -304,14 +310,12 @@ class DiscussionResource extends AbstractDatabaseResource
$model->newQuery()->getConnection()->transaction(function () use ($model, $context) {
$model->save();
/**
* @var JsonApi $api
* @var Post $post
*/
/** @var JsonApi $api */
$api = $context->api;
// Now that the discussion has been created, we can add the first post.
// We will do this by running the PostReply command.
/** @var Post $post */
$post = $api->forResource(PostResource::class)
->forEndpoint('create')
->withRequest($context->request)

View File

@@ -10,14 +10,16 @@
namespace Flarum\Api\Resource;
use Flarum\Api\Endpoint;
use Flarum\Api\Resource\Contracts\Findable;
use Flarum\Api\Schema;
use Flarum\Extension\Extension;
use Flarum\Extension\ExtensionManager;
use Tobyz\JsonApiServer\Context;
use Tobyz\JsonApiServer\Resource\Findable;
/**
* @todo: change to a simple ExtensionResource with readme field.
*
* @extends AbstractResource<Extension>
*/
class ExtensionReadmeResource extends AbstractResource implements Findable
{

View File

@@ -11,19 +11,26 @@ namespace Flarum\Api\Resource;
use Flarum\Api\Context;
use Flarum\Api\Endpoint;
use Flarum\Api\Resource\Contracts\Findable;
use Flarum\Api\Schema;
use Flarum\Foundation\Application;
use Flarum\Foundation\Config;
use Flarum\Group\Group;
use Flarum\Http\UrlGenerator;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Filesystem\Cloud;
use Illuminate\Contracts\Filesystem\Factory;
use Illuminate\Contracts\Filesystem\Filesystem;
use stdClass;
use Tobyz\JsonApiServer\Resource\Findable;
/**
* @extends AbstractResource<stdClass>
*/
class ForumResource extends AbstractResource implements Findable
{
/**
* @var Filesystem&Cloud
*/
protected Filesystem $assetsFilesystem;
public function __construct(

View File

@@ -20,6 +20,9 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Tobyz\JsonApiServer\Context;
/**
* @extends AbstractDatabaseResource<Group>
*/
class GroupResource extends AbstractDatabaseResource
{
public function __construct(

View File

@@ -10,7 +10,6 @@
namespace Flarum\Api\Resource;
use Flarum\Api\Endpoint;
use Flarum\Api\Resource\Contracts\Findable;
use Flarum\Api\Schema;
use Flarum\Mail\DriverInterface;
use Flarum\Settings\SettingsRepositoryInterface;
@@ -18,7 +17,11 @@ use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Validation\Factory;
use stdClass;
use Tobyz\JsonApiServer\Context;
use Tobyz\JsonApiServer\Resource\Findable;
/**
* @extends AbstractResource<object>
*/
class MailSettingResource extends AbstractResource implements Findable
{
public function __construct(

View File

@@ -16,8 +16,11 @@ use Flarum\Bus\Dispatcher;
use Flarum\Notification\Command\ReadNotification;
use Flarum\Notification\Notification;
use Flarum\Notification\NotificationRepository;
use Tobyz\JsonApiServer\Pagination\Pagination;
use Tobyz\JsonApiServer\Pagination\OffsetPagination;
/**
* @extends AbstractDatabaseResource<Notification>
*/
class NotificationResource extends AbstractDatabaseResource
{
public function __construct(
@@ -39,8 +42,10 @@ class NotificationResource extends AbstractDatabaseResource
public function query(\Tobyz\JsonApiServer\Context $context): object
{
if ($context->listing(self::class)) {
/** @var Pagination $pagination */
$pagination = ($context->endpoint->paginationResolver)($context);
/** @var Endpoint\Index $endpoint */
$endpoint = $context->endpoint;
/** @var OffsetPagination $pagination */
$pagination = ($endpoint->paginationResolver)($context);
return $this->notifications->query($context->getActor(), $pagination->limit, $pagination->offset);
}

View File

@@ -28,6 +28,9 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Tobyz\JsonApiServer\Exception\BadRequestException;
/**
* @extends AbstractDatabaseResource<Post>
*/
class PostResource extends AbstractDatabaseResource
{
public static int $defaultLimit = 20;
@@ -187,8 +190,12 @@ class PostResource extends AbstractDatabaseResource
}
})
->serialize(function (null|string|array $value, Context $context) {
// Prevent the string type from trying to convert array content (for event posts) to a string.
$context->field->type = null;
/**
* Prevent the string type from trying to convert array content (for event posts) to a string.
* @var Schema\Str $field
*/
$field = $context->field;
$field->type = null;
return $value;
}),
@@ -196,7 +203,7 @@ class PostResource extends AbstractDatabaseResource
->visible(function (Post $post) {
return $post instanceof CommentPost;
})
->get(function (Post $post, Context $context) {
->get(function (CommentPost $post, Context $context) {
try {
$rendered = $post->formatContent($context->request);
$post->setAttribute('renderFailed', false);

View File

@@ -35,6 +35,9 @@ use Illuminate\Support\Str;
use Intervention\Image\ImageManager;
use InvalidArgumentException;
/**
* @extends AbstractDatabaseResource<User>
*/
class UserResource extends AbstractDatabaseResource
{
public function __construct(
@@ -224,6 +227,7 @@ class UserResource extends AbstractDatabaseResource
})
->set(function (User $user, ?string $value, Context $context) {
if ($value) {
/** @var RegistrationToken $token */
$token = RegistrationToken::validOrFail($value);
$context->setParam('token', $token);

View File

@@ -44,11 +44,6 @@ class UserState extends AbstractModel
'last_read_at' => 'datetime'
];
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = ['last_read_post_number'];
/**

View File

@@ -10,11 +10,13 @@
namespace Flarum\Extend;
use Flarum\Api\Endpoint\EndpointInterface;
use Flarum\Api\Resource\Contracts\Resource;
use Flarum\Extension\Extension;
use Flarum\Foundation\ContainerUtil;
use Illuminate\Contracts\Container\Container;
use ReflectionClass;
use RuntimeException;
use Tobyz\JsonApiServer\Endpoint\Endpoint;
use Tobyz\JsonApiServer\Resource\Resource;
use Tobyz\JsonApiServer\Schema\Field\Field;
use Tobyz\JsonApiServer\Schema\Sort;
@@ -55,7 +57,7 @@ class ApiResource implements ExtenderInterface
/**
* Remove endpoints from the resource.
*
* @param array $endpoints must be an array of class names of the endpoints.
* @param array $endpoints must be an array of names of the endpoints.
* @param callable|class-string|null $condition a callable that returns a boolean or a string that represents whether this should be applied.
*/
public function removeEndpoints(array $endpoints, callable|string $condition = null): self
@@ -68,14 +70,13 @@ class ApiResource implements ExtenderInterface
/**
* Modify an endpoint.
*
* @param class-string<\Flarum\Api\Endpoint\EndpointInterface>|array<\Flarum\Api\Endpoint\EndpointInterface> $endpointClass the class name of the endpoint.
* or an array of class names of the endpoints.
* @param string|string[] $endpointNameOrClass the name or class name of the endpoint or an array of so.
* @param callable|class-string $mutator a callable that accepts an endpoint and returns the modified endpoint.
*/
public function endpoint(string|array $endpointClass, callable|string $mutator): self
public function endpoint(string|array $endpointNameOrClass, callable|string $mutator): self
{
foreach ((array) $endpointClass as $endpointClassItem) {
$this->endpoint[$endpointClassItem][] = $mutator;
foreach ((array) $endpointNameOrClass as $item) {
$this->endpoint[$item][] = $mutator;
}
return $this;
@@ -176,39 +177,45 @@ class ApiResource implements ExtenderInterface
/** @var class-string<\Flarum\Api\Resource\AbstractResource|\Flarum\Api\Resource\AbstractDatabaseResource> $resourceClass */
$resourceClass = $this->resourceClass;
$resourceClass::mutateEndpoints(function (array $endpoints, Resource $resource) use ($container): array {
foreach ($this->endpoints as $newEndpointsCallback) {
$newEndpointsCallback = ContainerUtil::wrapCallback($newEndpointsCallback, $container);
$endpoints = array_merge($endpoints, $newEndpointsCallback());
}
foreach ($this->removeEndpoints as $removeEndpointClass) {
[$endpointsToRemove, $condition] = $removeEndpointClass;
if ($this->isApplicable($condition, $resource, $container)) {
$endpoints = array_filter($endpoints, fn (EndpointInterface $endpoint) => ! in_array($endpoint::class, $endpointsToRemove));
$resourceClass::mutateEndpoints(
/**
* @var EndpointInterface[] $endpoints
*/
function (array $endpoints, Resource $resource) use ($container): array {
foreach ($this->endpoints as $newEndpointsCallback) {
$newEndpointsCallback = ContainerUtil::wrapCallback($newEndpointsCallback, $container);
$endpoints = array_merge($endpoints, $newEndpointsCallback());
}
}
foreach ($endpoints as $key => $endpoint) {
$endpointClass = $endpoint::class;
foreach ($this->removeEndpoints as $removeEndpointClass) {
[$endpointsToRemove, $condition] = $removeEndpointClass;
if (! empty($this->endpoint[$endpointClass])) {
foreach ($this->endpoint[$endpointClass] as $mutator) {
$mutateEndpoint = ContainerUtil::wrapCallback($mutator, $container);
$endpoint = $mutateEndpoint($endpoint, $resource);
if (! $endpoint instanceof EndpointInterface) {
throw new \RuntimeException('The endpoint mutator must return an instance of '.EndpointInterface::class);
}
if ($this->isApplicable($condition, $resource, $container)) {
$endpoints = array_filter($endpoints, fn (Endpoint $endpoint) => ! in_array($endpoint->name, $endpointsToRemove));
}
}
$endpoints[$key] = $endpoint;
}
foreach ($endpoints as $key => $endpoint) {
$endpointClass = $endpoint::class;
return $endpoints;
});
if (! empty($this->endpoint[$endpoint->name]) || ! empty($this->endpoint[$endpointClass])) {
foreach (array_merge($this->endpoint[$endpoint->name] ?? [], $this->endpoint[$endpointClass] ?? []) as $mutator) {
$mutateEndpoint = ContainerUtil::wrapCallback($mutator, $container);
$endpoint = $mutateEndpoint($endpoint, $resource);
if (! $endpoint instanceof EndpointInterface) {
throw new RuntimeException('The endpoint mutator must return an instance of '.EndpointInterface::class);
}
}
}
$endpoints[$key] = $endpoint;
}
return $endpoints;
}
);
$resourceClass::mutateFields(function (array $fields, Resource $resource) use ($container): array {
foreach ($this->fields as $newFieldsCallback) {
@@ -231,7 +238,7 @@ class ApiResource implements ExtenderInterface
$field = $mutateField($field);
if (! $field instanceof Field) {
throw new \RuntimeException('The field mutator must return an instance of '.Field::class);
throw new RuntimeException('The field mutator must return an instance of '.Field::class);
}
}
}
@@ -263,7 +270,7 @@ class ApiResource implements ExtenderInterface
$sort = $mutateSort($sort);
if (! $sort instanceof Sort) {
throw new \RuntimeException('The sort mutator must return an instance of '.Sort::class);
throw new RuntimeException('The sort mutator must return an instance of '.Sort::class);
}
}
}

View File

@@ -40,7 +40,6 @@ class Routes implements ExtenderInterface
*
* The handler should accept:
* - \Psr\Http\Message\ServerRequestInterface $request
* - \Tobscure\JsonApi\Document $document: If it extends one of the Flarum Api controllers.
*
* The handler should return:
* - \Psr\Http\Message\ResponseInterface $response
@@ -64,7 +63,6 @@ class Routes implements ExtenderInterface
*
* The handler should accept:
* - \Psr\Http\Message\ServerRequestInterface $request
* - \Tobscure\JsonApi\Document $document: If it extends one of the Flarum Api controllers.
*
* The handler should return:
* - \Psr\Http\Message\ResponseInterface $response
@@ -88,7 +86,6 @@ class Routes implements ExtenderInterface
*
* The handler should accept:
* - \Psr\Http\Message\ServerRequestInterface $request
* - \Tobscure\JsonApi\Document $document: If it extends one of the Flarum Api controllers.
*
* The handler should return:
* - \Psr\Http\Message\ResponseInterface $response
@@ -112,7 +109,6 @@ class Routes implements ExtenderInterface
*
* The handler should accept:
* - \Psr\Http\Message\ServerRequestInterface $request
* - \Tobscure\JsonApi\Document $document: If it extends one of the Flarum Api controllers.
*
* The handler should return:
* - \Psr\Http\Message\ResponseInterface $response
@@ -136,7 +132,6 @@ class Routes implements ExtenderInterface
*
* The handler should accept:
* - \Psr\Http\Message\ServerRequestInterface $request
* - \Tobscure\JsonApi\Document $document: If it extends one of the Flarum Api controllers.
*
* The handler should return:
* - \Psr\Http\Message\ResponseInterface $response

View File

@@ -20,7 +20,7 @@ class JsonApiExceptionHandler
return (new HandledError(
$e,
'validation_error',
$e->getJsonApiStatus()
intval($e->getJsonApiStatus())
))->withDetails($e->getJsonApiErrors());
}
}

View File

@@ -78,7 +78,7 @@ class RequestUtil
{
$limit = $request->getQueryParams()['page']['limit'] ?? '';
if (is_null($limit) || ! filled($limit)) {
if (! filled($limit)) {
$limit = $defaultLimit;
}

View File

@@ -24,6 +24,9 @@ class NotificationRepository
return $this->query($user, $limit, $offset)->get();
}
/**
* @return Builder<Notification>
*/
public function query(User $user, ?int $limit = null, int $offset = 0): Builder
{
$primaries = Notification::query()

View File

@@ -16,6 +16,9 @@ parameters:
- stubs/Illuminate/Contracts/Filesystem/Cloud.stub
- stubs/Illuminate/Contracts/Filesystem/Filesystem.stub
# We know for a fact the JsonApi object used internally is always the Flarum one.
- stubs/Tobyz/JsonApiServer/JsonApi.stub
services:
-
class: Flarum\PHPStan\Relations\ModelRelationsExtension

View File

@@ -30,3 +30,13 @@ parameters:
# ignore this error, so we have to ignore it globally.
- message: '#^Parameter \#[0-9]+ \$[A-z0-9_]+ of method Flarum\Extend\[A-z0-9_:\\()]+ expects \(?callable\([A-z0-9_,|\\: ()-]+\)\)?, (callable|Closure)\([A-z0-9_,|\\: ()-]+\) given\.$#'
reportUnmatched: false
# PHPStan suddenly doesn't recognize callables can be function names?
- message: '#^Parameter \#[0-9]+ \$[A-z0-9_]+ of function [A-z0-9_:\\()]+ expects \(?callable\([A-z0-9_,|\\: ()-]+, ''[A-z0-9_:\\()]+'' given\.$#'
reportUnmatched: false
# Not if we're using our own static make method.
- message: '#^Called ''Model\:\:make\(\)'' which performs unnecessary work, use ''new Model\(\)''\.$#'
# This assumes that the phpdoc telling it it's not nullable is correct, that's not the case for internal Laravel typings.
- message: '#^Property [A-z0-9-_:$,\\]+ \([A-z]+\) on left side of \?\? is not nullable\.$#'

View File

@@ -0,0 +1,11 @@
<?php
namespace Tobyz\JsonApiServer;
/**
* @mixin \Flarum\Api\JsonApi
*/
class JsonApi
{
}