mirror of
https://github.com/flarum/framework.git
synced 2024-11-26 02:10:09 +08:00
chore: increase phpstan level to 6 (#3836)
* chore: increase phpstan level to 6 Signed-off-by: Sami Mazouz <sychocouldy@gmail.com> * Apply fixes from StyleCI --------- Signed-off-by: Sami Mazouz <sychocouldy@gmail.com> Co-authored-by: StyleCI Bot <bot@styleci.io>
This commit is contained in:
parent
4a966b830f
commit
5820a16a96
|
@ -15,22 +15,19 @@ use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
class Akismet
|
class Akismet
|
||||||
{
|
{
|
||||||
private $apiKey;
|
private string $apiUrl;
|
||||||
private $apiUrl;
|
private array $params = [];
|
||||||
private $flarumVersion;
|
|
||||||
private $extensionVersion;
|
|
||||||
|
|
||||||
private $params = [];
|
public function __construct(
|
||||||
|
private readonly string $apiKey,
|
||||||
public function __construct(string $apiKey, string $homeUrl, string $flarumVersion, string $extensionVersion, bool $inDebugMode = false)
|
string $homeUrl,
|
||||||
{
|
private readonly string $flarumVersion,
|
||||||
$this->apiKey = $apiKey;
|
private readonly string $extensionVersion,
|
||||||
|
bool $inDebugMode = false
|
||||||
|
) {
|
||||||
$this->apiUrl = "https://$apiKey.rest.akismet.com/1.1";
|
$this->apiUrl = "https://$apiKey.rest.akismet.com/1.1";
|
||||||
$this->params['blog'] = $homeUrl;
|
$this->params['blog'] = $homeUrl;
|
||||||
|
|
||||||
$this->flarumVersion = $flarumVersion;
|
|
||||||
$this->extensionVersion = $extensionVersion;
|
|
||||||
|
|
||||||
if ($inDebugMode) {
|
if ($inDebugMode) {
|
||||||
$this->params['is_test'] = true;
|
$this->params['is_test'] = true;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +70,7 @@ class Akismet
|
||||||
/**
|
/**
|
||||||
* @throws GuzzleException
|
* @throws GuzzleException
|
||||||
*/
|
*/
|
||||||
public function submitSpam()
|
public function submitSpam(): void
|
||||||
{
|
{
|
||||||
$this->sendRequest('submit-spam');
|
$this->sendRequest('submit-spam');
|
||||||
}
|
}
|
||||||
|
@ -81,7 +78,7 @@ class Akismet
|
||||||
/**
|
/**
|
||||||
* @throws GuzzleException
|
* @throws GuzzleException
|
||||||
*/
|
*/
|
||||||
public function submitHam()
|
public function submitHam(): void
|
||||||
{
|
{
|
||||||
$this->sendRequest('submit-ham');
|
$this->sendRequest('submit-ham');
|
||||||
}
|
}
|
||||||
|
@ -90,7 +87,7 @@ class Akismet
|
||||||
* Allows you to set additional parameter
|
* Allows you to set additional parameter
|
||||||
* This lets you use Akismet features not supported directly in this util.
|
* This lets you use Akismet features not supported directly in this util.
|
||||||
*/
|
*/
|
||||||
public function withParam(string $key, $value): Akismet
|
public function withParam(string $key, mixed $value): Akismet
|
||||||
{
|
{
|
||||||
$new = clone $this;
|
$new = clone $this;
|
||||||
$new->params[$key] = $value;
|
$new->params[$key] = $value;
|
||||||
|
|
|
@ -21,10 +21,12 @@ class LikePostPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function like(User $actor, Post $post)
|
public function like(User $actor, Post $post): ?string
|
||||||
{
|
{
|
||||||
if ($actor->id === $post->user_id && ! (bool) $this->settings->get('flarum-likes.like_own_post')) {
|
if ($actor->id === $post->user_id && ! (bool) $this->settings->get('flarum-likes.like_own_post')) {
|
||||||
return $this->deny();
|
return $this->deny();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,12 @@ use Flarum\User\User;
|
||||||
|
|
||||||
class DiscussionPolicy extends AbstractPolicy
|
class DiscussionPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
public function reply(User $actor, Discussion $discussion)
|
public function reply(User $actor, Discussion $discussion): ?string
|
||||||
{
|
{
|
||||||
if ($discussion->is_locked && $actor->cannot('lock', $discussion)) {
|
if ($discussion->is_locked && $actor->cannot('lock', $discussion)) {
|
||||||
return $this->deny();
|
return $this->deny();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,9 +82,9 @@ class ConfigureMentions
|
||||||
/**
|
/**
|
||||||
* @param FormatterTag $tag
|
* @param FormatterTag $tag
|
||||||
* @param array{users: Collection<int, User>} $mentions
|
* @param array{users: Collection<int, User>} $mentions
|
||||||
* @return bool|void
|
* @return bool|null
|
||||||
*/
|
*/
|
||||||
public static function addUserId(FormatterTag $tag, array $mentions)
|
public static function addUserId(FormatterTag $tag, array $mentions): ?bool
|
||||||
{
|
{
|
||||||
$allow_username_format = (bool) resolve(SettingsRepositoryInterface::class)->get('flarum-mentions.allow_username_format');
|
$allow_username_format = (bool) resolve(SettingsRepositoryInterface::class)->get('flarum-mentions.allow_username_format');
|
||||||
|
|
||||||
|
@ -102,6 +102,8 @@ class ConfigureMentions
|
||||||
}
|
}
|
||||||
|
|
||||||
$tag->invalidate();
|
$tag->invalidate();
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function configurePostMentions(Configurator $config): void
|
private function configurePostMentions(Configurator $config): void
|
||||||
|
@ -141,9 +143,9 @@ class ConfigureMentions
|
||||||
/**
|
/**
|
||||||
* @param FormatterTag $tag
|
* @param FormatterTag $tag
|
||||||
* @param array{posts: Collection<int, Post>} $mentions
|
* @param array{posts: Collection<int, Post>} $mentions
|
||||||
* @return bool|void
|
* @return bool|null
|
||||||
*/
|
*/
|
||||||
public static function addPostId(FormatterTag $tag, array $mentions)
|
public static function addPostId(FormatterTag $tag, array $mentions): ?bool
|
||||||
{
|
{
|
||||||
$post = $mentions['posts']->where('id', $tag->getAttribute('id'))->first();
|
$post = $mentions['posts']->where('id', $tag->getAttribute('id'))->first();
|
||||||
|
|
||||||
|
@ -157,9 +159,11 @@ class ConfigureMentions
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function configureGroupMentions(Configurator $config)
|
private function configureGroupMentions(Configurator $config): void
|
||||||
{
|
{
|
||||||
$tagName = 'GROUPMENTION';
|
$tagName = 'GROUPMENTION';
|
||||||
|
|
||||||
|
@ -214,9 +218,9 @@ class ConfigureMentions
|
||||||
* @param FormatterTag $tag
|
* @param FormatterTag $tag
|
||||||
* @param User $actor
|
* @param User $actor
|
||||||
* @param array{groups: Collection<int, Group>} $mentions
|
* @param array{groups: Collection<int, Group>} $mentions
|
||||||
* @return bool|void
|
* @return bool|null
|
||||||
*/
|
*/
|
||||||
public static function addGroupId(FormatterTag $tag, User $actor, array $mentions)
|
public static function addGroupId(FormatterTag $tag, User $actor, array $mentions): ?bool
|
||||||
{
|
{
|
||||||
$id = $tag->getAttribute('id');
|
$id = $tag->getAttribute('id');
|
||||||
|
|
||||||
|
@ -236,9 +240,11 @@ class ConfigureMentions
|
||||||
}
|
}
|
||||||
|
|
||||||
$tag->invalidate();
|
$tag->invalidate();
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function configureTagMentions(Configurator $config)
|
private function configureTagMentions(Configurator $config): void
|
||||||
{
|
{
|
||||||
$config->rendering->parameters['TAG_URL'] = $this->url->to('forum')->route('tag', ['slug' => '']);
|
$config->rendering->parameters['TAG_URL'] = $this->url->to('forum')->route('tag', ['slug' => '']);
|
||||||
|
|
||||||
|
@ -303,9 +309,9 @@ class ConfigureMentions
|
||||||
/**
|
/**
|
||||||
* @param FormatterTag $tag
|
* @param FormatterTag $tag
|
||||||
* @param array{tags: Collection<int, Tag>} $mentions
|
* @param array{tags: Collection<int, Tag>} $mentions
|
||||||
* @return true|void
|
* @return bool|null
|
||||||
*/
|
*/
|
||||||
public static function addTagId(FormatterTag $tag, array $mentions)
|
public static function addTagId(FormatterTag $tag, array $mentions): ?bool
|
||||||
{
|
{
|
||||||
/** @var Tag|null $model */
|
/** @var Tag|null $model */
|
||||||
$model = $mentions['tags']->where('slug', $tag->getAttribute('slug'))->first();
|
$model = $mentions['tags']->where('slug', $tag->getAttribute('slug'))->first();
|
||||||
|
@ -316,6 +322,8 @@ class ConfigureMentions
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,7 +29,7 @@ class UnparsePostMentions
|
||||||
/**
|
/**
|
||||||
* Updates XML post mention tags before unparsing so that unparsing uses new display names.
|
* Updates XML post mention tags before unparsing so that unparsing uses new display names.
|
||||||
*/
|
*/
|
||||||
protected function updatePostMentionTags($context, string $xml): string
|
protected function updatePostMentionTags(mixed $context, string $xml): string
|
||||||
{
|
{
|
||||||
$post = $context;
|
$post = $context;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class UserPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function editNickname(User $actor, User $user)
|
public function editNickname(User $actor, User $user): ?string
|
||||||
{
|
{
|
||||||
if ($actor->isGuest() && ! $user->exists && $this->settings->get('flarum-nicknames.set_on_registration')) {
|
if ($actor->isGuest() && ! $user->exists && $this->settings->get('flarum-nicknames.set_on_registration')) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
|
@ -29,5 +29,7 @@ class UserPolicy extends AbstractPolicy
|
||||||
} elseif ($actor->can('edit', $user)) {
|
} elseif ($actor->can('edit', $user)) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,12 @@ use Flarum\User\User;
|
||||||
|
|
||||||
class UserPolicy extends AbstractPolicy
|
class UserPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
public function suspend(User $actor, User $user)
|
public function suspend(User $actor, User $user): ?string
|
||||||
{
|
{
|
||||||
if ($user->isAdmin() || $user->id === $actor->id) {
|
if ($user->isAdmin() || $user->id === $actor->id) {
|
||||||
return $this->deny();
|
return $this->deny();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function can(User $actor, string $ability, Discussion $discussion)
|
public function can(User $actor, string $ability, Discussion $discussion): ?string
|
||||||
{
|
{
|
||||||
// Wrap all discussion permission checks with some logic pertaining to
|
// Wrap all discussion permission checks with some logic pertaining to
|
||||||
// the discussion's tags. If the discussion has a tag that has been
|
// the discussion's tags. If the discussion has a tag that has been
|
||||||
|
@ -46,13 +46,15 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks, if the user is still allowed to edit the tags
|
* This method checks, if the user is still allowed to edit the tags
|
||||||
* based on the configuration item.
|
* based on the configuration item.
|
||||||
*/
|
*/
|
||||||
public function tag(User $actor, Discussion $discussion)
|
public function tag(User $actor, Discussion $discussion): ?string
|
||||||
{
|
{
|
||||||
if ($discussion->user_id == $actor->id && $actor->can('reply', $discussion)) {
|
if ($discussion->user_id == $actor->id && $actor->can('reply', $discussion)) {
|
||||||
$allowEditTags = $this->settings->get('allow_tag_change');
|
$allowEditTags = $this->settings->get('allow_tag_change');
|
||||||
|
@ -65,5 +67,7 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class GlobalPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function can(User $actor, string $ability)
|
public function can(User $actor, string $ability): ?string
|
||||||
{
|
{
|
||||||
static $enoughPrimary;
|
static $enoughPrimary;
|
||||||
static $enoughSecondary;
|
static $enoughSecondary;
|
||||||
|
@ -67,5 +67,7 @@ class GlobalPolicy extends AbstractPolicy
|
||||||
return $this->deny();
|
return $this->deny();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use Flarum\User\User;
|
||||||
|
|
||||||
class TagPolicy extends AbstractPolicy
|
class TagPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
public function can(User $actor, string $ability, Tag $tag)
|
public function can(User $actor, string $ability, Tag $tag): string|bool|null
|
||||||
{
|
{
|
||||||
if ($tag->parent_id !== null && ! $actor->can($ability, $tag->parent)) {
|
if ($tag->parent_id !== null && ! $actor->can($ability, $tag->parent)) {
|
||||||
return $this->deny();
|
return $this->deny();
|
||||||
|
@ -26,6 +26,8 @@ class TagPolicy extends AbstractPolicy
|
||||||
|
|
||||||
return $actor->hasPermission("tag$id.$ability");
|
return $actor->hasPermission("tag$id.$ability");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addToDiscussion(User $actor, Tag $tag): bool
|
public function addToDiscussion(User $actor, Tag $tag): bool
|
||||||
|
|
|
@ -89,12 +89,12 @@ class Tag
|
||||||
/**
|
/**
|
||||||
* Get the result of an API request to list discussions.
|
* Get the result of an API request to list discussions.
|
||||||
*/
|
*/
|
||||||
protected function getApiDocument(Request $request, array $params)
|
protected function getApiDocument(Request $request, array $params): object
|
||||||
{
|
{
|
||||||
return json_decode($this->api->withParentRequest($request)->withQueryParams($params)->get('/discussions')->getBody());
|
return json_decode($this->api->withParentRequest($request)->withQueryParams($params)->get('/discussions')->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getTagsDocument(Request $request, string $slug)
|
protected function getTagsDocument(Request $request, string $slug): object
|
||||||
{
|
{
|
||||||
return json_decode($this->api->withParentRequest($request)->withQueryParams([
|
return json_decode($this->api->withParentRequest($request)->withQueryParams([
|
||||||
'include' => 'children,children.parent,parent,parent.children.parent,state'
|
'include' => 'children,children.parent,parent,parent.children.parent,state'
|
||||||
|
|
|
@ -34,14 +34,14 @@ class Tags
|
||||||
public function __invoke(Document $document, Request $request): Document
|
public function __invoke(Document $document, Request $request): Document
|
||||||
{
|
{
|
||||||
$apiDocument = $this->getTagsDocument($request);
|
$apiDocument = $this->getTagsDocument($request);
|
||||||
$tags = collect(Arr::get($apiDocument, 'data', []));
|
$tags = collect((array) Arr::get($apiDocument, 'data', []));
|
||||||
|
|
||||||
$childTags = $tags->where('attributes.isChild', true);
|
$childTags = $tags->where('attributes.isChild', true);
|
||||||
$primaryTags = $tags->where('attributes.isChild', false)->where('attributes.position', '!==', null)->sortBy('attributes.position');
|
$primaryTags = $tags->where('attributes.isChild', false)->where('attributes.position', '!==', null)->sortBy('attributes.position');
|
||||||
$secondaryTags = $tags->where('attributes.isChild', false)->where('attributes.position', '===', null)->sortBy('attributes.name');
|
$secondaryTags = $tags->where('attributes.isChild', false)->where('attributes.position', '===', null)->sortBy('attributes.name');
|
||||||
|
|
||||||
$children = $primaryTags->mapWithKeys(function ($tag) use ($childTags) {
|
$children = $primaryTags->mapWithKeys(function ($tag) use ($childTags) {
|
||||||
$childIds = collect(Arr::get($tag, 'relationships.children.data'))->pluck('id');
|
$childIds = collect((array) Arr::get($tag, 'relationships.children.data'))->pluck('id');
|
||||||
|
|
||||||
return [$tag['id'] => $childTags->whereIn('id', $childIds)->sortBy('position')];
|
return [$tag['id'] => $childTags->whereIn('id', $childIds)->sortBy('position')];
|
||||||
});
|
});
|
||||||
|
@ -56,7 +56,7 @@ class Tags
|
||||||
return $document;
|
return $document;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getTagsDocument(Request $request)
|
protected function getTagsDocument(Request $request): array
|
||||||
{
|
{
|
||||||
return json_decode($this->api->withParentRequest($request)->withQueryParams([
|
return json_decode($this->api->withParentRequest($request)->withQueryParams([
|
||||||
'include' => 'children,lastPostedDiscussion,parent'
|
'include' => 'children,lastPostedDiscussion,parent'
|
||||||
|
|
|
@ -49,7 +49,7 @@ class TagFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), $filterValue, $negate, $filterState->getActor());
|
$this->constrain($filterState->getQuery(), $filterValue, $negate, $filterState->getActor());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function constrain(Builder $query, string|array $rawSlugs, $negate, User $actor): void
|
protected function constrain(Builder $query, string|array $rawSlugs, bool $negate, User $actor): void
|
||||||
{
|
{
|
||||||
$slugs = $this->asStringArray($rawSlugs);
|
$slugs = $this->asStringArray($rawSlugs);
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,10 @@ class CreatePostController extends AbstractCreateController
|
||||||
{
|
{
|
||||||
$actor = RequestUtil::getActor($request);
|
$actor = RequestUtil::getActor($request);
|
||||||
$data = Arr::get($request->getParsedBody(), 'data', []);
|
$data = Arr::get($request->getParsedBody(), 'data', []);
|
||||||
$discussionId = Arr::get($data, 'relationships.discussion.data.id');
|
$discussionId = (int) Arr::get($data, 'relationships.discussion.data.id');
|
||||||
$ipAddress = $request->getAttribute('ipAddress');
|
$ipAddress = $request->getAttribute('ipAddress');
|
||||||
|
|
||||||
|
/** @var CommentPost $post */
|
||||||
$post = $this->bus->dispatch(
|
$post = $this->bus->dispatch(
|
||||||
new PostReply($discussionId, $actor, $data, $ipAddress)
|
new PostReply($discussionId, $actor, $data, $ipAddress)
|
||||||
);
|
);
|
||||||
|
@ -56,7 +57,7 @@ class CreatePostController extends AbstractCreateController
|
||||||
}
|
}
|
||||||
|
|
||||||
$discussion = $post->discussion;
|
$discussion = $post->discussion;
|
||||||
$discussion->posts = $discussion->posts()->whereVisibleTo($actor)->orderBy('created_at')->pluck('id');
|
$discussion->setRelation('posts', $discussion->posts()->whereVisibleTo($actor)->orderBy('created_at')->pluck('id'));
|
||||||
|
|
||||||
$this->loadRelations($post->newCollection([$post]), $this->extractInclude($request), $request);
|
$this->loadRelations($post->newCollection([$post]), $this->extractInclude($request), $request);
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class UpdateDiscussionController extends AbstractShowController
|
||||||
protected function data(ServerRequestInterface $request, Document $document): Discussion
|
protected function data(ServerRequestInterface $request, Document $document): Discussion
|
||||||
{
|
{
|
||||||
$actor = RequestUtil::getActor($request);
|
$actor = RequestUtil::getActor($request);
|
||||||
$discussionId = Arr::get($request->getQueryParams(), 'id');
|
$discussionId = (int) Arr::get($request->getQueryParams(), 'id');
|
||||||
$data = Arr::get($request->getParsedBody(), 'data', []);
|
$data = Arr::get($request->getParsedBody(), 'data', []);
|
||||||
|
|
||||||
/** @var Discussion $discussion */
|
/** @var Discussion $discussion */
|
||||||
|
|
|
@ -17,11 +17,9 @@ use Psr\Http\Server\RequestHandlerInterface as Handler;
|
||||||
|
|
||||||
class ThrottleApi implements Middleware
|
class ThrottleApi implements Middleware
|
||||||
{
|
{
|
||||||
protected $throttlers;
|
public function __construct(
|
||||||
|
protected array $throttlers
|
||||||
public function __construct(array $throttlers)
|
) {
|
||||||
{
|
|
||||||
$this->throttlers = $throttlers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process(Request $request, Handler $handler): Response
|
public function process(Request $request, Handler $handler): Response
|
||||||
|
@ -33,9 +31,6 @@ class ThrottleApi implements Middleware
|
||||||
return $handler->handle($request);
|
return $handler->handle($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function throttle(Request $request): bool
|
public function throttle(Request $request): bool
|
||||||
{
|
{
|
||||||
$throttle = false;
|
$throttle = false;
|
||||||
|
|
|
@ -40,37 +40,37 @@ class BasicDiscussionSerializer extends AbstractSerializer
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function user($discussion): ?Relationship
|
protected function user(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($discussion, BasicUserSerializer::class);
|
return $this->hasOne($discussion, BasicUserSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function firstPost($discussion): ?Relationship
|
protected function firstPost(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($discussion, BasicPostSerializer::class);
|
return $this->hasOne($discussion, BasicPostSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function lastPostedUser($discussion): ?Relationship
|
protected function lastPostedUser(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($discussion, BasicUserSerializer::class);
|
return $this->hasOne($discussion, BasicUserSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function lastPost($discussion): ?Relationship
|
protected function lastPost(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($discussion, BasicPostSerializer::class);
|
return $this->hasOne($discussion, BasicPostSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function posts($discussion): ?Relationship
|
protected function posts(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasMany($discussion, PostSerializer::class);
|
return $this->hasMany($discussion, PostSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function mostRelevantPost($discussion): ?Relationship
|
protected function mostRelevantPost(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($discussion, PostSerializer::class);
|
return $this->hasOne($discussion, PostSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hiddenUser($discussion): ?Relationship
|
protected function hiddenUser(Discussion $discussion): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($discussion, BasicUserSerializer::class);
|
return $this->hasOne($discussion, BasicUserSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class BasicUserSerializer extends AbstractSerializer
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function groups($user): Relationship
|
protected function groups(User $user): Relationship
|
||||||
{
|
{
|
||||||
if ($this->getActor()->can('viewHiddenGroups')) {
|
if ($this->getActor()->can('viewHiddenGroups')) {
|
||||||
return $this->hasMany($user, GroupSerializer::class);
|
return $this->hasMany($user, GroupSerializer::class);
|
||||||
|
|
|
@ -100,7 +100,7 @@ class ForumSerializer extends AbstractSerializer
|
||||||
return $attributes;
|
return $attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function groups($model): ?Relationship
|
protected function groups(array $model): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasMany($model, GroupSerializer::class);
|
return $this->hasMany($model, GroupSerializer::class);
|
||||||
}
|
}
|
||||||
|
@ -119,12 +119,12 @@ class ForumSerializer extends AbstractSerializer
|
||||||
return $faviconPath ? $this->getAssetUrl($faviconPath) : null;
|
return $faviconPath ? $this->getAssetUrl($faviconPath) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAssetUrl($assetPath): string
|
public function getAssetUrl(string $assetPath): string
|
||||||
{
|
{
|
||||||
return $this->assetsFilesystem->url($assetPath);
|
return $this->assetsFilesystem->url($assetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function actor($model): ?Relationship
|
protected function actor(array $model): ?Relationship
|
||||||
{
|
{
|
||||||
return $this->hasOne($model, CurrentUserSerializer::class);
|
return $this->hasOne($model, CurrentUserSerializer::class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Flarum\Console;
|
||||||
|
|
||||||
use Flarum\Foundation\Config;
|
use Flarum\Foundation\Config;
|
||||||
use Illuminate\Console\Scheduling\Schedule as LaravelSchedule;
|
use Illuminate\Console\Scheduling\Schedule as LaravelSchedule;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class Schedule extends LaravelSchedule
|
class Schedule extends LaravelSchedule
|
||||||
|
@ -21,7 +22,7 @@ class Schedule extends LaravelSchedule
|
||||||
return (new Collection($this->events))->filter->isDue(new class($app) {
|
return (new Collection($this->events))->filter->isDue(new class($app) {
|
||||||
protected Config $config;
|
protected Config $config;
|
||||||
|
|
||||||
public function __construct($app)
|
public function __construct(Container $app)
|
||||||
{
|
{
|
||||||
$this->config = $app->make(Config::class);
|
$this->config = $app->make(Config::class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use Illuminate\Database\Schema\Builder;
|
||||||
*/
|
*/
|
||||||
abstract class Migration
|
abstract class Migration
|
||||||
{
|
{
|
||||||
public static function createTable($name, callable $definition): array
|
public static function createTable(string $name, callable $definition): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'up' => function (Builder $schema) use ($name, $definition) {
|
'up' => function (Builder $schema) use ($name, $definition) {
|
||||||
|
@ -35,7 +35,7 @@ abstract class Migration
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createTableIfNotExists($name, callable $definition): array
|
public static function createTableIfNotExists(string $name, callable $definition): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'up' => function (Builder $schema) use ($name, $definition) {
|
'up' => function (Builder $schema) use ($name, $definition) {
|
||||||
|
@ -51,7 +51,7 @@ abstract class Migration
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function renameTable($from, $to): array
|
public static function renameTable(string $from, string $to): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'up' => function (Builder $schema) use ($from, $to) {
|
'up' => function (Builder $schema) use ($from, $to) {
|
||||||
|
@ -63,7 +63,7 @@ abstract class Migration
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function addColumns($tableName, array $columnDefinitions): array
|
public static function addColumns(string $tableName, array $columnDefinitions): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'up' => function (Builder $schema) use ($tableName, $columnDefinitions) {
|
'up' => function (Builder $schema) use ($tableName, $columnDefinitions) {
|
||||||
|
@ -82,7 +82,7 @@ abstract class Migration
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function dropColumns($tableName, array $columnDefinitions): array
|
public static function dropColumns(string $tableName, array $columnDefinitions): array
|
||||||
{
|
{
|
||||||
$inverse = static::addColumns($tableName, $columnDefinitions);
|
$inverse = static::addColumns($tableName, $columnDefinitions);
|
||||||
|
|
||||||
|
@ -92,12 +92,12 @@ abstract class Migration
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function renameColumn($tableName, $from, $to): array
|
public static function renameColumn(string $tableName, string $from, string $to): array
|
||||||
{
|
{
|
||||||
return static::renameColumns($tableName, [$from => $to]);
|
return static::renameColumns($tableName, [$from => $to]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function renameColumns($tableName, array $columnNames): array
|
public static function renameColumns(string $tableName, array $columnNames): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'up' => function (Builder $schema) use ($tableName, $columnNames) {
|
'up' => function (Builder $schema) use ($tableName, $columnNames) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ trait ScopeVisibilityTrait
|
||||||
*/
|
*/
|
||||||
protected static array $visibilityScopers = [];
|
protected static array $visibilityScopers = [];
|
||||||
|
|
||||||
public static function registerVisibilityScoper($scoper, ?string $ability = null): void
|
public static function registerVisibilityScoper(callable $scoper, ?string $ability = null): void
|
||||||
{
|
{
|
||||||
$model = static::class;
|
$model = static::class;
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,16 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function can(User $actor, string $ability)
|
public function can(User $actor, string $ability): ?string
|
||||||
{
|
{
|
||||||
if ($actor->hasPermission('discussion.'.$ability)) {
|
if ($actor->hasPermission('discussion.'.$ability)) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rename(User $actor, Discussion $discussion)
|
public function rename(User $actor, Discussion $discussion): ?string
|
||||||
{
|
{
|
||||||
if ($discussion->user_id == $actor->id && $actor->can('reply', $discussion)) {
|
if ($discussion->user_id == $actor->id && $actor->can('reply', $discussion)) {
|
||||||
$allowRenaming = $this->settings->get('allow_renaming');
|
$allowRenaming = $this->settings->get('allow_renaming');
|
||||||
|
@ -39,9 +41,11 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hide(User $actor, Discussion $discussion)
|
public function hide(User $actor, Discussion $discussion): ?string
|
||||||
{
|
{
|
||||||
if ($discussion->user_id == $actor->id
|
if ($discussion->user_id == $actor->id
|
||||||
&& $discussion->participant_count <= 1
|
&& $discussion->participant_count <= 1
|
||||||
|
@ -50,5 +54,7 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use Flarum\User\User;
|
||||||
class EditDiscussion
|
class EditDiscussion
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public $discussionId,
|
public int $discussionId,
|
||||||
public User $actor,
|
public User $actor,
|
||||||
public array $data
|
public array $data
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -14,11 +14,11 @@ use Flarum\User\User;
|
||||||
class ReadDiscussion
|
class ReadDiscussion
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public $discussionId,
|
public int $discussionId,
|
||||||
/** The user to mark the discussion as read for */
|
/** The user to mark the discussion as read for */
|
||||||
public User $actor,
|
public User $actor,
|
||||||
/** The number of the post to mark as read */
|
/** The number of the post to mark as read */
|
||||||
public $lastReadPostNumber
|
public int $lastReadPostNumber
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class AuthorFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), $filterValue, $negate);
|
$this->constrain($filterState->getQuery(), $filterValue, $negate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function constrain(Builder $query, string|array $rawUsernames, $negate)
|
protected function constrain(Builder $query, string|array $rawUsernames, bool $negate): void
|
||||||
{
|
{
|
||||||
$usernames = $this->asStringArray($rawUsernames);
|
$usernames = $this->asStringArray($rawUsernames);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class CreatedFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), Arr::get($matches, 1), Arr::get($matches, 3), $negate);
|
$this->constrain($filterState->getQuery(), Arr::get($matches, 1), Arr::get($matches, 3), $negate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function constrain(Builder $query, ?string $firstDate, ?string $secondDate, $negate)
|
public function constrain(Builder $query, ?string $firstDate, ?string $secondDate, bool $negate): void
|
||||||
{
|
{
|
||||||
// If we've just been provided with a single YYYY-MM-DD date, then find
|
// If we've just been provided with a single YYYY-MM-DD date, then find
|
||||||
// discussions that were started on that exact date. But if we've been
|
// discussions that were started on that exact date. But if we've been
|
||||||
|
|
|
@ -37,7 +37,7 @@ class HiddenFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), $negate);
|
$this->constrain($filterState->getQuery(), $negate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function constrain(Builder $query, bool $negate)
|
protected function constrain(Builder $query, bool $negate): void
|
||||||
{
|
{
|
||||||
$query->where(function ($query) use ($negate) {
|
$query->where(function ($query) use ($negate) {
|
||||||
if ($negate) {
|
if ($negate) {
|
||||||
|
|
|
@ -52,7 +52,7 @@ class UnreadFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), $filterState->getActor(), $negate);
|
$this->constrain($filterState->getQuery(), $filterState->getActor(), $negate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function constrain(Builder $query, User $actor, bool $negate)
|
protected function constrain(Builder $query, User $actor, bool $negate): void
|
||||||
{
|
{
|
||||||
if ($actor->exists) {
|
if ($actor->exists) {
|
||||||
$readIds = $this->discussions->getReadIdsQuery($actor);
|
$readIds = $this->discussions->getReadIdsQuery($actor);
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Console implements ExtenderInterface
|
||||||
* The callback should apply relevant methods to $event, and does not need to return anything.
|
* The callback should apply relevant methods to $event, and does not need to return anything.
|
||||||
*
|
*
|
||||||
* @see https://laravel.com/api/8.x/Illuminate/Console/Scheduling/Event.html
|
* @see https://laravel.com/api/8.x/Illuminate/Console/Scheduling/Event.html
|
||||||
* @see https://laravel.com/docs/8.x/scheduling#schedule-frequency-options
|
* @see https://laravel.com/docs/10.x/scheduling#schedule-frequency-options
|
||||||
* for more information on available methods and what they do.
|
* for more information on available methods and what they do.
|
||||||
*
|
*
|
||||||
* @param array $args An array of args to call the command with.
|
* @param array $args An array of args to call the command with.
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Event implements ExtenderInterface
|
||||||
* Event subscribers are classes that may subscribe to multiple events from within the subscriber class itself,
|
* Event subscribers are classes that may subscribe to multiple events from within the subscriber class itself,
|
||||||
* allowing you to define several event handlers within a single class.
|
* allowing you to define several event handlers within a single class.
|
||||||
*
|
*
|
||||||
* @see https://laravel.com/docs/8.x/events#writing-event-subscribers
|
* @see https://laravel.com/docs/10.x/events#writing-event-subscribers
|
||||||
*
|
*
|
||||||
* @param string $subscriber: The ::class attribute of the subscriber class.
|
* @param string $subscriber: The ::class attribute of the subscriber class.
|
||||||
* @return self
|
* @return self
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Filesystem implements ExtenderInterface
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @see https://laravel.com/docs/8.x/filesystem#configuration
|
* @see https://laravel.com/docs/10.x/filesystem#configuration
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -61,7 +61,7 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function registerLocale(Container $container, LocaleManager $locales, Extension $extension, $locale, $title): void
|
private function registerLocale(Container $container, LocaleManager $locales, Extension $extension, string $locale, string $title): void
|
||||||
{
|
{
|
||||||
$locales->addLocale($locale, $title);
|
$locales->addLocale($locale, $title);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Model implements ExtenderInterface
|
||||||
* Add a custom attribute type cast. Should not be applied to non-extension attributes.
|
* Add a custom attribute type cast. Should not be applied to non-extension attributes.
|
||||||
*
|
*
|
||||||
* @param string $attribute: The new attribute name.
|
* @param string $attribute: The new attribute name.
|
||||||
* @param string $cast: The cast type. See https://laravel.com/docs/8.x/eloquent-mutators#attribute-casting
|
* @param string $cast: The cast type. See https://laravel.com/docs/10.x/eloquent-mutators#attribute-casting
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function cast(string $attribute, string $cast): self
|
public function cast(string $attribute, string $cast): self
|
||||||
|
|
|
@ -34,7 +34,7 @@ use Illuminate\Contracts\Container\Container;
|
||||||
*/
|
*/
|
||||||
class ModelPrivate implements ExtenderInterface
|
class ModelPrivate implements ExtenderInterface
|
||||||
{
|
{
|
||||||
private $checkers = [];
|
private array $checkers = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param class-string<AbstractModel> $modelClass: The ::class attribute of the model you are applying private checkers to.
|
* @param class-string<AbstractModel> $modelClass: The ::class attribute of the model you are applying private checkers to.
|
||||||
|
|
|
@ -148,7 +148,7 @@ class Routes implements ExtenderInterface
|
||||||
return $this->route('DELETE', $path, $name, $handler);
|
return $this->route('DELETE', $path, $name, $handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function route(string $httpMethod, string $path, string $name, $handler): self
|
private function route(string $httpMethod, string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
$this->routes[] = [
|
$this->routes[] = [
|
||||||
'method' => $httpMethod,
|
'method' => $httpMethod,
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ExtensionBootError extends Exception
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public Extension $extension,
|
public Extension $extension,
|
||||||
public $extender,
|
public object $extender,
|
||||||
Throwable $previous = null
|
Throwable $previous = null
|
||||||
) {
|
) {
|
||||||
$extenderClass = get_class($extender);
|
$extenderClass = get_class($extender);
|
||||||
|
|
|
@ -84,7 +84,7 @@ class Extension implements Arrayable
|
||||||
$this->assignId();
|
$this->assignId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function nameToId($name): string
|
protected static function nameToId(string $name): string
|
||||||
{
|
{
|
||||||
[$vendor, $package] = explode('/', $name);
|
[$vendor, $package] = explode('/', $name);
|
||||||
$package = str_replace(['flarum-ext-', 'flarum-'], '', $package);
|
$package = str_replace(['flarum-ext-', 'flarum-'], '', $package);
|
||||||
|
@ -114,12 +114,12 @@ class Extension implements Arrayable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($name)
|
public function __get(string $name): mixed
|
||||||
{
|
{
|
||||||
return $this->composerJsonAttribute(Str::snake($name, '-'));
|
return $this->composerJsonAttribute(Str::snake($name, '-'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __isset($name)
|
public function __isset(string $name): bool
|
||||||
{
|
{
|
||||||
return isset($this->{$name}) || $this->composerJsonAttribute(Str::snake($name, '-'));
|
return isset($this->{$name}) || $this->composerJsonAttribute(Str::snake($name, '-'));
|
||||||
}
|
}
|
||||||
|
@ -127,12 +127,9 @@ class Extension implements Arrayable
|
||||||
/**
|
/**
|
||||||
* Dot notation getter for composer.json attributes.
|
* Dot notation getter for composer.json attributes.
|
||||||
*
|
*
|
||||||
* @see https://laravel.com/docs/8.x/helpers#arrays
|
* @see https://laravel.com/docs/10.x/helpers#arrays
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public function composerJsonAttribute($name): mixed
|
public function composerJsonAttribute(string $name): mixed
|
||||||
{
|
{
|
||||||
return Arr::get($this->composerJson, $name);
|
return Arr::get($this->composerJson, $name);
|
||||||
}
|
}
|
||||||
|
@ -433,7 +430,7 @@ class Extension implements Arrayable
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function migrate(Migrator $migrator, $direction = 'up'): ?int
|
public function migrate(Migrator $migrator, string $direction = 'up'): ?int
|
||||||
{
|
{
|
||||||
if (! $this->hasMigrations()) {
|
if (! $this->hasMigrations()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -18,7 +18,7 @@ trait ValidateFilterTrait
|
||||||
* @throws FlarumValidationException
|
* @throws FlarumValidationException
|
||||||
* @return array<string>|array<array>
|
* @return array<string>|array<array>
|
||||||
*/
|
*/
|
||||||
protected function asStringArray($filterValue, bool $multidimensional = false): array
|
protected function asStringArray(string|array $filterValue, bool $multidimensional = false): array
|
||||||
{
|
{
|
||||||
if (is_array($filterValue)) {
|
if (is_array($filterValue)) {
|
||||||
$value = array_map(function ($subValue) use ($multidimensional) {
|
$value = array_map(function ($subValue) use ($multidimensional) {
|
||||||
|
@ -40,7 +40,7 @@ trait ValidateFilterTrait
|
||||||
/**
|
/**
|
||||||
* @throws FlarumValidationException
|
* @throws FlarumValidationException
|
||||||
*/
|
*/
|
||||||
protected function asString($filterValue): string
|
protected function asString(string|array $filterValue): string
|
||||||
{
|
{
|
||||||
if (is_array($filterValue)) {
|
if (is_array($filterValue)) {
|
||||||
$this->throwValidationException('core.api.invalid_filter_type.must_not_be_array_message');
|
$this->throwValidationException('core.api.invalid_filter_type.must_not_be_array_message');
|
||||||
|
@ -52,7 +52,7 @@ trait ValidateFilterTrait
|
||||||
/**
|
/**
|
||||||
* @throws FlarumValidationException
|
* @throws FlarumValidationException
|
||||||
*/
|
*/
|
||||||
protected function asInt($filterValue): int
|
protected function asInt(string|array $filterValue): int
|
||||||
{
|
{
|
||||||
if (! is_numeric($filterValue)) {
|
if (! is_numeric($filterValue)) {
|
||||||
$this->throwValidationException('core.api.invalid_filter_type.must_be_numeric_message');
|
$this->throwValidationException('core.api.invalid_filter_type.must_be_numeric_message');
|
||||||
|
@ -65,7 +65,7 @@ trait ValidateFilterTrait
|
||||||
* @throws FlarumValidationException
|
* @throws FlarumValidationException
|
||||||
* @return array<int>
|
* @return array<int>
|
||||||
*/
|
*/
|
||||||
protected function asIntArray($filterValue): array
|
protected function asIntArray(string|array $filterValue): array
|
||||||
{
|
{
|
||||||
return array_map(function ($value) {
|
return array_map(function ($value) {
|
||||||
return $this->asInt($value);
|
return $this->asInt($value);
|
||||||
|
@ -75,7 +75,7 @@ trait ValidateFilterTrait
|
||||||
/**
|
/**
|
||||||
* @throws FlarumValidationException
|
* @throws FlarumValidationException
|
||||||
*/
|
*/
|
||||||
protected function asBool($filterValue): bool
|
protected function asBool(string|array $filterValue): bool
|
||||||
{
|
{
|
||||||
return $this->asString($filterValue) === '1';
|
return $this->asString($filterValue) === '1';
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ class Formatter
|
||||||
return $renderer->render($xml);
|
return $renderer->render($xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unparse(string $xml, $context = null): string
|
public function unparse(string $xml, mixed $context = null): string
|
||||||
{
|
{
|
||||||
foreach ($this->unparsingCallbacks as $callback) {
|
foreach ($this->unparsingCallbacks as $callback) {
|
||||||
$xml = $callback($context, $xml);
|
$xml = $callback($context, $xml);
|
||||||
|
|
|
@ -66,7 +66,7 @@ class Registration
|
||||||
return $this->suggest('email', $email);
|
return $this->suggest('email', $email);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPayload($payload): self
|
public function setPayload(mixed $payload): self
|
||||||
{
|
{
|
||||||
$this->payload = $payload;
|
$this->payload = $payload;
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ class Discussion
|
||||||
*
|
*
|
||||||
* @throws RouteNotFoundException
|
* @throws RouteNotFoundException
|
||||||
*/
|
*/
|
||||||
protected function getApiDocument(Request $request, string $id, array $params)
|
protected function getApiDocument(Request $request, string $id, array $params): object
|
||||||
{
|
{
|
||||||
$params['bySlug'] = true;
|
$params['bySlug'] = true;
|
||||||
$response = $this->api
|
$response = $this->api
|
||||||
|
|
|
@ -44,7 +44,7 @@ class User
|
||||||
*
|
*
|
||||||
* @throws ModelNotFoundException
|
* @throws ModelNotFoundException
|
||||||
*/
|
*/
|
||||||
protected function getApiDocument(Request $request, string $username)
|
protected function getApiDocument(Request $request, string $username): object
|
||||||
{
|
{
|
||||||
$response = $this->api->withParentRequest($request)->withQueryParams(['bySlug' => true])->get("/users/$username");
|
$response = $this->api->withParentRequest($request)->withQueryParams(['bySlug' => true])->get("/users/$username");
|
||||||
$statusCode = $response->getStatusCode();
|
$statusCode = $response->getStatusCode();
|
||||||
|
|
|
@ -33,7 +33,7 @@ abstract class AbstractValidator
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addConfiguration($callable): void
|
public function addConfiguration(callable $callable): void
|
||||||
{
|
{
|
||||||
$this->configuration[] = $callable;
|
$this->configuration[] = $callable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Config implements ArrayAccess
|
||||||
return $this->data['offline'] ?? false;
|
return $this->data['offline'] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function requireKeys(...$keys): void
|
private function requireKeys(mixed ...$keys): void
|
||||||
{
|
{
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
if (! array_key_exists($key, $this->data)) {
|
if (! array_key_exists($key, $this->data)) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Container extends LaravelContainer
|
||||||
*
|
*
|
||||||
* @TODO: Implement the Application contract and merge the container into it.
|
* @TODO: Implement the Application contract and merge the container into it.
|
||||||
*/
|
*/
|
||||||
public function __call(string $name, array $arguments)
|
public function __call(string $name, array $arguments): mixed
|
||||||
{
|
{
|
||||||
return $this->get('flarum')->$name(...$arguments);
|
return $this->get('flarum')->$name(...$arguments);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,14 @@ trait DispatchEventsTrait
|
||||||
/**
|
/**
|
||||||
* Dispatch all events for an entity.
|
* Dispatch all events for an entity.
|
||||||
*/
|
*/
|
||||||
public function dispatchEventsFor($entity, User $actor = null): void
|
public function dispatchEventsFor(mixed $entity, User $actor = null): void
|
||||||
{
|
{
|
||||||
|
if (! method_exists($entity, 'releaseEvents')) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'The entity must use the EventGeneratorTrait trait in order to dispatch events.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($entity->releaseEvents() as $event) {
|
foreach ($entity->releaseEvents() as $event) {
|
||||||
$event->actor = $actor;
|
$event->actor = $actor;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ValidationExceptionHandler
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildDetails(array $messages, $pointer): array
|
private function buildDetails(array $messages, string $pointer): array
|
||||||
{
|
{
|
||||||
return array_map(function ($path, $detail) use ($pointer) {
|
return array_map(function ($path, $detail) use ($pointer) {
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -13,10 +13,7 @@ trait EventGeneratorTrait
|
||||||
{
|
{
|
||||||
protected array $pendingEvents = [];
|
protected array $pendingEvents = [];
|
||||||
|
|
||||||
/**
|
public function raise(object $event): void
|
||||||
* Raise a new event.
|
|
||||||
*/
|
|
||||||
public function raise($event): void
|
|
||||||
{
|
{
|
||||||
$this->pendingEvents[] = $event;
|
$this->pendingEvents[] = $event;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ class InstalledApp implements AppInterface
|
||||||
return $this->config->url()->getPath() ?: '/';
|
return $this->config->url()->getPath() ?: '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function subPath($pathName): string
|
protected function subPath(string $pathName): string
|
||||||
{
|
{
|
||||||
return '/'.($this->config['paths'][$pathName] ?? $pathName);
|
return '/'.($this->config['paths'][$pathName] ?? $pathName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Paths
|
||||||
$this->paths['vendor'] = $this->vendor ?? $this->base.'/vendor';
|
$this->paths['vendor'] = $this->vendor ?? $this->base.'/vendor';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($name): ?string
|
public function __get(string $name): ?string
|
||||||
{
|
{
|
||||||
return $this->paths[$name] ?? null;
|
return $this->paths[$name] ?? null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,12 @@ class Site
|
||||||
)->extendWith(static::loadExtenders($paths->base));
|
)->extendWith(static::loadExtenders($paths->base));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function hasConfigFile($basePath): bool
|
protected static function hasConfigFile(string $basePath): bool
|
||||||
{
|
{
|
||||||
return file_exists("$basePath/config.php");
|
return file_exists("$basePath/config.php");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function loadConfig($basePath): Config
|
protected static function loadConfig(string $basePath): Config
|
||||||
{
|
{
|
||||||
$config = include "$basePath/config.php";
|
$config = include "$basePath/config.php";
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class Site
|
||||||
return new Config($config);
|
return new Config($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function loadExtenders($basePath): array
|
protected static function loadExtenders(string $basePath): array
|
||||||
{
|
{
|
||||||
$extenderFile = "$basePath/extend.php";
|
$extenderFile = "$basePath/extend.php";
|
||||||
|
|
||||||
|
|
|
@ -44,35 +44,35 @@ class Assets
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function js($sources): static
|
public function js(callable $callback): static
|
||||||
{
|
{
|
||||||
$this->addSources('js', $sources);
|
$this->addSources('js', $callback);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function css($callback): static
|
public function css(callable $callback): static
|
||||||
{
|
{
|
||||||
$this->addSources('css', $callback);
|
$this->addSources('css', $callback);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function localeJs($callback): static
|
public function localeJs(callable $callback): static
|
||||||
{
|
{
|
||||||
$this->addSources('localeJs', $callback);
|
$this->addSources('localeJs', $callback);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function localeCss($callback): static
|
public function localeCss(callable $callback): static
|
||||||
{
|
{
|
||||||
$this->addSources('localeCss', $callback);
|
$this->addSources('localeCss', $callback);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addSources($type, $callback): void
|
private function addSources(string $type, callable $callback): void
|
||||||
{
|
{
|
||||||
$this->sources[$type][] = $callback;
|
$this->sources[$type][] = $callback;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ class Assets
|
||||||
return $compiler;
|
return $compiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function makeJsCompiler(string $filename)
|
protected function makeJsCompiler(string $filename): JsCompiler
|
||||||
{
|
{
|
||||||
return resolve(JsCompiler::class, [
|
return resolve(JsCompiler::class, [
|
||||||
'assetsDir' => $this->assetsDir,
|
'assetsDir' => $this->assetsDir,
|
||||||
|
@ -163,7 +163,7 @@ class Assets
|
||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName(string $name)
|
public function setName(string $name): void
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ class Assets
|
||||||
return $this->assetsDir;
|
return $this->assetsDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setAssetsDir(Cloud $assetsDir)
|
public function setAssetsDir(Cloud $assetsDir): void
|
||||||
{
|
{
|
||||||
$this->assetsDir = $assetsDir;
|
$this->assetsDir = $assetsDir;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ class Assets
|
||||||
return $this->cacheDir;
|
return $this->cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCacheDir(?string $cacheDir)
|
public function setCacheDir(?string $cacheDir): void
|
||||||
{
|
{
|
||||||
$this->cacheDir = $cacheDir;
|
$this->cacheDir = $cacheDir;
|
||||||
}
|
}
|
||||||
|
@ -193,17 +193,17 @@ class Assets
|
||||||
return $this->lessImportDirs;
|
return $this->lessImportDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setLessImportDirs(array $lessImportDirs)
|
public function setLessImportDirs(array $lessImportDirs): void
|
||||||
{
|
{
|
||||||
$this->lessImportDirs = $lessImportDirs;
|
$this->lessImportDirs = $lessImportDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addLessImportOverrides(array $lessImportOverrides)
|
public function addLessImportOverrides(array $lessImportOverrides): void
|
||||||
{
|
{
|
||||||
$this->lessImportOverrides = array_merge($this->lessImportOverrides, $lessImportOverrides);
|
$this->lessImportOverrides = array_merge($this->lessImportOverrides, $lessImportOverrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addFileSourceOverrides(array $fileSourceOverrides)
|
public function addFileSourceOverrides(array $fileSourceOverrides): void
|
||||||
{
|
{
|
||||||
$this->fileSourceOverrides = array_merge($this->fileSourceOverrides, $fileSourceOverrides);
|
$this->fileSourceOverrides = array_merge($this->fileSourceOverrides, $fileSourceOverrides);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Flarum\Frontend\Compiler;
|
||||||
|
|
||||||
interface VersionerInterface
|
interface VersionerInterface
|
||||||
{
|
{
|
||||||
public function putRevision(string $file, ?string $revision);
|
public function putRevision(string $file, ?string $revision): void;
|
||||||
|
|
||||||
public function getRevision(string $file): ?string;
|
public function getRevision(string $file): ?string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,8 @@ class FrontendServiceProvider extends AbstractServiceProvider
|
||||||
$paths->vendor.'/components/font-awesome/less' => ''
|
$paths->vendor.'/components/font-awesome/less' => ''
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$assets->css([$this, 'addBaseCss']);
|
$assets->css($this->addBaseCss(...));
|
||||||
$assets->localeCss([$this, 'addBaseCss']);
|
$assets->localeCss($this->addBaseCss(...));
|
||||||
|
|
||||||
return $assets;
|
return $assets;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,10 +14,12 @@ use Flarum\User\User;
|
||||||
|
|
||||||
class GroupPolicy extends AbstractPolicy
|
class GroupPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
public function can(User $actor, string $ability)
|
public function can(User $actor, string $ability): ?string
|
||||||
{
|
{
|
||||||
if ($actor->hasPermission('group.'.$ability)) {
|
if ($actor->hasPermission('group.'.$ability)) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,12 @@ use Flarum\User\User;
|
||||||
|
|
||||||
class AccessTokenPolicy extends AbstractPolicy
|
class AccessTokenPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
public function revoke(User $actor, AccessToken $token)
|
public function revoke(User $actor, AccessToken $token): ?string
|
||||||
{
|
{
|
||||||
if ($token->user_id === $actor->id || $actor->hasPermission('moderateAccessTokens')) {
|
if ($token->user_id === $actor->id || $actor->hasPermission('moderateAccessTokens')) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class AuthenticateWithHeader implements Middleware
|
||||||
return $handler->handle($request);
|
return $handler->handle($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getUser($string): ?User
|
private function getUser(string $string): ?User
|
||||||
{
|
{
|
||||||
$parts = explode('=', trim($string));
|
$parts = explode('=', trim($string));
|
||||||
|
|
||||||
|
|
|
@ -30,32 +30,32 @@ class RouteCollection
|
||||||
$this->routeParser = new RouteParser\Std;
|
$this->routeParser = new RouteParser\Std;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($path, $name, $handler): self
|
public function get(string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
return $this->addRoute('GET', $path, $name, $handler);
|
return $this->addRoute('GET', $path, $name, $handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function post($path, $name, $handler): self
|
public function post(string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
return $this->addRoute('POST', $path, $name, $handler);
|
return $this->addRoute('POST', $path, $name, $handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function put($path, $name, $handler): self
|
public function put(string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
return $this->addRoute('PUT', $path, $name, $handler);
|
return $this->addRoute('PUT', $path, $name, $handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function patch($path, $name, $handler): self
|
public function patch(string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
return $this->addRoute('PATCH', $path, $name, $handler);
|
return $this->addRoute('PATCH', $path, $name, $handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($path, $name, $handler): self
|
public function delete(string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
return $this->addRoute('DELETE', $path, $name, $handler);
|
return $this->addRoute('DELETE', $path, $name, $handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addRoute($method, $path, $name, $handler): self
|
public function addRoute(string $method, string $path, string $name, callable|string $handler): self
|
||||||
{
|
{
|
||||||
if (isset($this->routes[$name])) {
|
if (isset($this->routes[$name])) {
|
||||||
throw new \RuntimeException("Route $name already exists");
|
throw new \RuntimeException("Route $name already exists");
|
||||||
|
@ -102,7 +102,7 @@ class RouteCollection
|
||||||
return $this->dataGenerator->getData();
|
return $this->dataGenerator->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fixPathPart(mixed $part, array $parameters, string $routeName)
|
protected function fixPathPart(mixed $part, array $parameters, string $routeName): string
|
||||||
{
|
{
|
||||||
if (! is_array($part)) {
|
if (! is_array($part)) {
|
||||||
return $part;
|
return $part;
|
||||||
|
|
|
@ -26,7 +26,7 @@ class RouteHandlerFactory
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toController($controller): Closure
|
public function toController(callable|string $controller): Closure
|
||||||
{
|
{
|
||||||
return function (Request $request, array $routeParams) use ($controller) {
|
return function (Request $request, array $routeParams) use ($controller) {
|
||||||
$controller = $this->resolveController($controller);
|
$controller = $this->resolveController($controller);
|
||||||
|
@ -60,7 +60,7 @@ class RouteHandlerFactory
|
||||||
return $this->toFrontend('admin', $content);
|
return $this->toFrontend('admin', $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveController($controller): Handler
|
private function resolveController(callable|string $controller): Handler
|
||||||
{
|
{
|
||||||
if (is_callable($controller)) {
|
if (is_callable($controller)) {
|
||||||
$controller = $this->container->call($controller);
|
$controller = $this->container->call($controller);
|
||||||
|
|
|
@ -52,7 +52,7 @@ class Server
|
||||||
*
|
*
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
private function safelyBootAndGetHandler()
|
private function safelyBootAndGetHandler() // @phpstan-ignore-line
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $this->site->bootApp()->getRequestHandler();
|
return $this->site->bootApp()->getRequestHandler();
|
||||||
|
|
|
@ -103,7 +103,7 @@ class InstallCommand extends AbstractCommand
|
||||||
->run();
|
->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function showProblems($problems): void
|
protected function showProblems(iterable $problems): void
|
||||||
{
|
{
|
||||||
$this->output->writeln(
|
$this->output->writeln(
|
||||||
'<error>Please fix the following problems before we can continue with the installation.</error>'
|
'<error>Please fix the following problems before we can continue with the installation.</error>'
|
||||||
|
|
|
@ -76,7 +76,7 @@ class UserDataProvider implements DataProviderInterface
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function askForAdminPassword()
|
private function askForAdminPassword(): string
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
$password = $this->secret('Admin password (required >= 8 characters):');
|
$password = $this->secret('Admin password (required >= 8 characters):');
|
||||||
|
@ -108,14 +108,14 @@ class UserDataProvider implements DataProviderInterface
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function ask($question, $default = null): mixed
|
private function ask(string $question, string $default = null): mixed
|
||||||
{
|
{
|
||||||
$question = new Question("<question>$question</question> ", $default);
|
$question = new Question("<question>$question</question> ", $default);
|
||||||
|
|
||||||
return $this->questionHelper->ask($this->input, $this->output, $question);
|
return $this->questionHelper->ask($this->input, $this->output, $question);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function secret($question): mixed
|
private function secret(string $question): mixed
|
||||||
{
|
{
|
||||||
$question = new Question("<question>$question</question> ");
|
$question = new Question("<question>$question</question> ");
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ class UserDataProvider implements DataProviderInterface
|
||||||
return $this->questionHelper->ask($this->input, $this->output, $question);
|
return $this->questionHelper->ask($this->input, $this->output, $question);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validationError($message): void
|
private function validationError(string $message): void
|
||||||
{
|
{
|
||||||
$this->output->writeln("<error>$message</error>");
|
$this->output->writeln("<error>$message</error>");
|
||||||
$this->output->writeln('Please try again.');
|
$this->output->writeln('Please try again.');
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Pipeline
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function on($event, callable $callback): self
|
public function on(string $event, callable $callback): self
|
||||||
{
|
{
|
||||||
$this->callbacks[$event] = $callback;
|
$this->callbacks[$event] = $callback;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class Pipeline
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fireCallbacks($event, Step $step): void
|
private function fireCallbacks(string $event, Step $step): void
|
||||||
{
|
{
|
||||||
if (isset($this->callbacks[$event])) {
|
if (isset($this->callbacks[$event])) {
|
||||||
($this->callbacks[$event])($step);
|
($this->callbacks[$event])($step);
|
||||||
|
|
|
@ -54,7 +54,7 @@ class WritablePaths implements PrerequisiteInterface
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getAbsolutePath($path)
|
private function getAbsolutePath(string $path): string
|
||||||
{
|
{
|
||||||
$path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path);
|
$path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path);
|
||||||
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
|
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
|
||||||
|
|
|
@ -49,7 +49,7 @@ class LocaleManager
|
||||||
return isset($this->locales[$locale]);
|
return isset($this->locales[$locale]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addTranslations(string $locale, $file, string $module = null): void
|
public function addTranslations(string $locale, string $file, string $module = null): void
|
||||||
{
|
{
|
||||||
$prefix = $module ? $module.'::' : '';
|
$prefix = $module ? $module.'::' : '';
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use Symfony\Component\Translation\MessageCatalogue;
|
||||||
|
|
||||||
class PrefixedYamlFileLoader extends YamlFileLoader
|
class PrefixedYamlFileLoader extends YamlFileLoader
|
||||||
{
|
{
|
||||||
public function load(mixed $resource, $locale, $domain = 'messages'): MessageCatalogue
|
public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
|
||||||
{
|
{
|
||||||
$catalogue = parent::load($resource['file'], $locale, $domain);
|
$catalogue = parent::load($resource['file'], $locale, $domain);
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,16 @@ class PostPolicy extends AbstractPolicy
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function can(User $actor, string $ability, Post $post)
|
public function can(User $actor, string $ability, Post $post): ?string
|
||||||
{
|
{
|
||||||
if ($actor->can($ability.'Posts', $post->discussion)) {
|
if ($actor->can($ability.'Posts', $post->discussion)) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(User $actor, Post $post)
|
public function edit(User $actor, Post $post): ?string
|
||||||
{
|
{
|
||||||
// A post is allowed to be edited if the user is the author, the post
|
// A post is allowed to be edited if the user is the author, the post
|
||||||
// hasn't been deleted by someone else, and the user is allowed to
|
// hasn't been deleted by someone else, and the user is allowed to
|
||||||
|
@ -43,9 +45,11 @@ class PostPolicy extends AbstractPolicy
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hide(User $actor, Post $post)
|
public function hide(User $actor, Post $post): ?string
|
||||||
{
|
{
|
||||||
if ($post->user_id == $actor->id && (! $post->hidden_at || $post->hidden_user_id == $actor->id) && $actor->can('reply', $post->discussion)) {
|
if ($post->user_id == $actor->id && (! $post->hidden_at || $post->hidden_user_id == $actor->id) && $actor->can('reply', $post->discussion)) {
|
||||||
$allowHiding = $this->settings->get('allow_hide_own_posts');
|
$allowHiding = $this->settings->get('allow_hide_own_posts');
|
||||||
|
@ -56,5 +60,7 @@ class PostPolicy extends AbstractPolicy
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Flarum\Foundation\ErrorHandling\Reporter;
|
||||||
use Flarum\Foundation\Paths;
|
use Flarum\Foundation\Paths;
|
||||||
use Illuminate\Container\Container as ContainerImplementation;
|
use Illuminate\Container\Container as ContainerImplementation;
|
||||||
use Illuminate\Contracts\Cache\Factory as CacheFactory;
|
use Illuminate\Contracts\Cache\Factory as CacheFactory;
|
||||||
|
use Illuminate\Contracts\Cache\Repository;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
|
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
|
||||||
use Illuminate\Contracts\Events\Dispatcher;
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
|
@ -91,29 +92,24 @@ class QueueServiceProvider extends AbstractServiceProvider
|
||||||
// Bind a simple cache manager that returns the cache store.
|
// Bind a simple cache manager that returns the cache store.
|
||||||
$this->container->singleton('cache', function (Container $container) {
|
$this->container->singleton('cache', function (Container $container) {
|
||||||
return new class($container) implements CacheFactory {
|
return new class($container) implements CacheFactory {
|
||||||
/**
|
public function __construct(
|
||||||
* @var Container
|
private readonly Container $container
|
||||||
*/
|
) {
|
||||||
private $container;
|
|
||||||
|
|
||||||
public function __construct(Container $container)
|
|
||||||
{
|
|
||||||
$this->container = $container;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function driver()
|
public function driver(): Repository
|
||||||
{
|
{
|
||||||
return $this->container['cache.store'];
|
return $this->container['cache.store'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to define this explicitly
|
// We have to define this explicitly
|
||||||
// so that we implement the interface.
|
// so that we implement the interface.
|
||||||
public function store($name = null)
|
public function store($name = null): mixed
|
||||||
{
|
{
|
||||||
return $this->__call($name, null);
|
return $this->__call($name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __call($name, $arguments)
|
public function __call(string $name, ?array $arguments): mixed
|
||||||
{
|
{
|
||||||
return call_user_func_array([$this->driver(), $name], $arguments);
|
return call_user_func_array([$this->driver(), $name], $arguments);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class DatabaseSettingsRepository implements SettingsRepositoryInterface
|
||||||
return $this->database->table('settings')->pluck('value', 'key')->all();
|
return $this->database->table('settings')->pluck('value', 'key')->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $key, $default = null): mixed
|
public function get(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
if (is_null($value = $this->database->table('settings')->where('key', $key)->value('value'))) {
|
if (is_null($value = $this->database->table('settings')->where('key', $key)->value('value'))) {
|
||||||
return $default;
|
return $default;
|
||||||
|
|
|
@ -19,7 +19,7 @@ class DefaultSettingsRepository implements SettingsRepositoryInterface
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $key, $default = null): mixed
|
public function get(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
// Global default overrules local default because local default is deprecated,
|
// Global default overrules local default because local default is deprecated,
|
||||||
// and will be removed in 2.0
|
// and will be removed in 2.0
|
||||||
|
|
|
@ -31,7 +31,7 @@ class MemoryCacheSettingsRepository implements SettingsRepositoryInterface
|
||||||
return $this->cache;
|
return $this->cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $key, $default = null): mixed
|
public function get(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
if (array_key_exists($key, $this->cache)) {
|
if (array_key_exists($key, $this->cache)) {
|
||||||
return $this->cache[$key];
|
return $this->cache[$key];
|
||||||
|
|
|
@ -36,7 +36,7 @@ class OverrideSettingsRepository implements SettingsRepositoryInterface
|
||||||
return array_merge($this->inner->all(), $this->overrides);
|
return array_merge($this->inner->all(), $this->overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $key, $default = null): mixed
|
public function get(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
if (array_key_exists($key, $this->overrides)) {
|
if (array_key_exists($key, $this->overrides)) {
|
||||||
return $this->overrides[$key];
|
return $this->overrides[$key];
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface SettingsRepositoryInterface
|
||||||
/**
|
/**
|
||||||
* @todo remove deprecated $default in 2.0
|
* @todo remove deprecated $default in 2.0
|
||||||
*/
|
*/
|
||||||
public function get(string $key, $default = null): mixed;
|
public function get(string $key, mixed $default = null): mixed;
|
||||||
|
|
||||||
public function set(string $key, mixed $value): void;
|
public function set(string $key, mixed $value): void;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class UninstalledSettingsRepository implements SettingsRepositoryInterface
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $key, $default = null): mixed
|
public function get(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
namespace Flarum\User\Access;
|
namespace Flarum\User\Access;
|
||||||
|
|
||||||
|
use Flarum\Database\AbstractModel;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
abstract class AbstractPolicy
|
abstract class AbstractPolicy
|
||||||
|
@ -39,7 +40,7 @@ abstract class AbstractPolicy
|
||||||
return static::FORCE_DENY;
|
return static::FORCE_DENY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkAbility(User $actor, string $ability, $instance)
|
public function checkAbility(User $actor, string $ability, string|AbstractModel|null $instance): ?string
|
||||||
{
|
{
|
||||||
// If a specific method for this ability is defined,
|
// If a specific method for this ability is defined,
|
||||||
// call that and return any non-null results
|
// call that and return any non-null results
|
||||||
|
@ -55,6 +56,8 @@ abstract class AbstractPolicy
|
||||||
if (method_exists($this, 'can')) {
|
if (method_exists($this, 'can')) {
|
||||||
return $this->sanitizeResult(call_user_func_array([$this, 'can'], [$actor, $ability, $instance]));
|
return $this->sanitizeResult(call_user_func_array([$this, 'can'], [$actor, $ability, $instance]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,6 +46,7 @@ class Gate
|
||||||
public function allows(User $actor, string $ability, string|AbstractModel|null $model): bool
|
public function allows(User $actor, string $ability, string|AbstractModel|null $model): bool
|
||||||
{
|
{
|
||||||
$results = [];
|
$results = [];
|
||||||
|
/** @var AbstractPolicy[] $appliedPolicies */
|
||||||
$appliedPolicies = [];
|
$appliedPolicies = [];
|
||||||
|
|
||||||
if ($model) {
|
if ($model) {
|
||||||
|
|
|
@ -13,14 +13,16 @@ use Flarum\User\User;
|
||||||
|
|
||||||
class UserPolicy extends AbstractPolicy
|
class UserPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
public function can(User $actor, string $ability)
|
public function can(User $actor, string $ability): ?string
|
||||||
{
|
{
|
||||||
if ($actor->hasPermission('user.'.$ability)) {
|
if ($actor->hasPermission('user.'.$ability)) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function editCredentials(User $actor, User $user)
|
public function editCredentials(User $actor, User $user): ?string
|
||||||
{
|
{
|
||||||
if ($user->isAdmin() && ! $actor->isAdmin()) {
|
if ($user->isAdmin() && ! $actor->isAdmin()) {
|
||||||
return $this->deny();
|
return $this->deny();
|
||||||
|
@ -29,5 +31,7 @@ class UserPolicy extends AbstractPolicy
|
||||||
if ($actor->hasPermission('user.editCredentials')) {
|
if ($actor->hasPermission('user.editCredentials')) {
|
||||||
return $this->allow();
|
return $this->allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ class AvatarValidator extends AbstractValidator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function raise($error, array $parameters = [], $rule = null): void
|
protected function raise(string $error, array $parameters = [], string $rule = null): void
|
||||||
{
|
{
|
||||||
// When we switched to intl ICU message format, the translation parameters
|
// When we switched to intl ICU message format, the translation parameters
|
||||||
// have become required to be in the format `{param}`.
|
// have become required to be in the format `{param}`.
|
||||||
|
|
|
@ -96,7 +96,7 @@ class RegisterUserHandler
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applyToken(User $user, RegistrationToken $token)
|
private function applyToken(User $user, RegistrationToken $token): void
|
||||||
{
|
{
|
||||||
foreach ($token->user_attributes as $k => $v) {
|
foreach ($token->user_attributes as $k => $v) {
|
||||||
if ($k === 'avatar_url') {
|
if ($k === 'avatar_url') {
|
||||||
|
|
|
@ -53,7 +53,7 @@ class EmailFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), $filterValue, $negate);
|
$this->constrain($filterState->getQuery(), $filterValue, $negate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function constrain(Builder $query, $rawEmail, bool $negate): void
|
protected function constrain(Builder $query, string|array $rawEmail, bool $negate): void
|
||||||
{
|
{
|
||||||
$email = $this->asString($rawEmail);
|
$email = $this->asString($rawEmail);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class GroupFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||||
$this->constrain($filterState->getQuery(), $filterState->getActor(), $filterValue, $negate);
|
$this->constrain($filterState->getQuery(), $filterState->getActor(), $filterValue, $negate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function constrain(Builder $query, User $actor, $rawQuery, bool $negate): void
|
protected function constrain(Builder $query, User $actor, string|array $rawQuery, bool $negate): void
|
||||||
{
|
{
|
||||||
$groupIdentifiers = $this->asStringArray($rawQuery);
|
$groupIdentifiers = $this->asStringArray($rawQuery);
|
||||||
$groupQuery = Group::whereVisibleTo($actor);
|
$groupQuery = Group::whereVisibleTo($actor);
|
||||||
|
|
|
@ -114,7 +114,7 @@ if (! function_exists('config')) {
|
||||||
/**
|
/**
|
||||||
* @deprecated do not use, will be transferred to flarum/laravel-helpers.
|
* @deprecated do not use, will be transferred to flarum/laravel-helpers.
|
||||||
*/
|
*/
|
||||||
function config(string $key, $default = null)
|
function config(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
return resolve(Repository::class)->get($key, $default);
|
return resolve(Repository::class)->get($key, $default);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ includes:
|
||||||
- php-packages/phpstan/extension.neon
|
- php-packages/phpstan/extension.neon
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: 5
|
level: 6
|
||||||
paths:
|
paths:
|
||||||
- framework/core/src
|
- framework/core/src
|
||||||
- extensions/akismet/src
|
- extensions/akismet/src
|
||||||
|
@ -36,4 +36,5 @@ parameters:
|
||||||
excludePaths:
|
excludePaths:
|
||||||
- *.blade.php
|
- *.blade.php
|
||||||
checkMissingIterableValueType: false
|
checkMissingIterableValueType: false
|
||||||
|
checkGenericClassInNonGenericObjectType: false
|
||||||
databaseMigrationsPath: ['framework/core/migrations']
|
databaseMigrationsPath: ['framework/core/migrations']
|
||||||
|
|
Loading…
Reference in New Issue
Block a user