diff --git a/.github/workflows/REUSABLE_backend.yml b/.github/workflows/REUSABLE_backend.yml index d71b7483b..57923a412 100644 --- a/.github/workflows/REUSABLE_backend.yml +++ b/.github/workflows/REUSABLE_backend.yml @@ -25,7 +25,7 @@ on: description: Versions of PHP to test with. Should be array of strings encoded as JSON array type: string required: false - default: '["7.3", "7.4", "8.0", "8.1", "8.2"]' + default: '["8.1", "8.2"]' php_extensions: description: PHP extensions to install. diff --git a/composer.json b/composer.json index 0a26c6b6b..92672747b 100644 --- a/composer.json +++ b/composer.json @@ -85,7 +85,7 @@ "flarum/testing": "self.version" }, "require": { - "php": ">=7.3", + "php": "^8.1", "ext-json": "*", "components/font-awesome": "^5.14.0", "composer/composer": "^2.0", diff --git a/extensions/akismet/src/Listener/SubmitHam.php b/extensions/akismet/src/Listener/SubmitHam.php index bdc3770a3..2aa232275 100644 --- a/extensions/akismet/src/Listener/SubmitHam.php +++ b/extensions/akismet/src/Listener/SubmitHam.php @@ -14,17 +14,12 @@ use Flarum\Approval\Event\PostWasApproved; class SubmitHam { - /** - * @var Akismet - */ - protected $akismet; - - public function __construct(Akismet $akismet) - { - $this->akismet = $akismet; + public function __construct( + protected Akismet $akismet + ) { } - public function handle(PostWasApproved $event) + public function handle(PostWasApproved $event): void { if (! $this->akismet->isConfigured()) { return; diff --git a/extensions/akismet/src/Listener/SubmitSpam.php b/extensions/akismet/src/Listener/SubmitSpam.php index 732a17f70..269abcfaf 100644 --- a/extensions/akismet/src/Listener/SubmitSpam.php +++ b/extensions/akismet/src/Listener/SubmitSpam.php @@ -14,17 +14,12 @@ use Flarum\Post\Event\Hidden; class SubmitSpam { - /** - * @var Akismet - */ - protected $akismet; - - public function __construct(Akismet $akismet) - { - $this->akismet = $akismet; + public function __construct( + protected Akismet $akismet + ) { } - public function handle(Hidden $event) + public function handle(Hidden $event): void { if (! $this->akismet->isConfigured()) { return; diff --git a/extensions/akismet/src/Listener/ValidatePost.php b/extensions/akismet/src/Listener/ValidatePost.php index d0855b1cc..f42603d79 100644 --- a/extensions/akismet/src/Listener/ValidatePost.php +++ b/extensions/akismet/src/Listener/ValidatePost.php @@ -18,22 +18,13 @@ use Flarum\Settings\SettingsRepositoryInterface; class ValidatePost { - /** - * @var Akismet - */ - protected $akismet; - /** - * @var SettingsRepositoryInterface - */ - private $settings; - - public function __construct(Akismet $akismet, SettingsRepositoryInterface $settings) - { - $this->akismet = $akismet; - $this->settings = $settings; + public function __construct( + protected Akismet $akismet, + protected SettingsRepositoryInterface $settings + ) { } - public function handle(Saving $event) + public function handle(Saving $event): void { if (! $this->akismet->isConfigured()) { return; diff --git a/extensions/akismet/src/Provider/AkismetProvider.php b/extensions/akismet/src/Provider/AkismetProvider.php index 5d3f61a74..22f02ec32 100644 --- a/extensions/akismet/src/Provider/AkismetProvider.php +++ b/extensions/akismet/src/Provider/AkismetProvider.php @@ -20,7 +20,7 @@ use Illuminate\Container\Container; class AkismetProvider extends AbstractServiceProvider { - public function register() + public function register(): void { $this->container->bind(Akismet::class, function (Container $container) { /** @var SettingsRepositoryInterface $settings */ diff --git a/extensions/approval/extend.php b/extensions/approval/extend.php index c18e612a8..85801046c 100644 --- a/extensions/approval/extend.php +++ b/extensions/approval/extend.php @@ -37,7 +37,7 @@ return [ ->cast('is_approved', 'bool'), (new Extend\ApiSerializer(BasicDiscussionSerializer::class)) - ->attribute('isApproved', function ($serializer, Discussion $discussion) { + ->attribute('isApproved', function (BasicDiscussionSerializer $serializer, Discussion $discussion): bool { return $discussion->is_approved; }), @@ -65,8 +65,8 @@ return [ ->scope(Access\ScopePrivateDiscussionVisibility::class, 'viewPrivate'), (new Extend\ModelPrivate(Discussion::class)) - ->checker([Listener\UnapproveNewContent::class, 'markUnapprovedContentAsPrivate']), + ->checker(Listener\UnapproveNewContent::markUnapprovedContentAsPrivate(...)), (new Extend\ModelPrivate(CommentPost::class)) - ->checker([Listener\UnapproveNewContent::class, 'markUnapprovedContentAsPrivate']), + ->checker(Listener\UnapproveNewContent::markUnapprovedContentAsPrivate(...)), ]; diff --git a/extensions/approval/src/Access/ScopePrivateDiscussionVisibility.php b/extensions/approval/src/Access/ScopePrivateDiscussionVisibility.php index 8f63c01e6..f8ab591c8 100644 --- a/extensions/approval/src/Access/ScopePrivateDiscussionVisibility.php +++ b/extensions/approval/src/Access/ScopePrivateDiscussionVisibility.php @@ -14,11 +14,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopePrivateDiscussionVisibility { - /** - * @param Builder $query - * @param User $actor - */ - public function __invoke(User $actor, Builder $query) + public function __invoke(User $actor, Builder $query): void { // All statements need to be wrapped in an orWhere, since we're adding a // subset of private discussions that should be visible, not restricting the visible diff --git a/extensions/approval/src/Access/ScopePrivatePostVisibility.php b/extensions/approval/src/Access/ScopePrivatePostVisibility.php index e276bdf43..e1dab2892 100644 --- a/extensions/approval/src/Access/ScopePrivatePostVisibility.php +++ b/extensions/approval/src/Access/ScopePrivatePostVisibility.php @@ -16,11 +16,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopePrivatePostVisibility { - /** - * @param Builder $query - * @param User $actor - */ - public function __invoke(User $actor, Builder $query) + public function __invoke(User $actor, Builder $query): void { // All statements need to be wrapped in an orWhere, since we're adding a // subset of private posts that should be visible, not restricting the visible diff --git a/extensions/approval/src/Access/TagPolicy.php b/extensions/approval/src/Access/TagPolicy.php index 0e9de76a8..9cb2e63a6 100755 --- a/extensions/approval/src/Access/TagPolicy.php +++ b/extensions/approval/src/Access/TagPolicy.php @@ -15,10 +15,7 @@ use Flarum\User\User; class TagPolicy extends AbstractPolicy { - /** - * @return bool|null - */ - public function addToDiscussion(User $actor, Tag $tag) + public function addToDiscussion(User $actor, Tag $tag): bool { return $actor->can('discussion.startWithoutApproval', $tag); } diff --git a/extensions/approval/src/Event/PostWasApproved.php b/extensions/approval/src/Event/PostWasApproved.php index 979b9d447..1ea39a7a4 100644 --- a/extensions/approval/src/Event/PostWasApproved.php +++ b/extensions/approval/src/Event/PostWasApproved.php @@ -14,25 +14,9 @@ use Flarum\User\User; class PostWasApproved { - /** - * The post that was approved. - * - * @var Post - */ - public $post; - - /** - * @var User - */ - public $actor; - - /** - * @param Post $post - * @param User $actor - */ - public function __construct(Post $post, User $actor) - { - $this->post = $post; - $this->actor = $actor; + public function __construct( + public Post $post, + public User $actor + ) { } } diff --git a/extensions/approval/src/Listener/ApproveContent.php b/extensions/approval/src/Listener/ApproveContent.php index e0b996f22..e3d259eb0 100755 --- a/extensions/approval/src/Listener/ApproveContent.php +++ b/extensions/approval/src/Listener/ApproveContent.php @@ -15,15 +15,12 @@ use Illuminate\Contracts\Events\Dispatcher; class ApproveContent { - /** - * @param Dispatcher $events - */ - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Saving::class, [$this, 'approvePost']); + $events->listen(Saving::class, $this->approvePost(...)); } - public function approvePost(Saving $event) + public function approvePost(Saving $event): void { $attributes = $event->data['attributes']; $post = $event->post; diff --git a/extensions/approval/src/Listener/UnapproveNewContent.php b/extensions/approval/src/Listener/UnapproveNewContent.php index d53965ba9..ddd9bdc0f 100644 --- a/extensions/approval/src/Listener/UnapproveNewContent.php +++ b/extensions/approval/src/Listener/UnapproveNewContent.php @@ -18,18 +18,12 @@ use Illuminate\Contracts\Events\Dispatcher; class UnapproveNewContent { - /** - * @param Dispatcher $events - */ - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Saving::class, [$this, 'unapproveNewPosts']); + $events->listen(Saving::class, $this->unapproveNewPosts(...)); } - /** - * @param Saving $event - */ - public function unapproveNewPosts(Saving $event) + public function unapproveNewPosts(Saving $event): void { $post = $event->post; @@ -63,14 +57,12 @@ class UnapproveNewContent } } - /** - * @param Discussion|CommentPost $instance - * @return bool|null - */ - public static function markUnapprovedContentAsPrivate($instance) + public static function markUnapprovedContentAsPrivate(Discussion|CommentPost $instance): ?bool { if (! $instance->is_approved) { return true; } + + return null; } } diff --git a/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php b/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php index 0db738ae5..5756542fd 100644 --- a/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php +++ b/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php @@ -13,7 +13,7 @@ use Flarum\Approval\Event\PostWasApproved; class UpdateDiscussionAfterPostApproval { - public function handle(PostWasApproved $event) + public function handle(PostWasApproved $event): void { $post = $event->post; $discussion = $post->discussion; diff --git a/extensions/bbcode/src/Configure.php b/extensions/bbcode/src/Configure.php index 89eb64d21..765c4c802 100644 --- a/extensions/bbcode/src/Configure.php +++ b/extensions/bbcode/src/Configure.php @@ -13,7 +13,7 @@ use s9e\TextFormatter\Configurator; class Configure { - public function __invoke(Configurator $config) + public function __invoke(Configurator $config): void { $this->addTagsFromRepositories($config); $this->adaptHighlightJs($config); diff --git a/extensions/bbcode/src/Render.php b/extensions/bbcode/src/Render.php index 2a2ed3cc3..d4967e806 100644 --- a/extensions/bbcode/src/Render.php +++ b/extensions/bbcode/src/Render.php @@ -9,19 +9,14 @@ namespace Flarum\BBCode; +use Flarum\Locale\TranslatorInterface; use s9e\TextFormatter\Renderer; -use Symfony\Contracts\Translation\TranslatorInterface; class Render { - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + protected TranslatorInterface $translator + ) { } public function __invoke(Renderer $renderer, $context, string $xml): string diff --git a/extensions/flags/src/Access/ScopeFlagVisibility.php b/extensions/flags/src/Access/ScopeFlagVisibility.php index 9e08e6182..8add2307f 100644 --- a/extensions/flags/src/Access/ScopeFlagVisibility.php +++ b/extensions/flags/src/Access/ScopeFlagVisibility.php @@ -16,17 +16,12 @@ use Illuminate\Database\Eloquent\Builder; class ScopeFlagVisibility { - /** - * @var ExtensionManager - */ - protected $extensions; - - public function __construct(ExtensionManager $extensions) - { - $this->extensions = $extensions; + public function __construct( + protected ExtensionManager $extensions + ) { } - public function __invoke(User $actor, Builder $query) + public function __invoke(User $actor, Builder $query): void { if ($this->extensions->isEnabled('flarum-tags')) { $query diff --git a/extensions/flags/src/AddCanFlagAttribute.php b/extensions/flags/src/AddCanFlagAttribute.php index da354daa2..83731dd37 100644 --- a/extensions/flags/src/AddCanFlagAttribute.php +++ b/extensions/flags/src/AddCanFlagAttribute.php @@ -16,20 +16,12 @@ use Flarum\User\User; class AddCanFlagAttribute { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @param SettingsRepositoryInterface $settings - */ - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - public function __invoke(PostSerializer $serializer, Post $post) + public function __invoke(PostSerializer $serializer, Post $post): bool { return $serializer->getActor()->can('flag', $post) && $this->checkFlagOwnPostSetting($serializer->getActor(), $post); } diff --git a/extensions/flags/src/AddFlagsApiAttributes.php b/extensions/flags/src/AddFlagsApiAttributes.php index c687bd099..f8a2f1292 100755 --- a/extensions/flags/src/AddFlagsApiAttributes.php +++ b/extensions/flags/src/AddFlagsApiAttributes.php @@ -15,20 +15,12 @@ use Flarum\User\User; class AddFlagsApiAttributes { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @param SettingsRepositoryInterface $settings - */ - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - public function __invoke(ForumSerializer $serializer) + public function __invoke(ForumSerializer $serializer): array { $attributes = [ 'canViewFlags' => $serializer->getActor()->hasPermissionLike('discussion.viewFlags') @@ -41,11 +33,7 @@ class AddFlagsApiAttributes return $attributes; } - /** - * @param User $actor - * @return int - */ - protected function getFlagCount(User $actor) + protected function getFlagCount(User $actor): int { return Flag::whereVisibleTo($actor)->distinct()->count('flags.post_id'); } diff --git a/extensions/flags/src/AddNewFlagCountAttribute.php b/extensions/flags/src/AddNewFlagCountAttribute.php index b7f65010d..45a1fd829 100644 --- a/extensions/flags/src/AddNewFlagCountAttribute.php +++ b/extensions/flags/src/AddNewFlagCountAttribute.php @@ -14,16 +14,12 @@ use Flarum\User\User; class AddNewFlagCountAttribute { - public function __invoke(CurrentUserSerializer $serializer, User $user) + public function __invoke(CurrentUserSerializer $serializer, User $user): int { - return (int) $this->getNewFlagCount($user); + return $this->getNewFlagCount($user); } - /** - * @param User $actor - * @return int - */ - protected function getNewFlagCount(User $actor) + protected function getNewFlagCount(User $actor): int { $query = Flag::whereVisibleTo($actor); diff --git a/extensions/flags/src/Api/Controller/CreateFlagController.php b/extensions/flags/src/Api/Controller/CreateFlagController.php index f746418c3..7d5b5c376 100644 --- a/extensions/flags/src/Api/Controller/CreateFlagController.php +++ b/extensions/flags/src/Api/Controller/CreateFlagController.php @@ -12,6 +12,7 @@ namespace Flarum\Flags\Api\Controller; use Flarum\Api\Controller\AbstractCreateController; use Flarum\Flags\Api\Serializer\FlagSerializer; use Flarum\Flags\Command\CreateFlag; +use Flarum\Flags\Flag; use Flarum\Http\RequestUtil; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; @@ -20,37 +21,20 @@ use Tobscure\JsonApi\Document; class CreateFlagController extends AbstractCreateController { - /** - * {@inheritdoc} - */ - public $serializer = FlagSerializer::class; + public ?string $serializer = FlagSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'post', 'post.flags', 'user' ]; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Flag { return $this->bus->dispatch( new CreateFlag(RequestUtil::getActor($request), Arr::get($request->getParsedBody(), 'data', [])) diff --git a/extensions/flags/src/Api/Controller/DeleteFlagsController.php b/extensions/flags/src/Api/Controller/DeleteFlagsController.php index c6b7a15b5..6253cae04 100644 --- a/extensions/flags/src/Api/Controller/DeleteFlagsController.php +++ b/extensions/flags/src/Api/Controller/DeleteFlagsController.php @@ -18,23 +18,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeleteFlagsController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new DeleteFlags(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request), $request->getParsedBody()) diff --git a/extensions/flags/src/Api/Controller/ListFlagsController.php b/extensions/flags/src/Api/Controller/ListFlagsController.php index edbeac38f..216f61b05 100644 --- a/extensions/flags/src/Api/Controller/ListFlagsController.php +++ b/extensions/flags/src/Api/Controller/ListFlagsController.php @@ -19,25 +19,16 @@ use Tobscure\JsonApi\Document; class ListFlagsController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = FlagSerializer::class; + public ?string $serializer = FlagSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'user', 'post', 'post.user', 'post.discussion' ]; - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); $include = $this->extractInclude($request); diff --git a/extensions/flags/src/Api/Serializer/FlagSerializer.php b/extensions/flags/src/Api/Serializer/FlagSerializer.php index f307e3d7a..f68a8bfd3 100644 --- a/extensions/flags/src/Api/Serializer/FlagSerializer.php +++ b/extensions/flags/src/Api/Serializer/FlagSerializer.php @@ -14,42 +14,34 @@ use Flarum\Api\Serializer\BasicUserSerializer; use Flarum\Api\Serializer\PostSerializer; use Flarum\Flags\Flag; use InvalidArgumentException; +use Tobscure\JsonApi\Relationship; class FlagSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'flags'; - protected function getDefaultAttributes($flag) + protected function getDefaultAttributes(object|array $model): array { - if (! ($flag instanceof Flag)) { + if (! ($model instanceof Flag)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.Flag::class ); } return [ - 'type' => $flag->type, - 'reason' => $flag->reason, - 'reasonDetail' => $flag->reason_detail, - 'createdAt' => $this->formatDate($flag->created_at), + 'type' => $model->type, + 'reason' => $model->reason, + 'reasonDetail' => $model->reason_detail, + 'createdAt' => $this->formatDate($model->created_at), ]; } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function post($flag) + protected function post(Flag $flag): ?Relationship { return $this->hasOne($flag, PostSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function user($flag) + protected function user(Flag $flag): ?Relationship { return $this->hasOne($flag, BasicUserSerializer::class); } diff --git a/extensions/flags/src/Command/CreateFlag.php b/extensions/flags/src/Command/CreateFlag.php index 9b9afcda6..2c7f23480 100644 --- a/extensions/flags/src/Command/CreateFlag.php +++ b/extensions/flags/src/Command/CreateFlag.php @@ -13,27 +13,9 @@ use Flarum\User\User; class CreateFlag { - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes of the new flag. - * - * @var array - */ - public $data; - - /** - * @param User $actor The user performing the action. - * @param array $data The attributes of the new flag. - */ - public function __construct(User $actor, array $data) - { - $this->actor = $actor; - $this->data = $data; + public function __construct( + public User $actor, + public array $data + ) { } } diff --git a/extensions/flags/src/Command/CreateFlagHandler.php b/extensions/flags/src/Command/CreateFlagHandler.php index 1798ef95d..3fbb79aac 100644 --- a/extensions/flags/src/Command/CreateFlagHandler.php +++ b/extensions/flags/src/Command/CreateFlagHandler.php @@ -13,58 +13,26 @@ use Carbon\Carbon; use Flarum\Flags\Event\Created; use Flarum\Flags\Flag; use Flarum\Foundation\ValidationException; +use Flarum\Locale\TranslatorInterface; use Flarum\Post\CommentPost; use Flarum\Post\PostRepository; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Events\Dispatcher; use Illuminate\Support\Arr; -use Symfony\Contracts\Translation\TranslatorInterface; use Tobscure\JsonApi\Exception\InvalidParameterException; class CreateFlagHandler { - /** - * @var PostRepository - */ - protected $posts; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param PostRepository $posts - * @param TranslatorInterface $translator - * @param SettingsRepositoryInterface $settings - * @param Dispatcher $events - */ - public function __construct(PostRepository $posts, TranslatorInterface $translator, SettingsRepositoryInterface $settings, Dispatcher $events) - { - $this->posts = $posts; - $this->translator = $translator; - $this->settings = $settings; - $this->events = $events; + public function __construct( + protected PostRepository $posts, + protected TranslatorInterface $translator, + protected SettingsRepositoryInterface $settings, + protected Dispatcher $events + ) { } - /** - * @param CreateFlag $command - * @return Flag - * @throws InvalidParameterException - * @throws ValidationException - */ - public function handle(CreateFlag $command) + public function handle(CreateFlag $command): Flag { $actor = $command->actor; $data = $command->data; diff --git a/extensions/flags/src/Command/DeleteFlags.php b/extensions/flags/src/Command/DeleteFlags.php index 21fd85a41..de42acc17 100644 --- a/extensions/flags/src/Command/DeleteFlags.php +++ b/extensions/flags/src/Command/DeleteFlags.php @@ -13,34 +13,10 @@ use Flarum\User\User; class DeleteFlags { - /** - * The ID of the post to delete flags for. - * - * @var int - */ - public $postId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @var array - */ - public $data; - - /** - * @param int $postId The ID of the post to delete flags for. - * @param User $actor The user performing the action. - * @param array $data - */ - public function __construct($postId, User $actor, array $data = []) - { - $this->postId = $postId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $postId, + public User $actor, + public array $data = [] + ) { } } diff --git a/extensions/flags/src/Command/DeleteFlagsHandler.php b/extensions/flags/src/Command/DeleteFlagsHandler.php index 18173b8ad..ffb4e008e 100644 --- a/extensions/flags/src/Command/DeleteFlagsHandler.php +++ b/extensions/flags/src/Command/DeleteFlagsHandler.php @@ -17,31 +17,13 @@ use Illuminate\Events\Dispatcher; class DeleteFlagsHandler { - /** - * @var PostRepository - */ - protected $posts; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param PostRepository $posts - * @param Dispatcher $events - */ - public function __construct(PostRepository $posts, Dispatcher $events) - { - $this->posts = $posts; - $this->events = $events; + public function __construct( + protected PostRepository $posts, + protected Dispatcher $events + ) { } - /** - * @param DeleteFlags $command - * @return Post - */ - public function handle(DeleteFlags $command) + public function handle(DeleteFlags $command): Post { $actor = $command->actor; diff --git a/extensions/flags/src/Event/Created.php b/extensions/flags/src/Event/Created.php index 8c2949842..86e8ef9fe 100644 --- a/extensions/flags/src/Event/Created.php +++ b/extensions/flags/src/Event/Created.php @@ -14,30 +14,10 @@ use Flarum\User\User; class Created { - /** - * @var Flag - */ - public $flag; - - /** - * @var User - */ - public $actor; - - /** - * @var array - */ - public $data; - - /** - * @param Flag $flag - * @param User $actor - * @param array $data - */ - public function __construct(Flag $flag, User $actor, array $data = []) - { - $this->flag = $flag; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Flag $flag, + public User $actor, + public array $data = [] + ) { } } diff --git a/extensions/flags/src/Event/Deleting.php b/extensions/flags/src/Event/Deleting.php index ae7e585e2..3d713015b 100644 --- a/extensions/flags/src/Event/Deleting.php +++ b/extensions/flags/src/Event/Deleting.php @@ -14,30 +14,10 @@ use Flarum\User\User; class Deleting { - /** - * @var Flag - */ - public $flag; - - /** - * @var User - */ - public $actor; - - /** - * @var array - */ - public $data; - - /** - * @param Flag $flag - * @param User $actor - * @param array $data - */ - public function __construct(Flag $flag, User $actor, array $data = []) - { - $this->flag = $flag; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Flag $flag, + public User $actor, + public array $data = [] + ) { } } diff --git a/extensions/flags/src/Event/FlagsWillBeDeleted.php b/extensions/flags/src/Event/FlagsWillBeDeleted.php index 1e2a30794..d2f426591 100644 --- a/extensions/flags/src/Event/FlagsWillBeDeleted.php +++ b/extensions/flags/src/Event/FlagsWillBeDeleted.php @@ -18,30 +18,10 @@ use Flarum\User\User; */ class FlagsWillBeDeleted { - /** - * @var Post - */ - public $post; - - /** - * @var User - */ - public $actor; - - /** - * @var array - */ - public $data; - - /** - * @param Post $post - * @param User $actor - * @param array $data - */ - public function __construct(Post $post, User $actor, array $data = []) - { - $this->post = $post; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Post $post, + public User $actor, + public array $data = [] + ) { } } diff --git a/extensions/flags/src/Flag.php b/extensions/flags/src/Flag.php index 6f056469d..310b72fa0 100644 --- a/extensions/flags/src/Flag.php +++ b/extensions/flags/src/Flag.php @@ -14,6 +14,7 @@ use Flarum\Database\AbstractModel; use Flarum\Database\ScopeVisibilityTrait; use Flarum\Post\Post; use Flarum\User\User; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @property int $post_id @@ -30,23 +31,14 @@ class Flag extends AbstractModel { use ScopeVisibilityTrait; - /** - * {@inheritdoc} - */ protected $dates = ['created_at']; - /** - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function post() + public function post(): BelongsTo { return $this->belongsTo(Post::class); } - /** - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } diff --git a/extensions/flags/src/Listener/DeleteFlags.php b/extensions/flags/src/Listener/DeleteFlags.php index b959f998a..61520443c 100644 --- a/extensions/flags/src/Listener/DeleteFlags.php +++ b/extensions/flags/src/Listener/DeleteFlags.php @@ -13,10 +13,7 @@ use Flarum\Post\Event\Deleted; class DeleteFlags { - /** - * @param Deleted $event - */ - public function handle(Deleted $event) + public function handle(Deleted $event): void { $event->post->flags()->delete(); } diff --git a/extensions/flags/src/PrepareFlagsApiData.php b/extensions/flags/src/PrepareFlagsApiData.php index 77ab4d6aa..4442255d2 100755 --- a/extensions/flags/src/PrepareFlagsApiData.php +++ b/extensions/flags/src/PrepareFlagsApiData.php @@ -17,7 +17,7 @@ use Psr\Http\Message\ServerRequestInterface; class PrepareFlagsApiData { - public function __invoke(Controller\AbstractSerializeController $controller, $data, ServerRequestInterface $request) + public function __invoke(Controller\AbstractSerializeController $controller, mixed $data, ServerRequestInterface $request): void { // For any API action that allows the 'flags' relationship to be // included, we need to preload this relationship onto the data (Post diff --git a/extensions/likes/extend.php b/extensions/likes/extend.php index 881ff9c6a..c59a497e5 100644 --- a/extensions/likes/extend.php +++ b/extensions/likes/extend.php @@ -51,25 +51,25 @@ return [ (new Extend\ApiController(Controller\ShowDiscussionController::class)) ->addInclude('posts.likes') - ->loadWhere('posts.likes', [LoadLikesRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']), + ->loadWhere('posts.likes', LoadLikesRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadLikesRelationship::countRelation(...)), (new Extend\ApiController(Controller\ListPostsController::class)) ->addInclude('likes') - ->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']), + ->loadWhere('likes', LoadLikesRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadLikesRelationship::countRelation(...)), (new Extend\ApiController(Controller\ShowPostController::class)) ->addInclude('likes') - ->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']), + ->loadWhere('likes', LoadLikesRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadLikesRelationship::countRelation(...)), (new Extend\ApiController(Controller\CreatePostController::class)) ->addInclude('likes') - ->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']), + ->loadWhere('likes', LoadLikesRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadLikesRelationship::countRelation(...)), (new Extend\ApiController(Controller\UpdatePostController::class)) ->addInclude('likes') - ->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']), + ->loadWhere('likes', LoadLikesRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadLikesRelationship::countRelation(...)), (new Extend\Event()) ->listen(PostWasLiked::class, Listener\SendNotificationWhenPostIsLiked::class) diff --git a/extensions/likes/src/Access/LikePostPolicy.php b/extensions/likes/src/Access/LikePostPolicy.php index 366ddc574..e83e686eb 100644 --- a/extensions/likes/src/Access/LikePostPolicy.php +++ b/extensions/likes/src/Access/LikePostPolicy.php @@ -16,14 +16,9 @@ use Flarum\User\User; class LikePostPolicy extends AbstractPolicy { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } public function like(User $actor, Post $post) diff --git a/extensions/likes/src/Api/LoadLikesRelationship.php b/extensions/likes/src/Api/LoadLikesRelationship.php index bc4fab735..4f9b62619 100644 --- a/extensions/likes/src/Api/LoadLikesRelationship.php +++ b/extensions/likes/src/Api/LoadLikesRelationship.php @@ -9,6 +9,7 @@ namespace Flarum\Likes\Api; +use Flarum\Api\Controller\AbstractSerializeController; use Flarum\Discussion\Discussion; use Flarum\Http\RequestUtil; use Flarum\Post\Post; @@ -19,15 +20,15 @@ use Psr\Http\Message\ServerRequestInterface; class LoadLikesRelationship { - public static $maxLikes = 4; + public static int $maxLikes = 4; - public static function mutateRelation(BelongsToMany $query, ServerRequestInterface $request): BelongsToMany + public static function mutateRelation(BelongsToMany $query, ServerRequestInterface $request): void { $actor = RequestUtil::getActor($request); $grammar = $query->getQuery()->getGrammar(); - return $query + $query // So that we can tell if the current user has liked the post. ->orderBy(new Expression($grammar->wrap('user_id').' = '.$actor->id), 'desc') // Limiting a relationship results is only possible because @@ -39,12 +40,14 @@ class LoadLikesRelationship /** * Called using the @see ApiController::prepareDataForSerialization extender. */ - public static function countRelation($controller, $data): void + public static function countRelation(AbstractSerializeController $controller, mixed $data): array { $loadable = null; if ($data instanceof Discussion) { - $loadable = $data->newCollection($data->posts)->filter(function ($post) { + // We do this because the ShowDiscussionController manipulates the posts + // in a way that some of them are just ids. + $loadable = $data->posts->filter(function ($post) { return $post instanceof Post; }); } elseif ($data instanceof Collection) { @@ -56,5 +59,7 @@ class LoadLikesRelationship if ($loadable) { $loadable->loadCount('likes'); } + + return []; } } diff --git a/extensions/likes/src/Event/PostWasLiked.php b/extensions/likes/src/Event/PostWasLiked.php index 1796aaf63..5a9911731 100644 --- a/extensions/likes/src/Event/PostWasLiked.php +++ b/extensions/likes/src/Event/PostWasLiked.php @@ -14,23 +14,9 @@ use Flarum\User\User; class PostWasLiked { - /** - * @var Post - */ - public $post; - - /** - * @var User - */ - public $user; - - /** - * @param Post $post - * @param User $user - */ - public function __construct(Post $post, User $user) - { - $this->post = $post; - $this->user = $user; + public function __construct( + public Post $post, + public User $user + ) { } } diff --git a/extensions/likes/src/Event/PostWasUnliked.php b/extensions/likes/src/Event/PostWasUnliked.php index ad5db2d11..500da327e 100644 --- a/extensions/likes/src/Event/PostWasUnliked.php +++ b/extensions/likes/src/Event/PostWasUnliked.php @@ -14,23 +14,9 @@ use Flarum\User\User; class PostWasUnliked { - /** - * @var Post - */ - public $post; - - /** - * @var User - */ - public $user; - - /** - * @param Post $post - * @param User $user - */ - public function __construct(Post $post, User $user) - { - $this->post = $post; - $this->user = $user; + public function __construct( + public Post $post, + public User $user + ) { } } diff --git a/extensions/likes/src/Listener/SaveLikesToDatabase.php b/extensions/likes/src/Listener/SaveLikesToDatabase.php index 516b42f73..8be625e9b 100755 --- a/extensions/likes/src/Listener/SaveLikesToDatabase.php +++ b/extensions/likes/src/Listener/SaveLikesToDatabase.php @@ -17,19 +17,13 @@ use Illuminate\Contracts\Events\Dispatcher; class SaveLikesToDatabase { - /** - * @param Dispatcher $events - */ - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Saving::class, [$this, 'whenPostIsSaving']); - $events->listen(Deleted::class, [$this, 'whenPostIsDeleted']); + $events->listen(Saving::class, $this->whenPostIsSaving(...)); + $events->listen(Deleted::class, $this->whenPostIsDeleted(...)); } - /** - * @param Saving $event - */ - public function whenPostIsSaving(Saving $event) + public function whenPostIsSaving(Saving $event): void { $post = $event->post; $data = $event->data; @@ -54,10 +48,7 @@ class SaveLikesToDatabase } } - /** - * @param Deleted $event - */ - public function whenPostIsDeleted(Deleted $event) + public function whenPostIsDeleted(Deleted $event): void { $event->post->likes()->detach(); } diff --git a/extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php b/extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php index b687ff3e8..401394048 100755 --- a/extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php +++ b/extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php @@ -15,20 +15,12 @@ use Flarum\Notification\NotificationSyncer; class SendNotificationWhenPostIsLiked { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @param NotificationSyncer $notifications - */ - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(PostWasLiked $event) + public function handle(PostWasLiked $event): void { if ($event->post->user && $event->post->user->id != $event->user->id) { $this->notifications->sync( diff --git a/extensions/likes/src/Listener/SendNotificationWhenPostIsUnliked.php b/extensions/likes/src/Listener/SendNotificationWhenPostIsUnliked.php index 78919d6a4..5a9b97733 100755 --- a/extensions/likes/src/Listener/SendNotificationWhenPostIsUnliked.php +++ b/extensions/likes/src/Listener/SendNotificationWhenPostIsUnliked.php @@ -15,20 +15,12 @@ use Flarum\Notification\NotificationSyncer; class SendNotificationWhenPostIsUnliked { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @param NotificationSyncer $notifications - */ - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(PostWasUnliked $event) + public function handle(PostWasUnliked $event): void { if ($event->post->user && $event->post->user->id != $event->user->id) { $this->notifications->sync( diff --git a/extensions/likes/src/Notification/PostLikedBlueprint.php b/extensions/likes/src/Notification/PostLikedBlueprint.php index d0b1d837a..b5b9854eb 100644 --- a/extensions/likes/src/Notification/PostLikedBlueprint.php +++ b/extensions/likes/src/Notification/PostLikedBlueprint.php @@ -9,67 +9,40 @@ namespace Flarum\Likes\Notification; +use Flarum\Database\AbstractModel; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Post\Post; use Flarum\User\User; class PostLikedBlueprint implements BlueprintInterface { - /** - * @var Post - */ - public $post; - - /** - * @var User - */ - public $user; - - /** - * @param Post $post - * @param User $user - */ - public function __construct(Post $post, User $user) - { - $this->post = $post; - $this->user = $user; + public function __construct( + public Post $post, + public User $user + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->user; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): mixed { + return null; } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'postLiked'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Post::class; } diff --git a/extensions/likes/src/Query/LikedByFilter.php b/extensions/likes/src/Query/LikedByFilter.php index 5952e63fa..13e09ace0 100644 --- a/extensions/likes/src/Query/LikedByFilter.php +++ b/extensions/likes/src/Query/LikedByFilter.php @@ -22,7 +22,7 @@ class LikedByFilter implements FilterInterface return 'likedBy'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $likedId = $this->asInt($filterValue); diff --git a/extensions/likes/src/Query/LikedFilter.php b/extensions/likes/src/Query/LikedFilter.php index d65a32bb3..155b4c444 100644 --- a/extensions/likes/src/Query/LikedFilter.php +++ b/extensions/likes/src/Query/LikedFilter.php @@ -11,17 +11,20 @@ namespace Flarum\Likes\Query; use Flarum\Filter\FilterInterface; use Flarum\Filter\FilterState; +use Flarum\Filter\ValidateFilterTrait; class LikedFilter implements FilterInterface { + use ValidateFilterTrait; + public function getFilterKey(): string { return 'liked'; } - public function filter(FilterState $filterState, string $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { - $likedId = trim($filterValue, '"'); + $likedId = $this->asString($filterValue); $filterState ->getQuery() diff --git a/extensions/lock/src/Access/DiscussionPolicy.php b/extensions/lock/src/Access/DiscussionPolicy.php index 86a0e3571..c11acff8d 100755 --- a/extensions/lock/src/Access/DiscussionPolicy.php +++ b/extensions/lock/src/Access/DiscussionPolicy.php @@ -15,11 +15,6 @@ use Flarum\User\User; class DiscussionPolicy extends AbstractPolicy { - /** - * @param User $actor - * @param Discussion $discussion - * @return string|void - */ public function reply(User $actor, Discussion $discussion) { if ($discussion->is_locked && $actor->cannot('lock', $discussion)) { diff --git a/extensions/lock/src/Event/DiscussionWasLocked.php b/extensions/lock/src/Event/DiscussionWasLocked.php index 25044572f..220ab4225 100644 --- a/extensions/lock/src/Event/DiscussionWasLocked.php +++ b/extensions/lock/src/Event/DiscussionWasLocked.php @@ -14,23 +14,9 @@ use Flarum\User\User; class DiscussionWasLocked { - /** - * @var Discussion - */ - public $discussion; - - /** - * @var User - */ - public $user; - - /** - * @param Discussion $discussion - * @param User $user - */ - public function __construct(Discussion $discussion, User $user) - { - $this->discussion = $discussion; - $this->user = $user; + public function __construct( + public Discussion $discussion, + public User $user + ) { } } diff --git a/extensions/lock/src/Event/DiscussionWasUnlocked.php b/extensions/lock/src/Event/DiscussionWasUnlocked.php index 0b48c6e86..82dfb05f5 100644 --- a/extensions/lock/src/Event/DiscussionWasUnlocked.php +++ b/extensions/lock/src/Event/DiscussionWasUnlocked.php @@ -14,23 +14,9 @@ use Flarum\User\User; class DiscussionWasUnlocked { - /** - * @var Discussion - */ - public $discussion; - - /** - * @var User - */ - public $user; - - /** - * @param Discussion $discussion - * @param User $user - */ - public function __construct(Discussion $discussion, User $user) - { - $this->discussion = $discussion; - $this->user = $user; + public function __construct( + public Discussion $discussion, + public User $user + ) { } } diff --git a/extensions/lock/src/Listener/CreatePostWhenDiscussionIsLocked.php b/extensions/lock/src/Listener/CreatePostWhenDiscussionIsLocked.php index afc771460..cdc23a5a2 100755 --- a/extensions/lock/src/Listener/CreatePostWhenDiscussionIsLocked.php +++ b/extensions/lock/src/Listener/CreatePostWhenDiscussionIsLocked.php @@ -16,17 +16,12 @@ use Flarum\Notification\NotificationSyncer; class CreatePostWhenDiscussionIsLocked { - /** - * @var NotificationSyncer - */ - protected $notifications; - - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(DiscussionWasLocked $event) + public function handle(DiscussionWasLocked $event): void { $post = DiscussionLockedPost::reply( $event->discussion->id, diff --git a/extensions/lock/src/Listener/CreatePostWhenDiscussionIsUnlocked.php b/extensions/lock/src/Listener/CreatePostWhenDiscussionIsUnlocked.php index e4dd8b9fa..b3853547b 100755 --- a/extensions/lock/src/Listener/CreatePostWhenDiscussionIsUnlocked.php +++ b/extensions/lock/src/Listener/CreatePostWhenDiscussionIsUnlocked.php @@ -16,17 +16,12 @@ use Flarum\Notification\NotificationSyncer; class CreatePostWhenDiscussionIsUnlocked { - /** - * @var NotificationSyncer - */ - protected $notifications; - - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(DiscussionWasUnlocked $event) + public function handle(DiscussionWasUnlocked $event): void { $post = DiscussionLockedPost::reply( $event->discussion->id, diff --git a/extensions/lock/src/Listener/SaveLockedToDatabase.php b/extensions/lock/src/Listener/SaveLockedToDatabase.php index 10a08252a..e3c107a4f 100755 --- a/extensions/lock/src/Listener/SaveLockedToDatabase.php +++ b/extensions/lock/src/Listener/SaveLockedToDatabase.php @@ -15,7 +15,7 @@ use Flarum\Lock\Event\DiscussionWasUnlocked; class SaveLockedToDatabase { - public function handle(Saving $event) + public function handle(Saving $event): void { if (isset($event->data['attributes']['isLocked'])) { $isLocked = (bool) $event->data['attributes']['isLocked']; diff --git a/extensions/lock/src/Notification/DiscussionLockedBlueprint.php b/extensions/lock/src/Notification/DiscussionLockedBlueprint.php index c3d9bdff1..e9614cdae 100644 --- a/extensions/lock/src/Notification/DiscussionLockedBlueprint.php +++ b/extensions/lock/src/Notification/DiscussionLockedBlueprint.php @@ -9,61 +9,40 @@ namespace Flarum\Lock\Notification; +use Flarum\Database\AbstractModel; use Flarum\Discussion\Discussion; use Flarum\Lock\Post\DiscussionLockedPost; use Flarum\Notification\Blueprint\BlueprintInterface; +use Flarum\User\User; class DiscussionLockedBlueprint implements BlueprintInterface { - /** - * @var DiscussionLockedPost - */ - protected $post; - - /** - * @param DiscussionLockedPost $post - */ - public function __construct(DiscussionLockedPost $post) - { - $this->post = $post; + public function __construct( + protected DiscussionLockedPost $post + ) { } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->post->user; } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post->discussion; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): array { return ['postNumber' => (int) $this->post->number]; } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'discussionLocked'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Discussion::class; } diff --git a/extensions/lock/src/Post/DiscussionLockedPost.php b/extensions/lock/src/Post/DiscussionLockedPost.php index a379fe642..d46efbfb4 100755 --- a/extensions/lock/src/Post/DiscussionLockedPost.php +++ b/extensions/lock/src/Post/DiscussionLockedPost.php @@ -16,15 +16,9 @@ use Flarum\Post\Post; class DiscussionLockedPost extends AbstractEventPost implements MergeableInterface { - /** - * {@inheritdoc} - */ - public static $type = 'discussionLocked'; + public static string $type = 'discussionLocked'; - /** - * {@inheritdoc} - */ - public function saveAfter(Post $previous = null) + public function saveAfter(Post $previous = null): static { // If the previous post is another 'discussion locked' post, and it's // by the same user, then we can merge this post into it. If we find @@ -47,15 +41,7 @@ class DiscussionLockedPost extends AbstractEventPost implements MergeableInterfa return $this; } - /** - * Create a new instance in reply to a discussion. - * - * @param int $discussionId - * @param int $userId - * @param bool $isLocked - * @return static - */ - public static function reply($discussionId, $userId, $isLocked) + public static function reply(int $discussionId, int $userId, bool $isLocked): static { $post = new static; @@ -67,14 +53,8 @@ class DiscussionLockedPost extends AbstractEventPost implements MergeableInterfa return $post; } - /** - * Build the content attribute. - * - * @param bool $isLocked Whether or not the discussion is locked. - * @return array - */ - public static function buildContent($isLocked) + public static function buildContent(bool $isLocked): array { - return ['locked' => (bool) $isLocked]; + return ['locked' => $isLocked]; } } diff --git a/extensions/lock/src/Query/LockedFilterGambit.php b/extensions/lock/src/Query/LockedFilterGambit.php index 42abbfddd..2c3d14ad9 100644 --- a/extensions/lock/src/Query/LockedFilterGambit.php +++ b/extensions/lock/src/Query/LockedFilterGambit.php @@ -17,14 +17,14 @@ use Illuminate\Database\Query\Builder; class LockedFilterGambit extends AbstractRegexGambit implements FilterInterface { - protected function getGambitPattern() + protected function getGambitPattern(): string { return 'is:locked'; } - protected function conditions(SearchState $searchState, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { - $this->constrain($searchState->getQuery(), $negate); + $this->constrain($search->getQuery(), $negate); } public function getFilterKey(): string @@ -32,12 +32,12 @@ class LockedFilterGambit extends AbstractRegexGambit implements FilterInterface return 'locked'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $negate); } - protected function constrain(Builder $query, bool $negate) + protected function constrain(Builder $query, bool $negate): void { $query->where('is_locked', ! $negate); } diff --git a/extensions/mentions/extend.php b/extensions/mentions/extend.php index 52ee37717..b659d049d 100644 --- a/extensions/mentions/extend.php +++ b/extensions/mentions/extend.php @@ -80,8 +80,8 @@ return [ 'posts.mentionsUsers', 'posts.mentionsPosts', 'posts.mentionsPosts.user', 'posts.mentionsGroups' ]) - ->loadWhere('posts.mentionedBy', [LoadMentionedByRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadMentionedByRelationship::class, 'countRelation']), + ->loadWhere('posts.mentionedBy', LoadMentionedByRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadMentionedByRelationship::countRelation(...)), (new Extend\ApiController(Controller\ListDiscussionsController::class)) ->load([ @@ -93,14 +93,14 @@ return [ ->addInclude(['mentionedBy', 'mentionedBy.user', 'mentionedBy.discussion']) // We wouldn't normally need to eager load on a single model, // but we do so here for visibility scoping. - ->loadWhere('mentionedBy', [LoadMentionedByRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadMentionedByRelationship::class, 'countRelation']), + ->loadWhere('mentionedBy', LoadMentionedByRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadMentionedByRelationship::countRelation(...)), (new Extend\ApiController(Controller\ListPostsController::class)) ->addInclude(['mentionedBy', 'mentionedBy.user', 'mentionedBy.discussion']) ->load(['mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionsGroups']) - ->loadWhere('mentionedBy', [LoadMentionedByRelationship::class, 'mutateRelation']) - ->prepareDataForSerialization([LoadMentionedByRelationship::class, 'countRelation']), + ->loadWhere('mentionedBy', LoadMentionedByRelationship::mutateRelation(...)) + ->prepareDataForSerialization(LoadMentionedByRelationship::countRelation(...)), (new Extend\Settings) ->serializeToForum('allowUsernameMentionFormat', 'flarum-mentions.allow_username_format', 'boolval'), diff --git a/extensions/mentions/src/Api/LoadMentionedByRelationship.php b/extensions/mentions/src/Api/LoadMentionedByRelationship.php index 209e3be6b..82f916869 100644 --- a/extensions/mentions/src/Api/LoadMentionedByRelationship.php +++ b/extensions/mentions/src/Api/LoadMentionedByRelationship.php @@ -9,6 +9,7 @@ namespace Flarum\Mentions\Api; +use Flarum\Api\Controller\AbstractSerializeController; use Flarum\Discussion\Discussion; use Flarum\Http\RequestUtil; use Flarum\Post\Post; @@ -22,13 +23,13 @@ use Psr\Http\Message\ServerRequestInterface; */ class LoadMentionedByRelationship { - public static $maxMentionedBy = 4; + public static int $maxMentionedBy = 4; - public static function mutateRelation(BelongsToMany $query, ServerRequestInterface $request) + public static function mutateRelation(BelongsToMany $query, ServerRequestInterface $request): void { $actor = RequestUtil::getActor($request); - return $query + $query ->with(['mentionsPosts', 'mentionsPosts.user', 'mentionsUsers']) ->whereVisibleTo($actor) ->oldest() @@ -41,13 +42,15 @@ class LoadMentionedByRelationship /** * Called using the @see ApiController::prepareDataForSerialization extender. */ - public static function countRelation($controller, $data, ServerRequestInterface $request): void + public static function countRelation(AbstractSerializeController $controller, mixed $data, ServerRequestInterface $request): array { $actor = RequestUtil::getActor($request); $loadable = null; if ($data instanceof Discussion) { - $loadable = $data->newCollection($data->posts)->filter(function ($post) { + // We do this because the ShowDiscussionController manipulates the posts + // in a way that some of them are just ids. + $loadable = $data->posts->filter(function ($post) { return $post instanceof Post; }); } elseif ($data instanceof Collection) { @@ -63,5 +66,7 @@ class LoadMentionedByRelationship } ]); } + + return []; } } diff --git a/extensions/mentions/src/ConfigureMentions.php b/extensions/mentions/src/ConfigureMentions.php index ddc700471..2f7e076e8 100644 --- a/extensions/mentions/src/ConfigureMentions.php +++ b/extensions/mentions/src/ConfigureMentions.php @@ -30,23 +30,13 @@ class ConfigureMentions public const GROUP_MENTION_WITH_NAME_REGEX = '/\B@["“](?((?!"#[a-z]{0,3}[0-9]+).)+)["|”]#g(?[0-9]+)\b/'; public const TAG_MENTION_WITH_SLUG_REGEX = '/(?:[^“"]|^)\B#(?[-_\p{L}\p{N}\p{M}]+)\b/ui'; - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var ExtensionManager - */ - protected $extensions; - - public function __construct(UrlGenerator $url, ExtensionManager $extensions) - { - $this->url = $url; - $this->extensions = $extensions; + public function __construct( + protected UrlGenerator $url, + protected ExtensionManager $extensions + ) { } - public function __invoke(Configurator $config) + public function __invoke(Configurator $config): void { $this->configureUserMentions($config); $this->configurePostMentions($config); diff --git a/extensions/mentions/src/Filter/MentionedFilter.php b/extensions/mentions/src/Filter/MentionedFilter.php index 5652da21b..a0b470d93 100644 --- a/extensions/mentions/src/Filter/MentionedFilter.php +++ b/extensions/mentions/src/Filter/MentionedFilter.php @@ -22,7 +22,7 @@ class MentionedFilter implements FilterInterface return 'mentioned'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $mentionedId = $this->asInt($filterValue); diff --git a/extensions/mentions/src/Filter/MentionedPostFilter.php b/extensions/mentions/src/Filter/MentionedPostFilter.php index e9b32945d..da46bbe2c 100644 --- a/extensions/mentions/src/Filter/MentionedPostFilter.php +++ b/extensions/mentions/src/Filter/MentionedPostFilter.php @@ -19,7 +19,7 @@ class MentionedPostFilter implements FilterInterface return 'mentionedPost'; } - public function filter(FilterState $filterState, string $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $mentionedId = trim($filterValue, '"'); diff --git a/extensions/mentions/src/Formatter/EagerLoadMentionedModels.php b/extensions/mentions/src/Formatter/EagerLoadMentionedModels.php index 1033f45ac..0d39754e2 100644 --- a/extensions/mentions/src/Formatter/EagerLoadMentionedModels.php +++ b/extensions/mentions/src/Formatter/EagerLoadMentionedModels.php @@ -20,38 +20,15 @@ use s9e\TextFormatter\Parser; class EagerLoadMentionedModels { - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var PostRepository - */ - protected $posts; - - /** - * @var GroupRepository - */ - protected $groups; - - /** - * @var TagRepository - */ - protected $tags; - - public function __construct(ExtensionManager $extensions, PostRepository $posts, GroupRepository $groups, TagRepository $tags) - { - $this->extensions = $extensions; - $this->posts = $posts; - $this->groups = $groups; - $this->tags = $tags; + public function __construct( + protected ExtensionManager $extensions, + protected PostRepository $posts, + protected GroupRepository $groups, + protected TagRepository $tags + ) { } - /** - * @param mixed|\Flarum\Post\CommentPost|null $context - */ - public function __invoke(Parser $parser, $context, string $text, ?User $actor): string + public function __invoke(Parser $parser, mixed $context, string $text, ?User $actor): string { $callables = $this->getEagerLoaders(); diff --git a/extensions/mentions/src/Formatter/FormatGroupMentions.php b/extensions/mentions/src/Formatter/FormatGroupMentions.php index 985d6f321..0c8881a83 100644 --- a/extensions/mentions/src/Formatter/FormatGroupMentions.php +++ b/extensions/mentions/src/Formatter/FormatGroupMentions.php @@ -10,32 +10,19 @@ namespace Flarum\Mentions\Formatter; use Flarum\Group\Group; +use Flarum\Locale\TranslatorInterface; use Flarum\Post\Post; use s9e\TextFormatter\Renderer; use s9e\TextFormatter\Utils; -use Symfony\Contracts\Translation\TranslatorInterface; class FormatGroupMentions { - /** - * @var TranslatorInterface - */ - private $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + private readonly TranslatorInterface $translator + ) { } - /** - * Configure rendering for group mentions. - * - * @param \s9e\TextFormatter\Renderer $renderer - * @param mixed $context - * @param string $xml - * @return string - */ - public function __invoke(Renderer $renderer, $context, string $xml): string + public function __invoke(Renderer $renderer, mixed $context, string $xml): string { return Utils::replaceAttributes($xml, 'GROUPMENTION', function ($attributes) use ($context) { $group = (($context && isset($context->getRelations()['mentionsGroups'])) || $context instanceof Post) diff --git a/extensions/mentions/src/Formatter/FormatPostMentions.php b/extensions/mentions/src/Formatter/FormatPostMentions.php index 45a485e57..ed17bcb79 100644 --- a/extensions/mentions/src/Formatter/FormatPostMentions.php +++ b/extensions/mentions/src/Formatter/FormatPostMentions.php @@ -9,33 +9,19 @@ namespace Flarum\Mentions\Formatter; +use Flarum\Locale\TranslatorInterface; use Psr\Http\Message\ServerRequestInterface as Request; use s9e\TextFormatter\Renderer; use s9e\TextFormatter\Utils; -use Symfony\Contracts\Translation\TranslatorInterface; class FormatPostMentions { - /** - * @var TranslatorInterface - */ - private $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + private readonly TranslatorInterface $translator + ) { } - /** - * Configure rendering for post mentions. - * - * @param \s9e\TextFormatter\Renderer $renderer - * @param mixed $context - * @param string|null $xml - * @param \Psr\Http\Message\ServerRequestInterface $request - * @return string - */ - public function __invoke(Renderer $renderer, $context, $xml, Request $request = null) + public function __invoke(Renderer $renderer, mixed $context, ?string $xml, Request $request = null): string { $post = $context; diff --git a/extensions/mentions/src/Formatter/FormatTagMentions.php b/extensions/mentions/src/Formatter/FormatTagMentions.php index c74c83e69..b867969ca 100644 --- a/extensions/mentions/src/Formatter/FormatTagMentions.php +++ b/extensions/mentions/src/Formatter/FormatTagMentions.php @@ -17,7 +17,7 @@ use s9e\TextFormatter\Utils; class FormatTagMentions { - public function __invoke(Renderer $renderer, $context, ?string $xml, Request $request = null): string + public function __invoke(Renderer $renderer, mixed $context, ?string $xml, Request $request = null): string { return Utils::replaceAttributes($xml, 'TAGMENTION', function ($attributes) use ($context) { /** @var Tag|null $tag */ diff --git a/extensions/mentions/src/Formatter/FormatUserMentions.php b/extensions/mentions/src/Formatter/FormatUserMentions.php index 5625ac957..feefd58b4 100644 --- a/extensions/mentions/src/Formatter/FormatUserMentions.php +++ b/extensions/mentions/src/Formatter/FormatUserMentions.php @@ -10,39 +10,21 @@ namespace Flarum\Mentions\Formatter; use Flarum\Http\SlugManager; +use Flarum\Locale\TranslatorInterface; use Flarum\Post\Post; use Flarum\User\User; use s9e\TextFormatter\Renderer; use s9e\TextFormatter\Utils; -use Symfony\Contracts\Translation\TranslatorInterface; class FormatUserMentions { - /** - * @var SlugManager - */ - private $slugManager; - - /** - * @var TranslatorInterface - */ - private $translator; - - public function __construct(SlugManager $slugManager, TranslatorInterface $translator) - { - $this->slugManager = $slugManager; - $this->translator = $translator; + public function __construct( + private readonly TranslatorInterface $translator, + private readonly SlugManager $slugManager + ) { } - /** - * Configure rendering for user mentions. - * - * @param \s9e\TextFormatter\Renderer $renderer - * @param mixed $context - * @param string $xml - * @return string $xml to be rendered - */ - public function __invoke(Renderer $renderer, $context, string $xml) + public function __invoke(Renderer $renderer, mixed $context, string $xml): string { return Utils::replaceAttributes($xml, 'USERMENTION', function ($attributes) use ($context) { $user = (($context && isset($context->getRelations()['mentionsUsers'])) || $context instanceof Post) diff --git a/extensions/mentions/src/Formatter/UnparsePostMentions.php b/extensions/mentions/src/Formatter/UnparsePostMentions.php index 4f8d01614..3c32dee0b 100644 --- a/extensions/mentions/src/Formatter/UnparsePostMentions.php +++ b/extensions/mentions/src/Formatter/UnparsePostMentions.php @@ -9,42 +9,25 @@ namespace Flarum\Mentions\Formatter; +use Flarum\Locale\TranslatorInterface; use s9e\TextFormatter\Utils; -use Symfony\Contracts\Translation\TranslatorInterface; class UnparsePostMentions { - /** - * @var TranslatorInterface - */ - private $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + private readonly TranslatorInterface $translator + ) { } - /** - * Configure rendering for user mentions. - * - * @param string $xml - * @param mixed $context - * @return string $xml to be unparsed - */ - public function __invoke($context, string $xml) + public function __invoke(mixed $context, string $xml): string { - $xml = $this->updatePostMentionTags($context, $xml); - $xml = $this->unparsePostMentionTags($xml); - - return $xml; + return $this->unparsePostMentionTags( + $this->updatePostMentionTags($context, $xml) + ); } /** * Updates XML post mention tags before unparsing so that unparsing uses new display names. - * - * @param mixed $context - * @param string $xml : Parsed text. - * @return string $xml : Updated XML tags; */ protected function updatePostMentionTags($context, string $xml): string { @@ -74,9 +57,6 @@ class UnparsePostMentions /** * Transforms post mention tags from XML to raw unparsed content with updated format and display name. - * - * @param string $xml : Parsed text. - * @return string : Unparsed text. */ protected function unparsePostMentionTags(string $xml): string { diff --git a/extensions/mentions/src/Formatter/UnparseTagMentions.php b/extensions/mentions/src/Formatter/UnparseTagMentions.php index b2cae82f2..483e0517b 100644 --- a/extensions/mentions/src/Formatter/UnparseTagMentions.php +++ b/extensions/mentions/src/Formatter/UnparseTagMentions.php @@ -15,29 +15,17 @@ use s9e\TextFormatter\Utils; class UnparseTagMentions { - /** - * Configure rendering for user mentions. - * - * @param string $xml - * @param mixed $context - * @return string $xml to be unparsed - */ - public function __invoke($context, string $xml) + public function __invoke(mixed $context, string $xml): string { - $xml = $this->updateTagMentionTags($context, $xml); - $xml = $this->unparseTagMentionTags($xml); - - return $xml; + return $this->unparseTagMentionTags( + $this->updateTagMentionTags($context, $xml) + ); } /** * Updates XML user mention tags before unparsing so that unparsing uses new tag names. - * - * @param mixed $context - * @param string $xml : Parsed text. - * @return string $xml : Updated XML tags; */ - protected function updateTagMentionTags($context, string $xml): string + protected function updateTagMentionTags(mixed $context, string $xml): string { return Utils::replaceAttributes($xml, 'TAGMENTION', function (array $attributes) use ($context) { /** @var Tag|null $tag */ @@ -56,9 +44,6 @@ class UnparseTagMentions /** * Transforms tag mention tags from XML to raw unparsed content with updated name. - * - * @param string $xml : Parsed text. - * @return string : Unparsed text. */ protected function unparseTagMentionTags(string $xml): string { diff --git a/extensions/mentions/src/Formatter/UnparseUserMentions.php b/extensions/mentions/src/Formatter/UnparseUserMentions.php index b150d2f7b..b7fe68dd9 100644 --- a/extensions/mentions/src/Formatter/UnparseUserMentions.php +++ b/extensions/mentions/src/Formatter/UnparseUserMentions.php @@ -9,46 +9,29 @@ namespace Flarum\Mentions\Formatter; +use Flarum\Locale\TranslatorInterface; use Flarum\Post\Post; use Flarum\User\User; use s9e\TextFormatter\Utils; -use Symfony\Contracts\Translation\TranslatorInterface; class UnparseUserMentions { - /** - * @var TranslatorInterface - */ - private $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + private readonly TranslatorInterface $translator + ) { } - /** - * Configure rendering for user mentions. - * - * @param string $xml - * @param mixed $context - * @return string $xml to be unparsed - */ - public function __invoke($context, string $xml) + public function __invoke(mixed $context, string $xml): string { - $xml = $this->updateUserMentionTags($context, $xml); - $xml = $this->unparseUserMentionTags($xml); - - return $xml; + return $this->unparseUserMentionTags( + $this->updateUserMentionTags($context, $xml) + ); } /** * Updates XML user mention tags before unparsing so that unparsing uses new display names. - * - * @param mixed $context - * @param string $xml : Parsed text. - * @return string $xml : Updated XML tags; */ - protected function updateUserMentionTags($context, string $xml): string + protected function updateUserMentionTags(mixed $context, string $xml): string { return Utils::replaceAttributes($xml, 'USERMENTION', function ($attributes) use ($context) { $user = (($context && isset($context->getRelations()['mentionsUsers'])) || $context instanceof Post) @@ -71,9 +54,6 @@ class UnparseUserMentions /** * Transforms user mention tags from XML to raw unparsed content with updated format and display name. - * - * @param string $xml : Parsed text. - * @return string : Unparsed text. */ protected function unparseUserMentionTags(string $xml): string { diff --git a/extensions/mentions/src/Job/SendMentionsNotificationsJob.php b/extensions/mentions/src/Job/SendMentionsNotificationsJob.php index f3ed2d7b0..06cb3b179 100644 --- a/extensions/mentions/src/Job/SendMentionsNotificationsJob.php +++ b/extensions/mentions/src/Job/SendMentionsNotificationsJob.php @@ -20,37 +20,14 @@ use Flarum\User\User; class SendMentionsNotificationsJob extends AbstractJob { - /** - * @var CommentPost - */ - protected $post; + private NotificationSyncer $notifications; - /** - * @var array - */ - protected $userMentions; - - /** - * @var array - */ - protected $postMentions; - - /** - * @var array - */ - protected $groupMentions; - - /** - * @var NotificationSyncer - */ - private $notifications; - - public function __construct(CommentPost $post, array $userMentions, array $postMentions, array $groupMentions) - { - $this->post = $post; - $this->userMentions = $userMentions; - $this->postMentions = $postMentions; - $this->groupMentions = $groupMentions; + public function __construct( + protected CommentPost $post, + protected array $userMentions, + protected array $postMentions, + protected array $groupMentions + ) { } public function handle(NotificationSyncer $notifications): void @@ -62,7 +39,7 @@ class SendMentionsNotificationsJob extends AbstractJob $this->notifyAboutGroupMentions($this->post, $this->groupMentions); } - protected function notifyAboutUserMentions(Post $post, array $mentioned) + protected function notifyAboutUserMentions(Post $post, array $mentioned): void { $users = User::whereIn('id', $mentioned) ->with('groups') @@ -75,7 +52,7 @@ class SendMentionsNotificationsJob extends AbstractJob $this->notifications->sync(new UserMentionedBlueprint($post), $users); } - protected function notifyAboutPostMentions(Post $reply, array $mentioned) + protected function notifyAboutPostMentions(Post $reply, array $mentioned): void { $posts = Post::with('user') ->whereIn('id', $mentioned) @@ -91,7 +68,7 @@ class SendMentionsNotificationsJob extends AbstractJob } } - protected function notifyAboutGroupMentions(Post $post, array $mentioned) + protected function notifyAboutGroupMentions(Post $post, array $mentioned): void { $users = User::whereHas('groups', function ($query) use ($mentioned) { $query->whereIn('groups.id', $mentioned); diff --git a/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenInvisible.php b/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenInvisible.php index e3a82543a..2fc90e734 100755 --- a/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenInvisible.php +++ b/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenInvisible.php @@ -17,26 +17,13 @@ use Flarum\Post\Event\Hidden; class UpdateMentionsMetadataWhenInvisible { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @var ExtensionManager - */ - protected $extensions; - - public function __construct(NotificationSyncer $notifications, ExtensionManager $extensions) - { - $this->notifications = $notifications; - $this->extensions = $extensions; + public function __construct( + protected NotificationSyncer $notifications, + protected ExtensionManager $extensions + ) { } - /** - * @param Deleted|Hidden $event - */ - public function handle($event) + public function handle(Deleted|Hidden $event): void { // Remove user mentions $event->post->mentionsUsers()->sync([]); diff --git a/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php b/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php index 51cc329fa..0850ccf15 100755 --- a/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php +++ b/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php @@ -22,26 +22,13 @@ use s9e\TextFormatter\Utils; class UpdateMentionsMetadataWhenVisible { - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var Queue - */ - protected $queue; - - public function __construct(ExtensionManager $extensions, Queue $queue) - { - $this->extensions = $extensions; - $this->queue = $queue; + public function __construct( + protected ExtensionManager $extensions, + protected Queue $queue + ) { } - /** - * @param Posted|Restored|Revised|PostWasApproved $event - */ - public function handle($event) + public function handle(Restored|Revised|Posted|PostWasApproved $event): void { if (! $event->post instanceof CommentPost) { return; @@ -74,25 +61,25 @@ class UpdateMentionsMetadataWhenVisible $this->queue->push(new SendMentionsNotificationsJob($event->post, $userMentions, $postMentions, $groupMentions)); } - protected function syncUserMentions(Post $post, array $mentioned) + protected function syncUserMentions(Post $post, array $mentioned): void { $post->mentionsUsers()->sync($mentioned); $post->unsetRelation('mentionsUsers'); } - protected function syncPostMentions(Post $reply, array $mentioned) + protected function syncPostMentions(Post $reply, array $mentioned): void { $reply->mentionsPosts()->sync($mentioned); $reply->unsetRelation('mentionsPosts'); } - protected function syncGroupMentions(Post $post, array $mentioned) + protected function syncGroupMentions(Post $post, array $mentioned): void { $post->mentionsGroups()->sync($mentioned); $post->unsetRelation('mentionsGroups'); } - protected function syncTagMentions(Post $post, array $mentioned) + protected function syncTagMentions(Post $post, array $mentioned): void { $post->mentionsTags()->sync($mentioned); $post->unsetRelation('mentionsTags'); diff --git a/extensions/mentions/src/Notification/GroupMentionedBlueprint.php b/extensions/mentions/src/Notification/GroupMentionedBlueprint.php index 1842d0e24..50d9b5824 100644 --- a/extensions/mentions/src/Notification/GroupMentionedBlueprint.php +++ b/extensions/mentions/src/Notification/GroupMentionedBlueprint.php @@ -9,61 +9,41 @@ namespace Flarum\Mentions\Notification; +use Flarum\Database\AbstractModel; +use Flarum\Locale\TranslatorInterface; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\MailableInterface; use Flarum\Post\Post; -use Symfony\Contracts\Translation\TranslatorInterface; +use Flarum\User\User; class GroupMentionedBlueprint implements BlueprintInterface, MailableInterface { - /** - * @var Post - */ - public $post; - - /** - * @param Post $post - */ - public function __construct(Post $post) - { - $this->post = $post; + public function __construct( + public Post $post + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->post->user; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): mixed { + return null; } - /** - * {@inheritdoc} - */ - public function getEmailView() + public function getEmailView(): string|array { return ['text' => 'flarum-mentions::emails.groupMentioned']; } - /** - * {@inheritdoc} - */ - public function getEmailSubject(TranslatorInterface $translator) + public function getEmailSubject(TranslatorInterface $translator): string { return $translator->trans('flarum-mentions.email.group_mentioned.subject', [ '{mentioner_display_name}' => $this->post->user->display_name, @@ -71,18 +51,12 @@ class GroupMentionedBlueprint implements BlueprintInterface, MailableInterface ]); } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'groupMentioned'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Post::class; } diff --git a/extensions/mentions/src/Notification/PostMentionedBlueprint.php b/extensions/mentions/src/Notification/PostMentionedBlueprint.php index 3f8da0be8..465ee57ba 100644 --- a/extensions/mentions/src/Notification/PostMentionedBlueprint.php +++ b/extensions/mentions/src/Notification/PostMentionedBlueprint.php @@ -9,69 +9,42 @@ namespace Flarum\Mentions\Notification; +use Flarum\Database\AbstractModel; +use Flarum\Locale\TranslatorInterface; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\MailableInterface; use Flarum\Post\Post; -use Symfony\Contracts\Translation\TranslatorInterface; +use Flarum\User\User; class PostMentionedBlueprint implements BlueprintInterface, MailableInterface { - /** - * @var Post - */ - public $post; - - /** - * @var Post - */ - public $reply; - - /** - * @param Post $post - * @param Post $reply - */ - public function __construct(Post $post, Post $reply) - { - $this->post = $post; - $this->reply = $reply; + public function __construct( + public Post $post, + public Post $reply + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->reply->user; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): array { return ['replyNumber' => (int) $this->reply->number]; } - /** - * {@inheritdoc} - */ - public function getEmailView() + public function getEmailView(): string|array { return ['text' => 'flarum-mentions::emails.postMentioned']; } - /** - * {@inheritdoc} - */ - public function getEmailSubject(TranslatorInterface $translator) + public function getEmailSubject(TranslatorInterface $translator): string { return $translator->trans('flarum-mentions.email.post_mentioned.subject', [ '{replier_display_name}' => $this->reply->user->display_name, @@ -79,18 +52,12 @@ class PostMentionedBlueprint implements BlueprintInterface, MailableInterface ]); } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'postMentioned'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Post::class; } diff --git a/extensions/mentions/src/Notification/UserMentionedBlueprint.php b/extensions/mentions/src/Notification/UserMentionedBlueprint.php index 7c00ca702..155569338 100644 --- a/extensions/mentions/src/Notification/UserMentionedBlueprint.php +++ b/extensions/mentions/src/Notification/UserMentionedBlueprint.php @@ -9,61 +9,41 @@ namespace Flarum\Mentions\Notification; +use Flarum\Database\AbstractModel; +use Flarum\Locale\TranslatorInterface; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\MailableInterface; use Flarum\Post\Post; -use Symfony\Contracts\Translation\TranslatorInterface; +use Flarum\User\User; class UserMentionedBlueprint implements BlueprintInterface, MailableInterface { - /** - * @var Post - */ - public $post; - - /** - * @param Post $post - */ - public function __construct(Post $post) - { - $this->post = $post; + public function __construct( + public Post $post + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->post->user; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): mixed { + return null; } - /** - * {@inheritdoc} - */ - public function getEmailView() + public function getEmailView(): string|array { return ['text' => 'flarum-mentions::emails.userMentioned']; } - /** - * {@inheritdoc} - */ - public function getEmailSubject(TranslatorInterface $translator) + public function getEmailSubject(TranslatorInterface $translator): string { return $translator->trans('flarum-mentions.email.user_mentioned.subject', [ '{mentioner_display_name}' => $this->post->user->display_name, @@ -71,18 +51,12 @@ class UserMentionedBlueprint implements BlueprintInterface, MailableInterface ]); } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'userMentioned'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Post::class; } diff --git a/extensions/nicknames/src/Access/UserPolicy.php b/extensions/nicknames/src/Access/UserPolicy.php index 765db5366..c7791beb2 100644 --- a/extensions/nicknames/src/Access/UserPolicy.php +++ b/extensions/nicknames/src/Access/UserPolicy.php @@ -15,21 +15,11 @@ use Flarum\User\User; class UserPolicy extends AbstractPolicy { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param User $actor - * @param User $user - * @return bool|null - */ public function editNickname(User $actor, User $user) { if ($actor->isGuest() && ! $user->exists && $this->settings->get('flarum-nicknames.set_on_registration')) { diff --git a/extensions/nicknames/src/AddNicknameValidation.php b/extensions/nicknames/src/AddNicknameValidation.php index 5ce43e840..ed2350e30 100644 --- a/extensions/nicknames/src/AddNicknameValidation.php +++ b/extensions/nicknames/src/AddNicknameValidation.php @@ -9,29 +9,20 @@ namespace Flarum\Nicknames; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; +use Flarum\User\UserValidator; use Illuminate\Validation\Validator; -use Symfony\Contracts\Translation\TranslatorInterface; class AddNicknameValidation { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(SettingsRepositoryInterface $settings, TranslatorInterface $translator) - { - $this->settings = $settings; - $this->translator = $translator; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected TranslatorInterface $translator + ) { } - public function __invoke($flarumValidator, Validator $validator) + public function __invoke(UserValidator $flarumValidator, Validator $validator): void { $idSuffix = $flarumValidator->getUser() ? ','.$flarumValidator->getUser()->id : ''; $rules = $validator->getRules(); diff --git a/extensions/nicknames/src/NicknameDriver.php b/extensions/nicknames/src/NicknameDriver.php index 97f925b74..aa074f817 100644 --- a/extensions/nicknames/src/NicknameDriver.php +++ b/extensions/nicknames/src/NicknameDriver.php @@ -16,6 +16,6 @@ class NicknameDriver implements DriverInterface { public function displayName(User $user): string { - return $user->nickname ? $user->nickname : $user->username; + return $user->nickname ?? $user->username; } } diff --git a/extensions/nicknames/src/NicknameFullTextGambit.php b/extensions/nicknames/src/NicknameFullTextGambit.php index 84cec8035..1079e865f 100644 --- a/extensions/nicknames/src/NicknameFullTextGambit.php +++ b/extensions/nicknames/src/NicknameFullTextGambit.php @@ -19,27 +19,16 @@ namespace Flarum\Nicknames; use Flarum\Search\GambitInterface; use Flarum\Search\SearchState; use Flarum\User\UserRepository; +use Illuminate\Database\Eloquent\Builder; class NicknameFullTextGambit implements GambitInterface { - /** - * @var UserRepository - */ - protected $users; - - /** - * @param \Flarum\User\UserRepository $users - */ - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } - /** - * @param $searchValue - * @return \Illuminate\Database\Eloquent\Builder - */ - private function getUserSearchSubQuery($searchValue) + private function getUserSearchSubQuery(string $searchValue): Builder { return $this->users ->query() @@ -48,15 +37,12 @@ class NicknameFullTextGambit implements GambitInterface ->orWhere('nickname', 'like', "{$searchValue}%"); } - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $searchValue) + public function apply(SearchState $search, string $bit): bool { $search->getQuery() ->whereIn( 'id', - $this->getUserSearchSubQuery($searchValue) + $this->getUserSearchSubQuery($bit) ); return true; diff --git a/extensions/nicknames/src/SaveNicknameToDatabase.php b/extensions/nicknames/src/SaveNicknameToDatabase.php index 54b19d33e..8695c8814 100644 --- a/extensions/nicknames/src/SaveNicknameToDatabase.php +++ b/extensions/nicknames/src/SaveNicknameToDatabase.php @@ -15,17 +15,12 @@ use Illuminate\Support\Arr; class SaveNicknameToDatabase { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - public function handle(Saving $event) + public function handle(Saving $event): void { $user = $event->user; $data = $event->data; diff --git a/extensions/package-manager/src/Api/Controller/CheckForUpdatesController.php b/extensions/package-manager/src/Api/Controller/CheckForUpdatesController.php index a1d37087b..04a0d97c0 100755 --- a/extensions/package-manager/src/Api/Controller/CheckForUpdatesController.php +++ b/extensions/package-manager/src/Api/Controller/CheckForUpdatesController.php @@ -19,19 +19,11 @@ use Psr\Http\Server\RequestHandlerInterface; class CheckForUpdatesController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - */ public function handle(ServerRequestInterface $request): ResponseInterface { $actor = RequestUtil::getActor($request); diff --git a/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php b/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php index 158618e5d..2bd9793d0 100755 --- a/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php +++ b/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php @@ -20,19 +20,11 @@ use Psr\Http\Server\RequestHandlerInterface; class GlobalUpdateController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - */ public function handle(ServerRequestInterface $request): ResponseInterface { $actor = RequestUtil::getActor($request); diff --git a/extensions/package-manager/src/Api/Controller/ListTasksController.php b/extensions/package-manager/src/Api/Controller/ListTasksController.php index 115888500..804bd3a58 100644 --- a/extensions/package-manager/src/Api/Controller/ListTasksController.php +++ b/extensions/package-manager/src/Api/Controller/ListTasksController.php @@ -19,28 +19,15 @@ use Tobscure\JsonApi\Document; class ListTasksController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = TaskSerializer::class; + public ?string $serializer = TaskSerializer::class; - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var TaskRepository - */ - protected $repository; - - public function __construct(UrlGenerator $url, TaskRepository $repository) - { - $this->url = $url; - $this->repository = $repository; + public function __construct( + protected UrlGenerator $url, + protected TaskRepository $repository + ) { } - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); diff --git a/extensions/package-manager/src/Api/Controller/MajorUpdateController.php b/extensions/package-manager/src/Api/Controller/MajorUpdateController.php index a7bf3deb3..d2e41526b 100755 --- a/extensions/package-manager/src/Api/Controller/MajorUpdateController.php +++ b/extensions/package-manager/src/Api/Controller/MajorUpdateController.php @@ -21,14 +21,9 @@ use Psr\Http\Server\RequestHandlerInterface; class MajorUpdateController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } public function handle(ServerRequestInterface $request): ResponseInterface diff --git a/extensions/package-manager/src/Api/Controller/MinorUpdateController.php b/extensions/package-manager/src/Api/Controller/MinorUpdateController.php index 50b6d2c03..f2aeee206 100755 --- a/extensions/package-manager/src/Api/Controller/MinorUpdateController.php +++ b/extensions/package-manager/src/Api/Controller/MinorUpdateController.php @@ -20,19 +20,11 @@ use Psr\Http\Server\RequestHandlerInterface; class MinorUpdateController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - */ public function handle(ServerRequestInterface $request): ResponseInterface { $actor = RequestUtil::getActor($request); diff --git a/extensions/package-manager/src/Api/Controller/RemoveExtensionController.php b/extensions/package-manager/src/Api/Controller/RemoveExtensionController.php index 1e3071f67..de760a194 100755 --- a/extensions/package-manager/src/Api/Controller/RemoveExtensionController.php +++ b/extensions/package-manager/src/Api/Controller/RemoveExtensionController.php @@ -21,14 +21,9 @@ use Psr\Http\Server\RequestHandlerInterface; class RemoveExtensionController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } public function handle(ServerRequestInterface $request): ResponseInterface diff --git a/extensions/package-manager/src/Api/Controller/RequireExtensionController.php b/extensions/package-manager/src/Api/Controller/RequireExtensionController.php index 52465626a..5f05938db 100755 --- a/extensions/package-manager/src/Api/Controller/RequireExtensionController.php +++ b/extensions/package-manager/src/Api/Controller/RequireExtensionController.php @@ -20,14 +20,9 @@ use Psr\Http\Server\RequestHandlerInterface; class RequireExtensionController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } public function handle(ServerRequestInterface $request): ResponseInterface diff --git a/extensions/package-manager/src/Api/Controller/UpdateExtensionController.php b/extensions/package-manager/src/Api/Controller/UpdateExtensionController.php index 0b9833f13..6b59dd2de 100755 --- a/extensions/package-manager/src/Api/Controller/UpdateExtensionController.php +++ b/extensions/package-manager/src/Api/Controller/UpdateExtensionController.php @@ -21,14 +21,9 @@ use Psr\Http\Server\RequestHandlerInterface; class UpdateExtensionController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } public function handle(ServerRequestInterface $request): ResponseInterface diff --git a/extensions/package-manager/src/Api/Controller/WhyNotController.php b/extensions/package-manager/src/Api/Controller/WhyNotController.php index 261ce5d58..6ca94dc56 100755 --- a/extensions/package-manager/src/Api/Controller/WhyNotController.php +++ b/extensions/package-manager/src/Api/Controller/WhyNotController.php @@ -20,14 +20,9 @@ use Psr\Http\Server\RequestHandlerInterface; class WhyNotController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } public function handle(ServerRequestInterface $request): ResponseInterface diff --git a/extensions/package-manager/src/Api/Serializer/TaskSerializer.php b/extensions/package-manager/src/Api/Serializer/TaskSerializer.php index dfce8ab47..04f01532a 100644 --- a/extensions/package-manager/src/Api/Serializer/TaskSerializer.php +++ b/extensions/package-manager/src/Api/Serializer/TaskSerializer.php @@ -15,18 +15,12 @@ use InvalidArgumentException; class TaskSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'package-manager-tasks'; /** - * {@inheritdoc} - * - * @param Task $model * @throws InvalidArgumentException */ - protected function getDefaultAttributes($model) + protected function getDefaultAttributes(object|array $model): array { if (! ($model instanceof Task)) { throw new InvalidArgumentException( diff --git a/extensions/package-manager/src/Command/AbstractActionCommand.php b/extensions/package-manager/src/Command/AbstractActionCommand.php index 3f6924c8f..29565deb0 100644 --- a/extensions/package-manager/src/Command/AbstractActionCommand.php +++ b/extensions/package-manager/src/Command/AbstractActionCommand.php @@ -13,15 +13,8 @@ use Flarum\PackageManager\Task\Task; abstract class AbstractActionCommand { - /** - * @var Task|null - */ - public $task = null; - - /** - * @var string|null - */ - public $package = null; + public ?Task $task = null; + public ?string $package = null; abstract public function getOperationName(): string; } diff --git a/extensions/package-manager/src/Command/CheckForUpdates.php b/extensions/package-manager/src/Command/CheckForUpdates.php index 2ca6efcb4..8f91a8ffb 100755 --- a/extensions/package-manager/src/Command/CheckForUpdates.php +++ b/extensions/package-manager/src/Command/CheckForUpdates.php @@ -14,14 +14,9 @@ use Flarum\User\User; class CheckForUpdates extends AbstractActionCommand { - /** - * @var \Flarum\User\User - */ - public $actor; - - public function __construct(User $actor) - { - $this->actor = $actor; + public function __construct( + public User $actor + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/CheckForUpdatesHandler.php b/extensions/package-manager/src/Command/CheckForUpdatesHandler.php index c7a81865c..0462dd1ae 100755 --- a/extensions/package-manager/src/Command/CheckForUpdatesHandler.php +++ b/extensions/package-manager/src/Command/CheckForUpdatesHandler.php @@ -16,20 +16,10 @@ use Symfony\Component\Console\Input\ArrayInput; class CheckForUpdatesHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var \Flarum\PackageManager\Settings\LastUpdateCheck - */ - protected $lastUpdateCheck; - - public function __construct(ComposerAdapter $composer, LastUpdateCheck $lastUpdateCheck) - { - $this->composer = $composer; - $this->lastUpdateCheck = $lastUpdateCheck; + public function __construct( + private ComposerAdapter $composer, + private LastUpdateCheck $lastUpdateCheck + ) { } /** @@ -50,7 +40,7 @@ class CheckForUpdatesHandler * * @throws ComposerCommandFailedException */ - public function handle(CheckForUpdates $command) + public function handle(CheckForUpdates $command): array { $firstOutput = $this->runComposerCommand(false, $command); $firstOutput = json_decode($this->cleanJson($firstOutput), true); diff --git a/extensions/package-manager/src/Command/GlobalUpdate.php b/extensions/package-manager/src/Command/GlobalUpdate.php index a2fb69f34..610a92e34 100644 --- a/extensions/package-manager/src/Command/GlobalUpdate.php +++ b/extensions/package-manager/src/Command/GlobalUpdate.php @@ -14,14 +14,9 @@ use Flarum\User\User; class GlobalUpdate extends AbstractActionCommand { - /** - * @var \Flarum\User\User - */ - public $actor; - - public function __construct(User $actor) - { - $this->actor = $actor; + public function __construct( + public User $actor + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/GlobalUpdateHandler.php b/extensions/package-manager/src/Command/GlobalUpdateHandler.php index 121761a9f..b9e80ed31 100644 --- a/extensions/package-manager/src/Command/GlobalUpdateHandler.php +++ b/extensions/package-manager/src/Command/GlobalUpdateHandler.php @@ -18,32 +18,14 @@ use Symfony\Component\Console\Input\StringInput; class GlobalUpdateHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var FlarumDispatcher - */ - protected $commandDispatcher; - - public function __construct(ComposerAdapter $composer, Dispatcher $events, FlarumDispatcher $commandDispatcher) - { - $this->composer = $composer; - $this->events = $events; - $this->commandDispatcher = $commandDispatcher; + public function __construct( + protected ComposerAdapter $composer, + protected Dispatcher $events, + protected FlarumDispatcher $commandDispatcher + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException|ComposerUpdateFailedException - */ - public function handle(GlobalUpdate $command) + public function handle(GlobalUpdate $command): void { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Command/MajorUpdate.php b/extensions/package-manager/src/Command/MajorUpdate.php index 97bae589b..58970e028 100644 --- a/extensions/package-manager/src/Command/MajorUpdate.php +++ b/extensions/package-manager/src/Command/MajorUpdate.php @@ -14,20 +14,10 @@ use Flarum\User\User; class MajorUpdate extends AbstractActionCommand { - /** - * @var \Flarum\User\User - */ - public $actor; - - /** - * @var bool - */ - public $dryRun; - - public function __construct(User $actor, bool $dryRun) - { - $this->actor = $actor; - $this->dryRun = $dryRun; + public function __construct( + public User $actor, + public bool $dryRun + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/MajorUpdateHandler.php b/extensions/package-manager/src/Command/MajorUpdateHandler.php index c6d95bd8b..52b020a5d 100644 --- a/extensions/package-manager/src/Command/MajorUpdateHandler.php +++ b/extensions/package-manager/src/Command/MajorUpdateHandler.php @@ -20,38 +20,12 @@ use Symfony\Component\Console\Input\ArrayInput; class MajorUpdateHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var LastUpdateCheck - */ - protected $lastUpdateCheck; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var ComposerJson - */ - protected $composerJson; - - /** - * @param ComposerAdapter $composer - * @param LastUpdateCheck $lastUpdateCheck - * @param Dispatcher $events - * @param ComposerJson $composerJson - */ - public function __construct(ComposerAdapter $composer, LastUpdateCheck $lastUpdateCheck, Dispatcher $events, ComposerJson $composerJson) - { - $this->composer = $composer; - $this->lastUpdateCheck = $lastUpdateCheck; - $this->events = $events; - $this->composerJson = $composerJson; + public function __construct( + protected ComposerAdapter $composer, + protected LastUpdateCheck $lastUpdateCheck, + protected Dispatcher $events, + protected ComposerJson $composerJson + ) { } /** @@ -64,7 +38,7 @@ class MajorUpdateHandler * @throws \Flarum\User\Exception\PermissionDeniedException * @throws NoNewMajorVersionException|MajorUpdateFailedException */ - public function handle(MajorUpdate $command) + public function handle(MajorUpdate $command): void { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Command/MinorUpdate.php b/extensions/package-manager/src/Command/MinorUpdate.php index e1cb08101..c32c52183 100755 --- a/extensions/package-manager/src/Command/MinorUpdate.php +++ b/extensions/package-manager/src/Command/MinorUpdate.php @@ -14,14 +14,9 @@ use Flarum\User\User; class MinorUpdate extends AbstractActionCommand { - /** - * @var \Flarum\User\User - */ - public $actor; - - public function __construct(User $actor) - { - $this->actor = $actor; + public function __construct( + public User $actor + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/MinorUpdateHandler.php b/extensions/package-manager/src/Command/MinorUpdateHandler.php index 264b7b9e2..6f84bf62a 100755 --- a/extensions/package-manager/src/Command/MinorUpdateHandler.php +++ b/extensions/package-manager/src/Command/MinorUpdateHandler.php @@ -19,39 +19,15 @@ use Symfony\Component\Console\Input\StringInput; class MinorUpdateHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var \Flarum\PackageManager\Settings\LastUpdateCheck - */ - protected $lastUpdateCheck; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var ComposerJson - */ - protected $composerJson; - - public function __construct(ComposerAdapter $composer, LastUpdateCheck $lastUpdateCheck, Dispatcher $events, ComposerJson $composerJson) - { - $this->composer = $composer; - $this->lastUpdateCheck = $lastUpdateCheck; - $this->events = $events; - $this->composerJson = $composerJson; + public function __construct( + protected ComposerAdapter $composer, + protected LastUpdateCheck $lastUpdateCheck, + protected Dispatcher $events, + protected ComposerJson $composerJson + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws ComposerUpdateFailedException - */ - public function handle(MinorUpdate $command) + public function handle(MinorUpdate $command): void { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Command/RemoveExtension.php b/extensions/package-manager/src/Command/RemoveExtension.php index 853585dad..a33f23ed0 100755 --- a/extensions/package-manager/src/Command/RemoveExtension.php +++ b/extensions/package-manager/src/Command/RemoveExtension.php @@ -14,20 +14,10 @@ use Flarum\User\User; class RemoveExtension extends AbstractActionCommand { - /** - * @var User - */ - public $actor; - - /** - * @var string - */ - public $extensionId; - - public function __construct(User $actor, string $extensionId) - { - $this->actor = $actor; - $this->extensionId = $extensionId; + public function __construct( + public User $actor, + public string $extensionId + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/RemoveExtensionHandler.php b/extensions/package-manager/src/Command/RemoveExtensionHandler.php index 639cac5c3..d1a0b64f6 100755 --- a/extensions/package-manager/src/Command/RemoveExtensionHandler.php +++ b/extensions/package-manager/src/Command/RemoveExtensionHandler.php @@ -19,33 +19,14 @@ use Symfony\Component\Console\Input\StringInput; class RemoveExtensionHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var Dispatcher - */ - protected $events; - - public function __construct(ComposerAdapter $composer, ExtensionManager $extensions, Dispatcher $events) - { - $this->composer = $composer; - $this->extensions = $extensions; - $this->events = $events; + public function __construct( + private ComposerAdapter $composer, + private ExtensionManager $extensions, + private Dispatcher $events + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws \Exception - */ - public function handle(RemoveExtension $command) + public function handle(RemoveExtension $command): void { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Command/RequireExtension.php b/extensions/package-manager/src/Command/RequireExtension.php index 88bc1b975..7d18474ea 100755 --- a/extensions/package-manager/src/Command/RequireExtension.php +++ b/extensions/package-manager/src/Command/RequireExtension.php @@ -14,20 +14,10 @@ use Flarum\User\User; class RequireExtension extends AbstractActionCommand { - /** - * @var User - */ - public $actor; - - /** - * @var string - */ - public $package; - - public function __construct(User $actor, string $package) - { - $this->actor = $actor; - $this->package = $package; + public function __construct( + public User $actor, + public ?string $package + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/RequireExtensionHandler.php b/extensions/package-manager/src/Command/RequireExtensionHandler.php index 3d98fe9aa..383706b26 100755 --- a/extensions/package-manager/src/Command/RequireExtensionHandler.php +++ b/extensions/package-manager/src/Command/RequireExtensionHandler.php @@ -21,39 +21,15 @@ use Symfony\Component\Console\Input\StringInput; class RequireExtensionHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var RequirePackageValidator - */ - protected $validator; - - /** - * @var Dispatcher - */ - protected $events; - - public function __construct(ComposerAdapter $composer, ExtensionManager $extensions, RequirePackageValidator $validator, Dispatcher $events) - { - $this->composer = $composer; - $this->extensions = $extensions; - $this->validator = $validator; - $this->events = $events; + public function __construct( + protected ComposerAdapter $composer, + protected ExtensionManager $extensions, + protected RequirePackageValidator $validator, + protected Dispatcher $events + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws \Exception - */ - public function handle(RequireExtension $command) + public function handle(RequireExtension $command): array { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Command/UpdateExtension.php b/extensions/package-manager/src/Command/UpdateExtension.php index cf74c484c..f07399db6 100755 --- a/extensions/package-manager/src/Command/UpdateExtension.php +++ b/extensions/package-manager/src/Command/UpdateExtension.php @@ -14,20 +14,10 @@ use Flarum\User\User; class UpdateExtension extends AbstractActionCommand { - /** - * @var User - */ - public $actor; - - /** - * @var string - */ - public $extensionId; - - public function __construct(User $actor, string $extensionId) - { - $this->actor = $actor; - $this->extensionId = $extensionId; + public function __construct( + public User $actor, + public string $extensionId + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/UpdateExtensionHandler.php b/extensions/package-manager/src/Command/UpdateExtensionHandler.php index dde622d85..1b5787032 100755 --- a/extensions/package-manager/src/Command/UpdateExtensionHandler.php +++ b/extensions/package-manager/src/Command/UpdateExtensionHandler.php @@ -23,57 +23,17 @@ use Symfony\Component\Console\Input\StringInput; class UpdateExtensionHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var UpdateExtensionValidator - */ - protected $validator; - - /** - * @var LastUpdateCheck - */ - protected $lastUpdateCheck; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var Paths - */ - protected $paths; - public function __construct( - ComposerAdapter $composer, - ExtensionManager $extensions, - UpdateExtensionValidator $validator, - LastUpdateCheck $lastUpdateCheck, - Dispatcher $events, - Paths $paths + public ComposerAdapter $composer, + public ExtensionManager $extensions, + public UpdateExtensionValidator $validator, + public LastUpdateCheck $lastUpdateCheck, + public Dispatcher $events, + public Paths $paths ) { - $this->composer = $composer; - $this->extensions = $extensions; - $this->validator = $validator; - $this->lastUpdateCheck = $lastUpdateCheck; - $this->events = $events; - $this->paths = $paths; } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws \Exception - */ - public function handle(UpdateExtension $command) + public function handle(UpdateExtension $command): void { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Command/WhyNot.php b/extensions/package-manager/src/Command/WhyNot.php index 4e2d0fc2a..b8374f406 100755 --- a/extensions/package-manager/src/Command/WhyNot.php +++ b/extensions/package-manager/src/Command/WhyNot.php @@ -14,26 +14,11 @@ use Flarum\User\User; class WhyNot extends AbstractActionCommand { - /** - * @var User - */ - public $actor; - - /** - * @var string - */ - public $package; - - /** - * @var string - */ - public $version; - - public function __construct(User $actor, string $package, string $version) - { - $this->actor = $actor; - $this->package = $package; - $this->version = $version; + public function __construct( + public User $actor, + public ?string $package, + public string $version + ) { } public function getOperationName(): string diff --git a/extensions/package-manager/src/Command/WhyNotHandler.php b/extensions/package-manager/src/Command/WhyNotHandler.php index 33f4a2ec0..08ae7e6c0 100755 --- a/extensions/package-manager/src/Command/WhyNotHandler.php +++ b/extensions/package-manager/src/Command/WhyNotHandler.php @@ -17,33 +17,14 @@ use Symfony\Component\Console\Input\StringInput; class WhyNotHandler { - /** - * @var ComposerAdapter - */ - protected $composer; - - /** - * @var WhyNotValidator - */ - protected $validator; - - /** - * @var Dispatcher - */ - protected $events; - - public function __construct(ComposerAdapter $composer, WhyNotValidator $validator, Dispatcher $events) - { - $this->composer = $composer; - $this->validator = $validator; - $this->events = $events; + public function __construct( + protected ComposerAdapter $composer, + protected WhyNotValidator $validator, + protected Dispatcher $events + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws \Exception - */ - public function handle(WhyNot $command) + public function handle(WhyNot $command): array { $command->actor->assertAdmin(); diff --git a/extensions/package-manager/src/Composer/ComposerAdapter.php b/extensions/package-manager/src/Composer/ComposerAdapter.php index 1902735ce..36f1bdc86 100644 --- a/extensions/package-manager/src/Composer/ComposerAdapter.php +++ b/extensions/package-manager/src/Composer/ComposerAdapter.php @@ -22,31 +22,13 @@ use Symfony\Component\Console\Output\BufferedOutput; */ class ComposerAdapter { - /** - * @var Application - */ - private $application; + private readonly BufferedOutput $output; - /** - * @var OutputLogger - */ - private $logger; - - /** - * @var BufferedOutput - */ - private $output; - - /** - * @var Paths - */ - private $paths; - - public function __construct(Application $application, OutputLogger $logger, Paths $paths) - { - $this->application = $application; - $this->logger = $logger; - $this->paths = $paths; + public function __construct( + private readonly Application $application, + private readonly OutputLogger $logger, + private readonly Paths $paths + ) { $this->output = new BufferedOutput(); } @@ -73,7 +55,7 @@ class ComposerAdapter return new ComposerOutput($exitCode, $output); } - public static function setPhpVersion(string $phpVersion) + public static function setPhpVersion(string $phpVersion): void { Config::$defaultConfig['platform']['php'] = $phpVersion; } diff --git a/extensions/package-manager/src/Composer/ComposerJson.php b/extensions/package-manager/src/Composer/ComposerJson.php index beb27d71a..b16b55266 100644 --- a/extensions/package-manager/src/Composer/ComposerJson.php +++ b/extensions/package-manager/src/Composer/ComposerJson.php @@ -15,32 +15,19 @@ use Illuminate\Support\Str; class ComposerJson { - /** - * @var Paths - */ - protected $paths; + protected array $initialJson; - /** - * @var Filesystem - */ - protected $filesystem; - - /** - * @var array - */ - protected $initialJson; - - public function __construct(Paths $paths, Filesystem $filesystem) - { - $this->paths = $paths; - $this->filesystem = $filesystem; + public function __construct( + protected Paths $paths, + protected Filesystem $filesystem + ) { } public function require(string $packageName, string $version): void { $composerJson = $this->get(); - if (strpos($packageName, '*') === false) { + if (! str_contains($packageName, '*')) { $composerJson['require'][$packageName] = $version; } else { foreach ($composerJson['require'] as $p => $v) { diff --git a/extensions/package-manager/src/Composer/ComposerOutput.php b/extensions/package-manager/src/Composer/ComposerOutput.php index 87719880a..6c90a39d1 100644 --- a/extensions/package-manager/src/Composer/ComposerOutput.php +++ b/extensions/package-manager/src/Composer/ComposerOutput.php @@ -11,20 +11,10 @@ namespace Flarum\PackageManager\Composer; class ComposerOutput { - /** - * @var int - */ - protected $exitCode; - - /** - * @var string - */ - protected $contents; - - public function __construct(int $exitCode, string $contents) - { - $this->exitCode = $exitCode; - $this->contents = $contents; + public function __construct( + protected int $exitCode, + protected string $contents + ) { } public function getExitCode(): int diff --git a/extensions/package-manager/src/Event/FlarumUpdated.php b/extensions/package-manager/src/Event/FlarumUpdated.php index 108d10ab9..3a58ebca6 100644 --- a/extensions/package-manager/src/Event/FlarumUpdated.php +++ b/extensions/package-manager/src/Event/FlarumUpdated.php @@ -17,19 +17,9 @@ class FlarumUpdated public const MINOR = 'minor'; public const MAJOR = 'major'; - /** - * @var User - */ - public $actor; - - /** - * @var string - */ - public $type; - - public function __construct(User $actor, string $type) - { - $this->actor = $actor; - $this->type = $type; + public function __construct( + public User $actor, + public string $type + ) { } } diff --git a/extensions/package-manager/src/Exception/ComposerCommandFailedException.php b/extensions/package-manager/src/Exception/ComposerCommandFailedException.php index 318f1fb37..ab2f2ff29 100755 --- a/extensions/package-manager/src/Exception/ComposerCommandFailedException.php +++ b/extensions/package-manager/src/Exception/ComposerCommandFailedException.php @@ -13,20 +13,12 @@ use Exception; class ComposerCommandFailedException extends Exception { - /** - * @var string - */ - public $packageName; - - /** - * @var array - */ - public $details = []; - - public function __construct(string $packageName, string $output) - { - $this->packageName = $packageName; + public array $details = []; + public function __construct( + public string $packageName, + string $output, + ) { parent::__construct($output); } diff --git a/extensions/package-manager/src/Exception/MajorUpdateFailedException.php b/extensions/package-manager/src/Exception/MajorUpdateFailedException.php index e494176cf..8b205ac25 100644 --- a/extensions/package-manager/src/Exception/MajorUpdateFailedException.php +++ b/extensions/package-manager/src/Exception/MajorUpdateFailedException.php @@ -17,15 +17,11 @@ class MajorUpdateFailedException extends ComposerCommandFailedException { private const INCOMPATIBLE_REGEX = '/^ +- (?[A-z0-9\/-]+) [A-z0-9.-_\/]+ requires flarum\/core (?(?:[A-z0-9.><=_ -](?!->))+)/m'; - /** - * @var string - */ - private $majorVersion; - - public function __construct(string $packageName, string $output, string $majorVersion) - { - $this->majorVersion = $majorVersion; - + public function __construct( + string $packageName, + string $output, + private readonly string $majorVersion + ) { parent::__construct($packageName, $output); } diff --git a/extensions/package-manager/src/Extension/Event/Installed.php b/extensions/package-manager/src/Extension/Event/Installed.php index 8d56ddd96..f8266b096 100755 --- a/extensions/package-manager/src/Extension/Event/Installed.php +++ b/extensions/package-manager/src/Extension/Event/Installed.php @@ -11,13 +11,8 @@ namespace Flarum\PackageManager\Extension\Event; class Installed { - /** - * @var string - */ - public $extensionId; - - public function __construct(string $extensionId) - { - $this->extensionId = $extensionId; + public function __construct( + public string $extensionId + ) { } } diff --git a/extensions/package-manager/src/Extension/Event/Removed.php b/extensions/package-manager/src/Extension/Event/Removed.php index 369453980..960316f64 100755 --- a/extensions/package-manager/src/Extension/Event/Removed.php +++ b/extensions/package-manager/src/Extension/Event/Removed.php @@ -13,13 +13,8 @@ use Flarum\Extension\Extension; class Removed { - /** - * @var Extension - */ - public $extension; - - public function __construct(Extension $extension) - { - $this->extension = $extension; + public function __construct( + public Extension $extension + ) { } } diff --git a/extensions/package-manager/src/Extension/Event/Updated.php b/extensions/package-manager/src/Extension/Event/Updated.php index 61c9e55ec..c0f38ba37 100755 --- a/extensions/package-manager/src/Extension/Event/Updated.php +++ b/extensions/package-manager/src/Extension/Event/Updated.php @@ -14,19 +14,9 @@ use Flarum\User\User; class Updated { - /** - * @var User - */ - public $actor; - - /** - * @var Extension - */ - public $extension; - - public function __construct(User $actor, Extension $extension) - { - $this->actor = $actor; - $this->extension = $extension; + public function __construct( + public User $actor, + public Extension $extension + ) { } } diff --git a/extensions/package-manager/src/Job/ComposerCommandJob.php b/extensions/package-manager/src/Job/ComposerCommandJob.php index be9e2140f..ec11d55dc 100644 --- a/extensions/package-manager/src/Job/ComposerCommandJob.php +++ b/extensions/package-manager/src/Job/ComposerCommandJob.php @@ -18,23 +18,13 @@ use Throwable; class ComposerCommandJob extends AbstractJob { - /** - * @var AbstractActionCommand - */ - protected $command; - - /** - * @var string - */ - protected $phpVersion; - - public function __construct(AbstractActionCommand $command, string $phpVersion) - { - $this->command = $command; - $this->phpVersion = $phpVersion; + public function __construct( + protected AbstractActionCommand $command, + protected string $phpVersion + ) { } - public function handle(Dispatcher $bus) + public function handle(Dispatcher $bus): void { try { ComposerAdapter::setPhpVersion($this->phpVersion); @@ -49,7 +39,7 @@ class ComposerCommandJob extends AbstractJob } } - public function abort(Throwable $exception) + public function abort(Throwable $exception): void { if (! $this->command->task->output) { $this->command->task->output = $exception->getMessage(); @@ -60,7 +50,7 @@ class ComposerCommandJob extends AbstractJob $this->fail($exception); } - public function middleware() + public function middleware(): array { return [ new WithoutOverlapping(), diff --git a/extensions/package-manager/src/Job/Dispatcher.php b/extensions/package-manager/src/Job/Dispatcher.php index 20026dc07..7eecadf6f 100644 --- a/extensions/package-manager/src/Job/Dispatcher.php +++ b/extensions/package-manager/src/Job/Dispatcher.php @@ -18,35 +18,18 @@ use Illuminate\Queue\SyncQueue; class Dispatcher { - /** - * @var Bus - */ - protected $bus; - - /** - * @var Queue - */ - protected $queue; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - /** * Overrides the user setting for execution mode if set. * Runs synchronously regardless of user setting if set true. * Asynchronously if set false. - * - * @var bool|null */ - protected $runSyncOverride; + protected ?bool $runSyncOverride; - public function __construct(Bus $bus, Queue $queue, SettingsRepositoryInterface $settings) - { - $this->bus = $bus; - $this->queue = $queue; - $this->settings = $settings; + public function __construct( + protected Bus $bus, + protected Queue $queue, + protected SettingsRepositoryInterface $settings + ) { } public function sync(): self diff --git a/extensions/package-manager/src/Job/DispatcherResponse.php b/extensions/package-manager/src/Job/DispatcherResponse.php index 4ff8790a4..fb006cc4f 100644 --- a/extensions/package-manager/src/Job/DispatcherResponse.php +++ b/extensions/package-manager/src/Job/DispatcherResponse.php @@ -11,13 +11,9 @@ namespace Flarum\PackageManager\Job; class DispatcherResponse { - public $queueJobs; - - public $data; - - public function __construct(bool $queueJobs, ?array $data) - { - $this->queueJobs = $queueJobs; - $this->data = $data; + public function __construct( + public bool $queueJobs, + public ?array $data + ) { } } diff --git a/extensions/package-manager/src/Listener/ClearCacheAfterUpdate.php b/extensions/package-manager/src/Listener/ClearCacheAfterUpdate.php index 75a9417f0..c4c8ed06d 100644 --- a/extensions/package-manager/src/Listener/ClearCacheAfterUpdate.php +++ b/extensions/package-manager/src/Listener/ClearCacheAfterUpdate.php @@ -18,26 +18,11 @@ use Symfony\Component\Console\Output\NullOutput; class ClearCacheAfterUpdate { - /** - * @var ClearCacheCommand - */ - private $clearCache; - - /** - * @var AssetsPublishCommand - */ - private $publishAssets; - - /** - * @var MigrateCommand - */ - private $migrate; - - public function __construct(ClearCacheCommand $clearCache, AssetsPublishCommand $publishAssets, MigrateCommand $migrate) - { - $this->clearCache = $clearCache; - $this->publishAssets = $publishAssets; - $this->migrate = $migrate; + public function __construct( + private ClearCacheCommand $clearCache, + private AssetsPublishCommand $publishAssets, + private MigrateCommand $migrate + ) { } /** diff --git a/extensions/package-manager/src/Listener/ReCheckForUpdates.php b/extensions/package-manager/src/Listener/ReCheckForUpdates.php index dfb60dca1..eb03a7717 100644 --- a/extensions/package-manager/src/Listener/ReCheckForUpdates.php +++ b/extensions/package-manager/src/Listener/ReCheckForUpdates.php @@ -18,31 +18,14 @@ use Flarum\PackageManager\Settings\LastUpdateRun; class ReCheckForUpdates { - /** - * @var LastUpdateRun - */ - private $lastUpdateRun; - /** - * @var LastUpdateCheck - */ - private $lastUpdateCheck; - - /** - * @var Dispatcher - */ - private $bus; - - public function __construct(LastUpdateRun $lastUpdateRun, LastUpdateCheck $lastUpdateCheck, Dispatcher $bus) - { - $this->lastUpdateRun = $lastUpdateRun; - $this->lastUpdateCheck = $lastUpdateCheck; - $this->bus = $bus; + public function __construct( + private readonly LastUpdateRun $lastUpdateRun, + private readonly LastUpdateCheck $lastUpdateCheck, + private readonly Dispatcher $bus + ) { } - /** - * @param FlarumUpdated|Updated $event - */ - public function handle($event): void + public function handle(FlarumUpdated|Updated $event): void { $previousUpdateCheck = $this->lastUpdateCheck->get(); diff --git a/extensions/package-manager/src/OutputLogger.php b/extensions/package-manager/src/OutputLogger.php index 6442d05d8..1fe65e0ad 100644 --- a/extensions/package-manager/src/OutputLogger.php +++ b/extensions/package-manager/src/OutputLogger.php @@ -13,14 +13,9 @@ use Psr\Log\LoggerInterface; class OutputLogger { - /** - * @var LoggerInterface - */ - protected $logger; - - public function __construct(LoggerInterface $logger) - { - $this->logger = $logger; + public function __construct( + protected LoggerInterface $logger + ) { } public function log(string $input, string $output, int $exitCode): void diff --git a/extensions/package-manager/src/PackageManagerServiceProvider.php b/extensions/package-manager/src/PackageManagerServiceProvider.php index 4717b2b93..aa2599d2e 100755 --- a/extensions/package-manager/src/PackageManagerServiceProvider.php +++ b/extensions/package-manager/src/PackageManagerServiceProvider.php @@ -29,7 +29,7 @@ use Monolog\Logger; class PackageManagerServiceProvider extends AbstractServiceProvider { - public function register() + public function register(): void { $this->container->singleton(ComposerAdapter::class, function (Container $container) { // This should only ever be resolved when running composer commands, @@ -67,7 +67,7 @@ class PackageManagerServiceProvider extends AbstractServiceProvider }); } - public function boot(Container $container) + public function boot(Container $container): void { /** @var Dispatcher $events */ $events = $container->make('events'); diff --git a/extensions/package-manager/src/RequirePackageValidator.php b/extensions/package-manager/src/RequirePackageValidator.php index 51fedf355..554778bdf 100755 --- a/extensions/package-manager/src/RequirePackageValidator.php +++ b/extensions/package-manager/src/RequirePackageValidator.php @@ -15,10 +15,7 @@ class RequirePackageValidator extends AbstractValidator { public const PACKAGE_NAME_REGEX = '/^[A-z0-9-_]+\/[A-z-0-9]+(?::[A-z-0-9.->=<_]+){0,1}$/i'; - /** - * {@inheritdoc} - */ - protected $rules = [ + protected array $rules = [ 'package' => ['required', 'string', 'regex:'.self::PACKAGE_NAME_REGEX] ]; } diff --git a/extensions/package-manager/src/Settings/JsonSetting.php b/extensions/package-manager/src/Settings/JsonSetting.php index 834ab780d..c25b3008a 100644 --- a/extensions/package-manager/src/Settings/JsonSetting.php +++ b/extensions/package-manager/src/Settings/JsonSetting.php @@ -11,7 +11,7 @@ namespace Flarum\PackageManager\Settings; interface JsonSetting { - public function with(string $key, $value): self; + public function with(string $key, mixed $value): self; public function save(): array; diff --git a/extensions/package-manager/src/Settings/LastUpdateCheck.php b/extensions/package-manager/src/Settings/LastUpdateCheck.php index c84b6a330..45719ce47 100755 --- a/extensions/package-manager/src/Settings/LastUpdateCheck.php +++ b/extensions/package-manager/src/Settings/LastUpdateCheck.php @@ -15,19 +15,14 @@ use Illuminate\Support\Arr; class LastUpdateCheck implements JsonSetting { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; + protected array $data = []; - protected $data = []; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - public function with(string $key, $value): JsonSetting + public function with(string $key, mixed $value): JsonSetting { $this->data[$key] = $value; diff --git a/extensions/package-manager/src/Settings/LastUpdateRun.php b/extensions/package-manager/src/Settings/LastUpdateRun.php index 4a21f9f14..80178fa5d 100644 --- a/extensions/package-manager/src/Settings/LastUpdateRun.php +++ b/extensions/package-manager/src/Settings/LastUpdateRun.php @@ -17,22 +17,12 @@ class LastUpdateRun implements JsonSetting { public const SUCCESS = 'success'; public const FAILURE = 'failure'; + protected array $data; + protected ?string $activeUpdate; - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - protected $data; - - /** - * @var string|null - */ - protected $activeUpdate; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings, + ) { $this->data = self::default(); } @@ -47,7 +37,7 @@ class LastUpdateRun implements JsonSetting return $this; } - public function with(string $key, $value): JsonSetting + public function with(string $key, mixed $value): JsonSetting { $this->data[$this->activeUpdate][$key] = $value; diff --git a/extensions/package-manager/src/Task/TaskRepository.php b/extensions/package-manager/src/Task/TaskRepository.php index 05f014b38..2895d2732 100644 --- a/extensions/package-manager/src/Task/TaskRepository.php +++ b/extensions/package-manager/src/Task/TaskRepository.php @@ -17,17 +17,12 @@ class TaskRepository /** * @return Builder */ - public function query() + public function query(): Builder { return Task::query(); } - /** - * @param int $id - * @param User $actor - * @return Task - */ - public function findOrFail($id, User $actor = null): Task + public function findOrFail(int $id, ?User $actor = null): Task { return Task::findOrFail($id); } diff --git a/extensions/package-manager/src/UpdateExtensionValidator.php b/extensions/package-manager/src/UpdateExtensionValidator.php index 84f817f4d..d49dd40e5 100755 --- a/extensions/package-manager/src/UpdateExtensionValidator.php +++ b/extensions/package-manager/src/UpdateExtensionValidator.php @@ -13,10 +13,7 @@ use Flarum\Foundation\AbstractValidator; class UpdateExtensionValidator extends AbstractValidator { - /** - * {@inheritdoc} - */ - protected $rules = [ + protected array $rules = [ 'extensionId' => 'required|string' ]; } diff --git a/extensions/package-manager/src/WhyNotValidator.php b/extensions/package-manager/src/WhyNotValidator.php index ee5b2ef0e..6fc191e8e 100644 --- a/extensions/package-manager/src/WhyNotValidator.php +++ b/extensions/package-manager/src/WhyNotValidator.php @@ -13,10 +13,7 @@ use Flarum\Foundation\AbstractValidator; class WhyNotValidator extends AbstractValidator { - /** - * {@inheritdoc} - */ - protected $rules = [ + protected array $rules = [ 'package' => ['required', 'string', 'regex:'.RequirePackageValidator::PACKAGE_NAME_REGEX], 'version' => ['sometimes', 'string', 'regex:/(?:\*|[A-z0-9.-]+)/i'] ]; diff --git a/extensions/pusher/src/Api/Controller/AuthController.php b/extensions/pusher/src/Api/Controller/AuthController.php index fa95c6d8f..e0c8b6bfd 100644 --- a/extensions/pusher/src/Api/Controller/AuthController.php +++ b/extensions/pusher/src/Api/Controller/AuthController.php @@ -21,23 +21,11 @@ use Pusher; class AuthController implements RequestHandlerInterface { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @param SettingsRepositoryInterface $settings - */ - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param ServerRequestInterface $request - * @return ResponseInterface - */ public function handle(ServerRequestInterface $request): ResponseInterface { $userChannel = 'private-user'.RequestUtil::getActor($request)->id; diff --git a/extensions/pusher/src/Listener/PushNewPost.php b/extensions/pusher/src/Listener/PushNewPost.php index 390946c25..725452526 100644 --- a/extensions/pusher/src/Listener/PushNewPost.php +++ b/extensions/pusher/src/Listener/PushNewPost.php @@ -18,23 +18,13 @@ use Pusher; class PushNewPost { - /** - * @var Pusher - */ - protected $pusher; - - /** - * @var ExtensionManager - */ - protected $extensions; - - public function __construct(Pusher $pusher, ExtensionManager $extensions) - { - $this->pusher = $pusher; - $this->extensions = $extensions; + public function __construct( + protected Pusher $pusher, + protected ExtensionManager $extensions + ) { } - public function handle(Posted $event) + public function handle(Posted $event): void { $channels = []; diff --git a/extensions/pusher/src/Provider/PusherProvider.php b/extensions/pusher/src/Provider/PusherProvider.php index 18129516b..0c7f50976 100644 --- a/extensions/pusher/src/Provider/PusherProvider.php +++ b/extensions/pusher/src/Provider/PusherProvider.php @@ -11,13 +11,14 @@ namespace Flarum\Pusher\Provider; use Flarum\Foundation\AbstractServiceProvider; use Flarum\Settings\SettingsRepositoryInterface; +use Pusher; class PusherProvider extends AbstractServiceProvider { - public function register() + public function register(): void { - $this->app->bind(\Pusher::class, function () { - $settings = $this->app->make(SettingsRepositoryInterface::class); + $this->container->bind(Pusher::class, function () { + $settings = $this->container->make(SettingsRepositoryInterface::class); $options = []; @@ -25,7 +26,7 @@ class PusherProvider extends AbstractServiceProvider $options['cluster'] = $cluster; } - return new \Pusher( + return new Pusher( $settings->get('flarum-pusher.app_key'), $settings->get('flarum-pusher.app_secret'), $settings->get('flarum-pusher.app_id'), diff --git a/extensions/pusher/src/PusherNotificationDriver.php b/extensions/pusher/src/PusherNotificationDriver.php index 6fb15ee4c..ae7ce08e7 100644 --- a/extensions/pusher/src/PusherNotificationDriver.php +++ b/extensions/pusher/src/PusherNotificationDriver.php @@ -15,19 +15,11 @@ use Illuminate\Contracts\Queue\Queue; class PusherNotificationDriver implements NotificationDriverInterface { - /** - * @var Queue - */ - protected $queue; - - public function __construct(Queue $queue) - { - $this->queue = $queue; + public function __construct( + protected Queue $queue + ) { } - /** - * {@inheritDoc} - */ public function send(BlueprintInterface $blueprint, array $users): void { if (count($users)) { @@ -35,9 +27,6 @@ class PusherNotificationDriver implements NotificationDriverInterface } } - /** - * {@inheritDoc} - */ public function registerType(string $blueprintClass, array $driversEnabledByDefault): void { // ... diff --git a/extensions/pusher/src/SendPusherNotificationsJob.php b/extensions/pusher/src/SendPusherNotificationsJob.php index def83ca28..31f81207f 100644 --- a/extensions/pusher/src/SendPusherNotificationsJob.php +++ b/extensions/pusher/src/SendPusherNotificationsJob.php @@ -16,23 +16,14 @@ use Pusher; class SendPusherNotificationsJob extends AbstractJob { - /** - * @var BlueprintInterface - */ - private $blueprint; - - /** - * @var User[] - */ - private $recipients; - - public function __construct(BlueprintInterface $blueprint, array $recipients) - { - $this->blueprint = $blueprint; - $this->recipients = $recipients; + public function __construct( + private readonly BlueprintInterface $blueprint, + /** @var User[] */ + private readonly array $recipients + ) { } - public function handle(Pusher $pusher) + public function handle(Pusher $pusher): void { foreach ($this->recipients as $user) { if ($user->shouldAlert($this->blueprint::getType())) { diff --git a/extensions/statistics/src/Api/Controller/ShowStatisticsData.php b/extensions/statistics/src/Api/Controller/ShowStatisticsData.php index d6125074e..9319a6d1b 100644 --- a/extensions/statistics/src/Api/Controller/ShowStatisticsData.php +++ b/extensions/statistics/src/Api/Controller/ShowStatisticsData.php @@ -31,30 +31,19 @@ class ShowStatisticsData implements RequestHandlerInterface /** * The amount of time to cache lifetime statistics data for in seconds. */ - public static $lifetimeStatsCacheTtl = 300; + public static int $lifetimeStatsCacheTtl = 300; /** * The amount of time to cache timed statistics data for in seconds. */ - public static $timedStatsCacheTtl = 900; + public static int $timedStatsCacheTtl = 900; - protected $entities = []; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var CacheRepository - */ - protected $cache; - - public function __construct(SettingsRepositoryInterface $settings, CacheRepository $cache) - { - $this->settings = $settings; - $this->cache = $cache; + protected array $entities = []; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected CacheRepository $cache + ) { $this->entities = [ 'users' => [User::query(), 'joined_at'], 'discussions' => [Discussion::query(), 'created_at'], @@ -108,7 +97,7 @@ class ShowStatisticsData implements RequestHandlerInterface return $this->getTimedStatistics($model); } - private function getLifetimeStatistics() + private function getLifetimeStatistics(): array { return $this->cache->remember('flarum-subscriptions.lifetime_stats', self::$lifetimeStatsCacheTtl, function () { return array_map(function ($entity) { @@ -117,14 +106,14 @@ class ShowStatisticsData implements RequestHandlerInterface }); } - private function getTimedStatistics(string $model) + private function getTimedStatistics(string $model): array { return $this->cache->remember("flarum-subscriptions.timed_stats.$model", self::$lifetimeStatsCacheTtl, function () use ($model) { return $this->getTimedCounts($this->entities[$model][0], $this->entities[$model][1]); }); } - private function getTimedCounts(Builder $query, string $column, ?DateTime $startDate = null, ?DateTime $endDate = null) + private function getTimedCounts(Builder $query, string $column, ?DateTime $startDate = null, ?DateTime $endDate = null): array { $diff = $startDate && $endDate ? $startDate->diff($endDate) : null; diff --git a/extensions/sticky/extend.php b/extensions/sticky/extend.php index 5e08a4a08..3a9ff0bc2 100644 --- a/extensions/sticky/extend.php +++ b/extensions/sticky/extend.php @@ -34,7 +34,7 @@ return [ ->type(DiscussionStickiedPost::class), (new Extend\ApiSerializer(DiscussionSerializer::class)) - ->attribute('isSticky', function (DiscussionSerializer $serializer, $discussion) { + ->attribute('isSticky', function (DiscussionSerializer $serializer, Discussion $discussion) { return (bool) $discussion->is_sticky; }) ->attribute('canSticky', function (DiscussionSerializer $serializer, $discussion) { diff --git a/extensions/sticky/src/Event/DiscussionWasStickied.php b/extensions/sticky/src/Event/DiscussionWasStickied.php index 4c4a7b8c6..7f9176910 100644 --- a/extensions/sticky/src/Event/DiscussionWasStickied.php +++ b/extensions/sticky/src/Event/DiscussionWasStickied.php @@ -14,23 +14,9 @@ use Flarum\User\User; class DiscussionWasStickied { - /** - * @var Discussion - */ - public $discussion; - - /** - * @var User - */ - public $user; - - /** - * @param Discussion $discussion - * @param User $user - */ - public function __construct(Discussion $discussion, User $user) - { - $this->discussion = $discussion; - $this->user = $user; + public function __construct( + public Discussion $discussion, + public User $user + ) { } } diff --git a/extensions/sticky/src/Event/DiscussionWasUnstickied.php b/extensions/sticky/src/Event/DiscussionWasUnstickied.php index d224ded98..65ab1a198 100644 --- a/extensions/sticky/src/Event/DiscussionWasUnstickied.php +++ b/extensions/sticky/src/Event/DiscussionWasUnstickied.php @@ -14,23 +14,9 @@ use Flarum\User\User; class DiscussionWasUnstickied { - /** - * @var Discussion - */ - public $discussion; - - /** - * @var User - */ - public $user; - - /** - * @param Discussion $discussion - * @param User $user - */ - public function __construct(Discussion $discussion, User $user) - { - $this->discussion = $discussion; - $this->user = $user; + public function __construct( + public Discussion $discussion, + public User $user + ) { } } diff --git a/extensions/sticky/src/Listener/CreatePostWhenDiscussionIsStickied.php b/extensions/sticky/src/Listener/CreatePostWhenDiscussionIsStickied.php index 5c72779d1..6d1b51a27 100755 --- a/extensions/sticky/src/Listener/CreatePostWhenDiscussionIsStickied.php +++ b/extensions/sticky/src/Listener/CreatePostWhenDiscussionIsStickied.php @@ -17,28 +17,17 @@ use Flarum\User\User; class CreatePostWhenDiscussionIsStickied { - /** - * @param DiscussionWasStickied $event - */ - public static function whenDiscussionWasStickied(DiscussionWasStickied $event) + public static function whenDiscussionWasStickied(DiscussionWasStickied $event): void { static::stickyChanged($event->discussion, $event->user, true); } - /** - * @param DiscussionWasUnstickied $event - */ - public static function whenDiscussionWasUnstickied(DiscussionWasUnstickied $event) + public static function whenDiscussionWasUnstickied(DiscussionWasUnstickied $event): void { static::stickyChanged($event->discussion, $event->user, false); } - /** - * @param Discussion $discussion - * @param User $user - * @param bool $isSticky - */ - protected static function stickyChanged(Discussion $discussion, User $user, $isSticky) + protected static function stickyChanged(Discussion $discussion, User $user, bool $isSticky): void { $post = DiscussionStickiedPost::reply( $discussion->id, diff --git a/extensions/sticky/src/Listener/SaveStickyToDatabase.php b/extensions/sticky/src/Listener/SaveStickyToDatabase.php index a2153fa75..719c92cdf 100755 --- a/extensions/sticky/src/Listener/SaveStickyToDatabase.php +++ b/extensions/sticky/src/Listener/SaveStickyToDatabase.php @@ -15,10 +15,7 @@ use Flarum\Sticky\Event\DiscussionWasUnstickied; class SaveStickyToDatabase { - /** - * @param Saving $event - */ - public function handle(Saving $event) + public function handle(Saving $event): void { if (isset($event->data['attributes']['isSticky'])) { $isSticky = (bool) $event->data['attributes']['isSticky']; diff --git a/extensions/sticky/src/PinStickiedDiscussionsToTop.php b/extensions/sticky/src/PinStickiedDiscussionsToTop.php index 44e956204..b16eaefa8 100755 --- a/extensions/sticky/src/PinStickiedDiscussionsToTop.php +++ b/extensions/sticky/src/PinStickiedDiscussionsToTop.php @@ -15,7 +15,7 @@ use Flarum\Tags\Query\TagFilterGambit; class PinStickiedDiscussionsToTop { - public function __invoke(FilterState $filterState, QueryCriteria $criteria) + public function __invoke(FilterState $filterState, QueryCriteria $criteria): void { if ($criteria->sortIsDefault) { $query = $filterState->getQuery(); diff --git a/extensions/sticky/src/Post/DiscussionStickiedPost.php b/extensions/sticky/src/Post/DiscussionStickiedPost.php index c6a1c1f0c..7efed3829 100755 --- a/extensions/sticky/src/Post/DiscussionStickiedPost.php +++ b/extensions/sticky/src/Post/DiscussionStickiedPost.php @@ -16,15 +16,9 @@ use Flarum\Post\Post; class DiscussionStickiedPost extends AbstractEventPost implements MergeableInterface { - /** - * {@inheritdoc} - */ - public static $type = 'discussionStickied'; + public static string $type = 'discussionStickied'; - /** - * {@inheritdoc} - */ - public function saveAfter(Post $previous = null) + public function saveAfter(Post $previous = null): static { // If the previous post is another 'discussion stickied' post, and it's // by the same user, then we can merge this post into it. If we find @@ -47,15 +41,7 @@ class DiscussionStickiedPost extends AbstractEventPost implements MergeableInter return $this; } - /** - * Create a new instance in reply to a discussion. - * - * @param int $discussionId - * @param int $userId - * @param bool $isSticky - * @return static - */ - public static function reply($discussionId, $userId, $isSticky) + public static function reply(int $discussionId, int $userId, bool $isSticky): static { $post = new static; @@ -67,14 +53,8 @@ class DiscussionStickiedPost extends AbstractEventPost implements MergeableInter return $post; } - /** - * Build the content attribute. - * - * @param bool $isSticky Whether or not the discussion is stickied. - * @return array - */ - public static function buildContent($isSticky) + public static function buildContent(bool $isSticky): array { - return ['sticky' => (bool) $isSticky]; + return ['sticky' => $isSticky]; } } diff --git a/extensions/sticky/src/Query/StickyFilterGambit.php b/extensions/sticky/src/Query/StickyFilterGambit.php index 5ce083e08..e95ddd050 100644 --- a/extensions/sticky/src/Query/StickyFilterGambit.php +++ b/extensions/sticky/src/Query/StickyFilterGambit.php @@ -17,12 +17,12 @@ use Illuminate\Database\Query\Builder; class StickyFilterGambit extends AbstractRegexGambit implements FilterInterface { - protected function getGambitPattern() + protected function getGambitPattern(): string { return 'is:sticky'; } - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $negate); } @@ -32,12 +32,12 @@ class StickyFilterGambit extends AbstractRegexGambit implements FilterInterface return 'sticky'; } - public function filter(FilterState $filterState, $filterValue, $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $negate); } - protected function constrain(Builder $query, bool $negate) + protected function constrain(Builder $query, bool $negate): void { $query->where('is_sticky', ! $negate); } diff --git a/extensions/subscriptions/src/HideIgnoredFromAllDiscussionsPage.php b/extensions/subscriptions/src/HideIgnoredFromAllDiscussionsPage.php index f4e1d609d..37b38e777 100644 --- a/extensions/subscriptions/src/HideIgnoredFromAllDiscussionsPage.php +++ b/extensions/subscriptions/src/HideIgnoredFromAllDiscussionsPage.php @@ -14,7 +14,7 @@ use Flarum\Query\QueryCriteria; class HideIgnoredFromAllDiscussionsPage { - public function __invoke(FilterState $filterState, QueryCriteria $criteria) + public function __invoke(FilterState $filterState, QueryCriteria $criteria): void { // We only want to hide on the "all discussions" page. if (count($filterState->getActiveFilters()) === 0) { diff --git a/extensions/subscriptions/src/Job/SendReplyNotification.php b/extensions/subscriptions/src/Job/SendReplyNotification.php index 6dc5c776b..a598210d3 100644 --- a/extensions/subscriptions/src/Job/SendReplyNotification.php +++ b/extensions/subscriptions/src/Job/SendReplyNotification.php @@ -11,7 +11,6 @@ namespace Flarum\Subscriptions\Job; use Flarum\Notification\NotificationSyncer; use Flarum\Post\Post; -use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Subscriptions\Notification\NewPostBlueprint; use Flarum\User\User; use Illuminate\Bus\Queueable; @@ -25,27 +24,13 @@ class SendReplyNotification implements ShouldQueue use Queueable; use SerializesModels; - /** - * @var Post - */ - protected $post; - - /** - * @var int - */ - protected $lastPostNumber; - - /** - * @param Post $post - * @param int|null $lastPostNumber - */ - public function __construct(Post $post, $lastPostNumber) - { - $this->post = $post; - $this->lastPostNumber = $lastPostNumber; + public function __construct( + protected Post $post, + protected ?int $lastPostNumber + ) { } - public function handle(NotificationSyncer $notifications, SettingsRepositoryInterface $settings) + public function handle(NotificationSyncer $notifications): void { $post = $this->post; $discussion = $post->discussion; diff --git a/extensions/subscriptions/src/Listener/DeleteNotificationWhenPostIsHiddenOrDeleted.php b/extensions/subscriptions/src/Listener/DeleteNotificationWhenPostIsHiddenOrDeleted.php index 6749e0a58..151102c09 100755 --- a/extensions/subscriptions/src/Listener/DeleteNotificationWhenPostIsHiddenOrDeleted.php +++ b/extensions/subscriptions/src/Listener/DeleteNotificationWhenPostIsHiddenOrDeleted.php @@ -16,23 +16,12 @@ use Flarum\Subscriptions\Notification\NewPostBlueprint; class DeleteNotificationWhenPostIsHiddenOrDeleted { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @param NotificationSyncer $notifications - */ - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - /** - * @param Hidden|Deleted $event - */ - public function handle($event) + public function handle(Deleted|Hidden $event): void { $this->notifications->delete(new NewPostBlueprint($event->post)); } diff --git a/extensions/subscriptions/src/Listener/FollowAfterReply.php b/extensions/subscriptions/src/Listener/FollowAfterReply.php index 14bd52175..a293a5551 100644 --- a/extensions/subscriptions/src/Listener/FollowAfterReply.php +++ b/extensions/subscriptions/src/Listener/FollowAfterReply.php @@ -13,7 +13,7 @@ use Flarum\Post\Event\Posted; class FollowAfterReply { - public function handle(Posted $event) + public function handle(Posted $event): void { $actor = $event->actor; diff --git a/extensions/subscriptions/src/Listener/RestoreNotificationWhenPostIsRestored.php b/extensions/subscriptions/src/Listener/RestoreNotificationWhenPostIsRestored.php index a1fb150ae..e74cbd5a8 100755 --- a/extensions/subscriptions/src/Listener/RestoreNotificationWhenPostIsRestored.php +++ b/extensions/subscriptions/src/Listener/RestoreNotificationWhenPostIsRestored.php @@ -15,20 +15,12 @@ use Flarum\Subscriptions\Notification\NewPostBlueprint; class RestoreNotificationWhenPostIsRestored { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @param NotificationSyncer $notifications - */ - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(Restored $event) + public function handle(Restored $event): void { $this->notifications->restore(new NewPostBlueprint($event->post)); } diff --git a/extensions/subscriptions/src/Listener/SaveSubscriptionToDatabase.php b/extensions/subscriptions/src/Listener/SaveSubscriptionToDatabase.php index 18a53831f..3b348cd13 100755 --- a/extensions/subscriptions/src/Listener/SaveSubscriptionToDatabase.php +++ b/extensions/subscriptions/src/Listener/SaveSubscriptionToDatabase.php @@ -13,7 +13,7 @@ use Flarum\Discussion\Event\Saving; class SaveSubscriptionToDatabase { - public function handle(Saving $event) + public function handle(Saving $event): void { $discussion = $event->discussion; $data = $event->data; diff --git a/extensions/subscriptions/src/Listener/SendNotificationWhenReplyIsPosted.php b/extensions/subscriptions/src/Listener/SendNotificationWhenReplyIsPosted.php index ec3af606b..7bf264140 100755 --- a/extensions/subscriptions/src/Listener/SendNotificationWhenReplyIsPosted.php +++ b/extensions/subscriptions/src/Listener/SendNotificationWhenReplyIsPosted.php @@ -16,21 +16,12 @@ use Illuminate\Contracts\Queue\Queue; class SendNotificationWhenReplyIsPosted { - /** - * @var Queue - */ - protected $queue; - - public function __construct(Queue $queue) - { - $this->queue = $queue; + public function __construct( + protected Queue $queue + ) { } - /** - * @param Posted|PostWasApproved $event - * @return void - */ - public function handle($event) + public function handle(Posted|PostWasApproved $event): void { $this->queue->push( new SendReplyNotification($event->post, $event->post->discussion->last_post_number) diff --git a/extensions/subscriptions/src/Notification/NewPostBlueprint.php b/extensions/subscriptions/src/Notification/NewPostBlueprint.php index 36f27f555..58664bc42 100644 --- a/extensions/subscriptions/src/Notification/NewPostBlueprint.php +++ b/extensions/subscriptions/src/Notification/NewPostBlueprint.php @@ -9,79 +9,52 @@ namespace Flarum\Subscriptions\Notification; +use Flarum\Database\AbstractModel; use Flarum\Discussion\Discussion; +use Flarum\Locale\TranslatorInterface; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\MailableInterface; use Flarum\Post\Post; -use Symfony\Contracts\Translation\TranslatorInterface; +use Flarum\User\User; class NewPostBlueprint implements BlueprintInterface, MailableInterface { - /** - * @var Post - */ - public $post; - - /** - * @param Post $post - */ - public function __construct(Post $post) - { - $this->post = $post; + public function __construct( + public Post $post + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post->discussion; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->post->user; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): array { return ['postNumber' => (int) $this->post->number]; } - /** - * {@inheritdoc} - */ - public function getEmailView() + public function getEmailView(): string|array { return ['text' => 'flarum-subscriptions::emails.newPost']; } - /** - * {@inheritdoc} - */ - public function getEmailSubject(TranslatorInterface $translator) + public function getEmailSubject(TranslatorInterface $translator): string { return $translator->trans('flarum-subscriptions.email.new_post.subject', ['{title}' => $this->post->discussion->title]); } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'newPost'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Discussion::class; } diff --git a/extensions/subscriptions/src/Query/SubscriptionFilterGambit.php b/extensions/subscriptions/src/Query/SubscriptionFilterGambit.php index b94ddfc5c..fc3814c08 100644 --- a/extensions/subscriptions/src/Query/SubscriptionFilterGambit.php +++ b/extensions/subscriptions/src/Query/SubscriptionFilterGambit.php @@ -21,12 +21,12 @@ class SubscriptionFilterGambit extends AbstractRegexGambit implements FilterInte { use ValidateFilterTrait; - protected function getGambitPattern() + protected function getGambitPattern(): string { return 'is:(follow|ignor)(?:ing|ed)'; } - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $search->getActor(), $matches[1], $negate); } @@ -36,7 +36,7 @@ class SubscriptionFilterGambit extends AbstractRegexGambit implements FilterInte return 'subscription'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $filterValue = $this->asString($filterValue); @@ -45,7 +45,7 @@ class SubscriptionFilterGambit extends AbstractRegexGambit implements FilterInte $this->constrain($filterState->getQuery(), $filterState->getActor(), $matches[1], $negate); } - protected function constrain(Builder $query, User $actor, string $subscriptionType, bool $negate) + protected function constrain(Builder $query, User $actor, string $subscriptionType, bool $negate): void { $method = $negate ? 'whereNotIn' : 'whereIn'; $query->$method('discussions.id', function ($query) use ($actor, $subscriptionType) { diff --git a/extensions/suspend/src/Access/UserPolicy.php b/extensions/suspend/src/Access/UserPolicy.php index 69823772c..5b6299d97 100644 --- a/extensions/suspend/src/Access/UserPolicy.php +++ b/extensions/suspend/src/Access/UserPolicy.php @@ -14,11 +14,6 @@ use Flarum\User\User; class UserPolicy extends AbstractPolicy { - /** - * @param User $actor - * @param User $user - * @return bool|null - */ public function suspend(User $actor, User $user) { if ($user->isAdmin() || $user->id === $actor->id) { diff --git a/extensions/suspend/src/AddUserSuspendAttributes.php b/extensions/suspend/src/AddUserSuspendAttributes.php index e2411469f..44d63a5cb 100755 --- a/extensions/suspend/src/AddUserSuspendAttributes.php +++ b/extensions/suspend/src/AddUserSuspendAttributes.php @@ -14,7 +14,7 @@ use Flarum\User\User; class AddUserSuspendAttributes { - public function __invoke(UserSerializer $serializer, User $user) + public function __invoke(UserSerializer $serializer, User $user): array { $attributes = []; $canSuspend = $serializer->getActor()->can('suspend', $user); diff --git a/extensions/suspend/src/Event/Suspended.php b/extensions/suspend/src/Event/Suspended.php index 5fee7ee62..dfedb6d8c 100644 --- a/extensions/suspend/src/Event/Suspended.php +++ b/extensions/suspend/src/Event/Suspended.php @@ -13,18 +13,9 @@ use Flarum\User\User; class Suspended { - /** - * @var User - */ - public $user; - /** - * @var User - */ - public $actor; - - public function __construct(User $user, User $actor) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public User $actor + ) { } } diff --git a/extensions/suspend/src/Event/Unsuspended.php b/extensions/suspend/src/Event/Unsuspended.php index 792fd5f5d..b930e938e 100644 --- a/extensions/suspend/src/Event/Unsuspended.php +++ b/extensions/suspend/src/Event/Unsuspended.php @@ -13,18 +13,9 @@ use Flarum\User\User; class Unsuspended { - /** - * @var User - */ - public $user; - /** - * @var User - */ - public $actor; - - public function __construct(User $user, User $actor) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public User $actor + ) { } } diff --git a/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php b/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php index a516398d9..34e40e7ac 100755 --- a/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php +++ b/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php @@ -20,29 +20,13 @@ use Illuminate\Support\Arr; class SaveSuspensionToDatabase { - /** - * Validator for limited suspension. - * - * @var SuspendValidator - */ - protected $validator; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param SuspendValidator $validator - * @param Dispatcher $events - */ - public function __construct(SuspendValidator $validator, Dispatcher $events) - { - $this->validator = $validator; - $this->events = $events; + public function __construct( + protected SuspendValidator $validator, + protected Dispatcher $events + ) { } - public function handle(Saving $event) + public function handle(Saving $event): void { $attributes = Arr::get($event->data, 'attributes', []); diff --git a/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php b/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php index 1db55549c..cc1c44000 100644 --- a/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php +++ b/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php @@ -15,20 +15,12 @@ use Flarum\Suspend\Notification\UserSuspendedBlueprint; class SendNotificationWhenUserIsSuspended { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @param NotificationSyncer $notifications - */ - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(Suspended $event) + public function handle(Suspended $event): void { $this->notifications->sync( new UserSuspendedBlueprint($event->user), diff --git a/extensions/suspend/src/Listener/SendNotificationWhenUserIsUnsuspended.php b/extensions/suspend/src/Listener/SendNotificationWhenUserIsUnsuspended.php index 2b89a08ea..02928ac93 100644 --- a/extensions/suspend/src/Listener/SendNotificationWhenUserIsUnsuspended.php +++ b/extensions/suspend/src/Listener/SendNotificationWhenUserIsUnsuspended.php @@ -15,20 +15,12 @@ use Flarum\Suspend\Notification\UserUnsuspendedBlueprint; class SendNotificationWhenUserIsUnsuspended { - /** - * @var NotificationSyncer - */ - protected $notifications; - - /** - * @param NotificationSyncer $notifications - */ - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(Unsuspended $event) + public function handle(Unsuspended $event): void { $this->notifications->sync( new UserUnsuspendedBlueprint($event->user), diff --git a/extensions/suspend/src/Notification/UserSuspendedBlueprint.php b/extensions/suspend/src/Notification/UserSuspendedBlueprint.php index 5c3e729c8..53b1f3807 100644 --- a/extensions/suspend/src/Notification/UserSuspendedBlueprint.php +++ b/extensions/suspend/src/Notification/UserSuspendedBlueprint.php @@ -9,78 +9,51 @@ namespace Flarum\Suspend\Notification; +use Carbon\CarbonInterface; +use Flarum\Database\AbstractModel; +use Flarum\Locale\TranslatorInterface; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\MailableInterface; use Flarum\User\User; -use Symfony\Contracts\Translation\TranslatorInterface; class UserSuspendedBlueprint implements BlueprintInterface, MailableInterface { - /** - * @var User - */ - public $user; - - /** - * @param User $user - */ - public function __construct(User $user) - { - $this->user = $user; + public function __construct( + public User $user + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->user; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return null; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): CarbonInterface { return $this->user->suspended_until; } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'userSuspended'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return User::class; } - /** - * {@inheritdoc} - */ - public function getEmailView() + public function getEmailView(): string|array { return ['text' => 'flarum-suspend::emails.suspended']; } - /** - * {@inheritdoc} - */ - public function getEmailSubject(TranslatorInterface $translator) + public function getEmailSubject(TranslatorInterface $translator): string { return $translator->trans('flarum-suspend.email.suspended.subject'); } diff --git a/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php b/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php index 85fa01c32..8660b12d3 100644 --- a/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php +++ b/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php @@ -9,79 +9,52 @@ namespace Flarum\Suspend\Notification; +use Carbon\CarbonInterface; +use Flarum\Database\AbstractModel; +use Flarum\Locale\TranslatorInterface; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\MailableInterface; use Flarum\User\User; use Illuminate\Support\Carbon; -use Symfony\Contracts\Translation\TranslatorInterface; class UserUnsuspendedBlueprint implements BlueprintInterface, MailableInterface { - /** - * @var User - */ - public $user; - - /** - * @param User $user - */ - public function __construct(User $user) - { - $this->user = $user; + public function __construct( + public User $user + ) { } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->user; } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return null; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): CarbonInterface { return Carbon::now(); } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'userUnsuspended'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return User::class; } - /** - * {@inheritdoc} - */ - public function getEmailView() + public function getEmailView(): string|array { return ['text' => 'flarum-suspend::emails.unsuspended']; } - /** - * {@inheritdoc} - */ - public function getEmailSubject(TranslatorInterface $translator) + public function getEmailSubject(TranslatorInterface $translator): string { return $translator->trans('flarum-suspend.email.unsuspended.subject'); } diff --git a/extensions/suspend/src/Query/SuspendedFilterGambit.php b/extensions/suspend/src/Query/SuspendedFilterGambit.php index ae33ded2d..24b192c4d 100644 --- a/extensions/suspend/src/Query/SuspendedFilterGambit.php +++ b/extensions/suspend/src/Query/SuspendedFilterGambit.php @@ -20,28 +20,17 @@ use Illuminate\Database\Query\Builder; class SuspendedFilterGambit extends AbstractRegexGambit implements FilterInterface { - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @param \Flarum\User\UserRepository $users - */ - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } - protected function getGambitPattern() + protected function getGambitPattern(): string { return 'is:suspended'; } - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $bit) + public function apply(SearchState $search, string $bit): bool { if (! $search->getActor()->can('suspend', new Guest())) { return false; @@ -50,10 +39,7 @@ class SuspendedFilterGambit extends AbstractRegexGambit implements FilterInterfa return parent::apply($search, $bit); } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $negate); } @@ -63,16 +49,16 @@ class SuspendedFilterGambit extends AbstractRegexGambit implements FilterInterfa return 'suspended'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { if (! $filterState->getActor()->can('suspend', new Guest())) { - return false; + return; } $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) { if ($negate) { diff --git a/extensions/suspend/src/RevokeAccessFromSuspendedUsers.php b/extensions/suspend/src/RevokeAccessFromSuspendedUsers.php index d6a7b3f47..40e8d7b7e 100644 --- a/extensions/suspend/src/RevokeAccessFromSuspendedUsers.php +++ b/extensions/suspend/src/RevokeAccessFromSuspendedUsers.php @@ -15,11 +15,7 @@ use Flarum\User\User; class RevokeAccessFromSuspendedUsers { - /** - * @param User $user - * @param array $groupIds - */ - public function __invoke(User $user, array $groupIds) + public function __invoke(User $user, array $groupIds): array { $suspendedUntil = $user->suspended_until; diff --git a/extensions/suspend/src/SuspendValidator.php b/extensions/suspend/src/SuspendValidator.php index 7b2805965..db91666ea 100644 --- a/extensions/suspend/src/SuspendValidator.php +++ b/extensions/suspend/src/SuspendValidator.php @@ -13,10 +13,7 @@ use Flarum\Foundation\AbstractValidator; class SuspendValidator extends AbstractValidator { - /** - * {@inheritdoc} - */ - protected $rules = [ + protected array $rules = [ 'suspendedUntil' => ['nullable', 'date'], ]; } diff --git a/extensions/tags/extend.php b/extensions/tags/extend.php index 4ca124e5b..823360525 100644 --- a/extensions/tags/extend.php +++ b/extensions/tags/extend.php @@ -35,6 +35,8 @@ use Flarum\Tags\Search\Gambit\FulltextGambit; use Flarum\Tags\Search\TagSearcher; use Flarum\Tags\Tag; use Flarum\Tags\Utf8SlugDriver; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; use Psr\Http\Message\ServerRequestInterface; $eagerLoadTagState = function ($query, ?ServerRequestInterface $request, array $relations) { @@ -171,7 +173,7 @@ return [ (new Extend\ApiController(FlarumController\ListPostsController::class)) ->addInclude('eventPostMentionsTags') // Restricted tags should still appear as `deleted` to unauthorized users. - ->loadWhere('eventPostMentionsTags', function ($query, ?ServerRequestInterface $request) { + ->loadWhere('eventPostMentionsTags', function (Relation|Builder $query, ?ServerRequestInterface $request) { if ($request) { $actor = RequestUtil::getActor($request); $query->whereVisibleTo($actor); diff --git a/extensions/tags/src/Access/DiscussionPolicy.php b/extensions/tags/src/Access/DiscussionPolicy.php index a4cfccc64..a84897b77 100755 --- a/extensions/tags/src/Access/DiscussionPolicy.php +++ b/extensions/tags/src/Access/DiscussionPolicy.php @@ -17,26 +17,12 @@ use Flarum\User\User; class DiscussionPolicy extends AbstractPolicy { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @param SettingsRepositoryInterface $settings - */ - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param User $actor - * @param string $ability - * @param Discussion $discussion - * @return string|void - */ - public function can(User $actor, $ability, Discussion $discussion) + public function can(User $actor, string $ability, Discussion $discussion) { // Wrap all discussion permission checks with some logic pertaining to // the discussion's tags. If the discussion has a tag that has been @@ -65,10 +51,6 @@ class DiscussionPolicy extends AbstractPolicy /** * This method checks, if the user is still allowed to edit the tags * based on the configuration item. - * - * @param User $actor - * @param Discussion $discussion - * @return string|void */ public function tag(User $actor, Discussion $discussion) { diff --git a/extensions/tags/src/Access/GlobalPolicy.php b/extensions/tags/src/Access/GlobalPolicy.php index feb05432a..7218d1778 100644 --- a/extensions/tags/src/Access/GlobalPolicy.php +++ b/extensions/tags/src/Access/GlobalPolicy.php @@ -16,21 +16,11 @@ use Flarum\User\User; class GlobalPolicy extends AbstractPolicy { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param User $actor - * @param string $ability - * @return string|void - */ public function can(User $actor, string $ability) { static $enoughPrimary; diff --git a/extensions/tags/src/Access/ScopeDiscussionVisibilityForAbility.php b/extensions/tags/src/Access/ScopeDiscussionVisibilityForAbility.php index 57a7b15a9..2846c19a9 100644 --- a/extensions/tags/src/Access/ScopeDiscussionVisibilityForAbility.php +++ b/extensions/tags/src/Access/ScopeDiscussionVisibilityForAbility.php @@ -16,12 +16,7 @@ use Illuminate\Support\Str; class ScopeDiscussionVisibilityForAbility { - /** - * @param User $actor - * @param Builder $query - * @param string $ability - */ - public function __invoke(User $actor, Builder $query, $ability) + public function __invoke(User $actor, Builder $query, string $ability): void { // Automatic scoping should be applied to the global `view` ability, // and to arbitrary abilities that aren't subqueries of `view`. @@ -29,7 +24,7 @@ class ScopeDiscussionVisibilityForAbility // edit posts, this should apply. // But if we are expanding a restriction of `view` (for example, // `viewPrivate`), we shouldn't apply this query again. - if (substr($ability, 0, 4) === 'view' && $ability !== 'view') { + if (Str::startsWith($ability, 'view') && $ability !== 'view') { return; } diff --git a/extensions/tags/src/Access/ScopeTagVisibility.php b/extensions/tags/src/Access/ScopeTagVisibility.php index 779ac68bb..3ca1bc5cb 100644 --- a/extensions/tags/src/Access/ScopeTagVisibility.php +++ b/extensions/tags/src/Access/ScopeTagVisibility.php @@ -15,11 +15,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopeTagVisibility { - /** - * @param User $actor - * @param Builder $query - */ - public function __invoke(User $actor, Builder $query) + public function __invoke(User $actor, Builder $query): void { $query->whereIn('id', function ($query) use ($actor) { Tag::query()->setQuery($query->from('tags'))->whereHasPermission($actor, 'viewForum')->select('tags.id'); diff --git a/extensions/tags/src/Access/TagPolicy.php b/extensions/tags/src/Access/TagPolicy.php index 25b74c6c3..b8977b16b 100755 --- a/extensions/tags/src/Access/TagPolicy.php +++ b/extensions/tags/src/Access/TagPolicy.php @@ -28,7 +28,7 @@ class TagPolicy extends AbstractPolicy } } - public function addToDiscussion(User $actor, Tag $tag) + public function addToDiscussion(User $actor, Tag $tag): bool { return $actor->can('startDiscussion', $tag); } diff --git a/extensions/tags/src/Api/Controller/CreateTagController.php b/extensions/tags/src/Api/Controller/CreateTagController.php index 7c5c75417..7a5fcd6f7 100644 --- a/extensions/tags/src/Api/Controller/CreateTagController.php +++ b/extensions/tags/src/Api/Controller/CreateTagController.php @@ -13,6 +13,7 @@ use Flarum\Api\Controller\AbstractCreateController; use Flarum\Http\RequestUtil; use Flarum\Tags\Api\Serializer\TagSerializer; use Flarum\Tags\Command\CreateTag; +use Flarum\Tags\Tag; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -20,33 +21,16 @@ use Tobscure\JsonApi\Document; class CreateTagController extends AbstractCreateController { - /** - * {@inheritdoc} - */ - public $serializer = TagSerializer::class; + public ?string $serializer = TagSerializer::class; - /** - * {@inheritdoc} - */ - public $include = ['parent']; + public array $include = ['parent']; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Tag { return $this->bus->dispatch( new CreateTag(RequestUtil::getActor($request), Arr::get($request->getParsedBody(), 'data', [])) diff --git a/extensions/tags/src/Api/Controller/DeleteTagController.php b/extensions/tags/src/Api/Controller/DeleteTagController.php index 910a6a8ec..db75abeb8 100644 --- a/extensions/tags/src/Api/Controller/DeleteTagController.php +++ b/extensions/tags/src/Api/Controller/DeleteTagController.php @@ -18,23 +18,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeleteTagController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new DeleteTag(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request)) diff --git a/extensions/tags/src/Api/Controller/ListTagsController.php b/extensions/tags/src/Api/Controller/ListTagsController.php index d78b5339e..85400f3c5 100644 --- a/extensions/tags/src/Api/Controller/ListTagsController.php +++ b/extensions/tags/src/Api/Controller/ListTagsController.php @@ -21,53 +21,26 @@ use Tobscure\JsonApi\Document; class ListTagsController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = TagSerializer::class; + public ?string $serializer = TagSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'parent' ]; - /** - * {@inheritdoc} - */ - public $optionalInclude = [ + public array $optionalInclude = [ 'children', 'lastPostedDiscussion', 'state' ]; - /** - * @var TagRepository - */ - protected $tags; - - /** - * @var TagSearcher - */ - protected $searcher; - - /** - * @var UrlGenerator - */ - protected $url; - - public function __construct(TagRepository $tags, TagSearcher $searcher, UrlGenerator $url) - { - $this->tags = $tags; - $this->searcher = $searcher; - $this->url = $url; + public function __construct( + protected TagRepository $tags, + protected TagSearcher $searcher, + protected UrlGenerator $url + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); $include = $this->extractInclude($request); diff --git a/extensions/tags/src/Api/Controller/OrderTagsController.php b/extensions/tags/src/Api/Controller/OrderTagsController.php index 41b0e2f44..9cb4e125e 100644 --- a/extensions/tags/src/Api/Controller/OrderTagsController.php +++ b/extensions/tags/src/Api/Controller/OrderTagsController.php @@ -19,9 +19,6 @@ use Psr\Http\Server\RequestHandlerInterface; class OrderTagsController implements RequestHandlerInterface { - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { RequestUtil::getActor($request)->assertAdmin(); diff --git a/extensions/tags/src/Api/Controller/ShowTagController.php b/extensions/tags/src/Api/Controller/ShowTagController.php index dd8ae3824..ae34d51de 100644 --- a/extensions/tags/src/Api/Controller/ShowTagController.php +++ b/extensions/tags/src/Api/Controller/ShowTagController.php @@ -21,9 +21,9 @@ use Tobscure\JsonApi\Document; class ShowTagController extends AbstractShowController { - public $serializer = TagSerializer::class; + public ?string $serializer = TagSerializer::class; - public $optionalInclude = [ + public array $optionalInclude = [ 'children', 'children.parent', 'lastPostedDiscussion', @@ -33,26 +33,13 @@ class ShowTagController extends AbstractShowController 'state' ]; - /** - * @var TagRepository - */ - protected $tags; - - /** - * @var SlugManager - */ - protected $slugger; - - public function __construct(TagRepository $tags, SlugManager $slugger) - { - $this->tags = $tags; - $this->slugger = $slugger; + public function __construct( + protected TagRepository $tags, + protected SlugManager $slugger + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Tag { $slug = Arr::get($request->getQueryParams(), 'slug'); $actor = RequestUtil::getActor($request); diff --git a/extensions/tags/src/Api/Controller/UpdateTagController.php b/extensions/tags/src/Api/Controller/UpdateTagController.php index b5ac3549a..2f5776446 100644 --- a/extensions/tags/src/Api/Controller/UpdateTagController.php +++ b/extensions/tags/src/Api/Controller/UpdateTagController.php @@ -13,6 +13,7 @@ use Flarum\Api\Controller\AbstractShowController; use Flarum\Http\RequestUtil; use Flarum\Tags\Api\Serializer\TagSerializer; use Flarum\Tags\Command\EditTag; +use Flarum\Tags\Tag; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -20,28 +21,14 @@ use Tobscure\JsonApi\Document; class UpdateTagController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = TagSerializer::class; + public ?string $serializer = TagSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Tag { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/extensions/tags/src/Api/Serializer/TagSerializer.php b/extensions/tags/src/Api/Serializer/TagSerializer.php index a989061cb..deac6768e 100644 --- a/extensions/tags/src/Api/Serializer/TagSerializer.php +++ b/extensions/tags/src/Api/Serializer/TagSerializer.php @@ -14,80 +14,61 @@ use Flarum\Api\Serializer\DiscussionSerializer; use Flarum\Http\SlugManager; use Flarum\Tags\Tag; use InvalidArgumentException; +use Tobscure\JsonApi\Relationship; class TagSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'tags'; - /** - * @var SlugManager - */ - protected $slugManager; - - public function __construct(SlugManager $slugManager) - { - $this->slugManager = $slugManager; + public function __construct( + protected SlugManager $slugManager + ) { } - /** - * Get the default set of serialized attributes for a model. - * - * @param Tag $tag - * @return array - */ - protected function getDefaultAttributes($tag) + protected function getDefaultAttributes(object|array $model): array { - if (! ($tag instanceof Tag)) { + if (! ($model instanceof Tag)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.Tag::class ); } $attributes = [ - 'name' => $tag->name, - 'description' => $tag->description, - 'slug' => $this->slugManager->forResource(Tag::class)->toSlug($tag), - 'color' => $tag->color, - 'backgroundUrl' => $tag->background_path, - 'backgroundMode' => $tag->background_mode, - 'icon' => $tag->icon, - 'discussionCount' => (int) $tag->discussion_count, - 'position' => $tag->position === null ? null : (int) $tag->position, - 'defaultSort' => $tag->default_sort, - 'isChild' => (bool) $tag->parent_id, - 'isHidden' => (bool) $tag->is_hidden, - 'lastPostedAt' => $this->formatDate($tag->last_posted_at), - 'canStartDiscussion' => $this->actor->can('startDiscussion', $tag), - 'canAddToDiscussion' => $this->actor->can('addToDiscussion', $tag) + 'name' => $model->name, + 'description' => $model->description, + 'slug' => $this->slugManager->forResource(Tag::class)->toSlug($model), + 'color' => $model->color, + 'backgroundUrl' => $model->background_path, + 'backgroundMode' => $model->background_mode, + 'icon' => $model->icon, + 'discussionCount' => (int) $model->discussion_count, + 'position' => $model->position === null ? null : (int) $model->position, + 'defaultSort' => $model->default_sort, + 'isChild' => (bool) $model->parent_id, + 'isHidden' => (bool) $model->is_hidden, + 'lastPostedAt' => $this->formatDate($model->last_posted_at), + 'canStartDiscussion' => $this->actor->can('startDiscussion', $model), + 'canAddToDiscussion' => $this->actor->can('addToDiscussion', $model) ]; if ($this->actor->isAdmin()) { - $attributes['isRestricted'] = (bool) $tag->is_restricted; + $attributes['isRestricted'] = (bool) $model->is_restricted; } return $attributes; } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function parent($tag) + protected function parent(Tag $tag): ?Relationship { return $this->hasOne($tag, self::class); } - protected function children($tag) + protected function children(Tag $tag): ?Relationship { return $this->hasMany($tag, self::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function lastPostedDiscussion($tag) + protected function lastPostedDiscussion(Tag $tag): ?Relationship { return $this->hasOne($tag, DiscussionSerializer::class); } diff --git a/extensions/tags/src/Command/CreateTag.php b/extensions/tags/src/Command/CreateTag.php index 7254d83b8..2d3d4c99d 100644 --- a/extensions/tags/src/Command/CreateTag.php +++ b/extensions/tags/src/Command/CreateTag.php @@ -13,27 +13,9 @@ use Flarum\User\User; class CreateTag { - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes of the new tag. - * - * @var array - */ - public $data; - - /** - * @param User $actor The user performing the action. - * @param array $data The attributes of the new tag. - */ - public function __construct(User $actor, array $data) - { - $this->actor = $actor; - $this->data = $data; + public function __construct( + public User $actor, + public array $data + ) { } } diff --git a/extensions/tags/src/Command/CreateTagHandler.php b/extensions/tags/src/Command/CreateTagHandler.php index 3409a562d..f51cd46f7 100644 --- a/extensions/tags/src/Command/CreateTagHandler.php +++ b/extensions/tags/src/Command/CreateTagHandler.php @@ -17,31 +17,13 @@ use Illuminate\Support\Arr; class CreateTagHandler { - /** - * @var TagValidator - */ - protected $validator; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param TagValidator $validator - * @param Dispatcher $events - */ - public function __construct(TagValidator $validator, Dispatcher $events) - { - $this->validator = $validator; - $this->events = $events; + public function __construct( + protected TagValidator $validator, + protected Dispatcher $events + ) { } - /** - * @param CreateTag $command - * @return Tag - */ - public function handle(CreateTag $command) + public function handle(CreateTag $command): Tag { $actor = $command->actor; $data = $command->data; diff --git a/extensions/tags/src/Command/DeleteTag.php b/extensions/tags/src/Command/DeleteTag.php index 447166bf2..48d239088 100644 --- a/extensions/tags/src/Command/DeleteTag.php +++ b/extensions/tags/src/Command/DeleteTag.php @@ -13,38 +13,10 @@ use Flarum\User\User; class DeleteTag { - /** - * The ID of the tag to delete. - * - * @var int - */ - public $tagId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * Any other tag input associated with the action. This is unused by - * default, but may be used by extensions. - * - * @var array - */ - public $data; - - /** - * @param int $tagId The ID of the tag to delete. - * @param User $actor The user performing the action. - * @param array $data Any other tag input associated with the action. This - * is unused by default, but may be used by extensions. - */ - public function __construct($tagId, User $actor, array $data = []) - { - $this->tagId = $tagId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $tagId, + public User $actor, + public array $data = [] + ) { } } diff --git a/extensions/tags/src/Command/DeleteTagHandler.php b/extensions/tags/src/Command/DeleteTagHandler.php index d2c20267b..dd8b01297 100644 --- a/extensions/tags/src/Command/DeleteTagHandler.php +++ b/extensions/tags/src/Command/DeleteTagHandler.php @@ -10,37 +10,19 @@ namespace Flarum\Tags\Command; use Flarum\Tags\Event\Deleting; +use Flarum\Tags\Tag; use Flarum\Tags\TagRepository; use Illuminate\Contracts\Events\Dispatcher; class DeleteTagHandler { - /** - * @var TagRepository - */ - protected $tags; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param TagRepository $tags - * @param Dispatcher $events - */ - public function __construct(TagRepository $tags, Dispatcher $events) - { - $this->tags = $tags; - $this->events = $events; + public function __construct( + protected TagRepository $tags, + protected Dispatcher $events + ) { } - /** - * @param DeleteTag $command - * @return \Flarum\Tags\Tag - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(DeleteTag $command) + public function handle(DeleteTag $command): Tag { $actor = $command->actor; diff --git a/extensions/tags/src/Command/EditTag.php b/extensions/tags/src/Command/EditTag.php index 4615274e6..a52d43586 100644 --- a/extensions/tags/src/Command/EditTag.php +++ b/extensions/tags/src/Command/EditTag.php @@ -13,36 +13,10 @@ use Flarum\User\User; class EditTag { - /** - * The ID of the tag to edit. - * - * @var int - */ - public $tagId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the tag. - * - * @var array - */ - public $data; - - /** - * @param int $tagId The ID of the tag to edit. - * @param User $actor The user performing the action. - * @param array $data The attributes to update on the tag. - */ - public function __construct($tagId, User $actor, array $data) - { - $this->tagId = $tagId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $tagId, + public User $actor, + public array $data + ) { } } diff --git a/extensions/tags/src/Command/EditTagHandler.php b/extensions/tags/src/Command/EditTagHandler.php index f13a4534b..6628d44e8 100644 --- a/extensions/tags/src/Command/EditTagHandler.php +++ b/extensions/tags/src/Command/EditTagHandler.php @@ -10,6 +10,7 @@ namespace Flarum\Tags\Command; use Flarum\Tags\Event\Saving; +use Flarum\Tags\Tag; use Flarum\Tags\TagRepository; use Flarum\Tags\TagValidator; use Illuminate\Contracts\Events\Dispatcher; @@ -17,39 +18,14 @@ use Illuminate\Support\Arr; class EditTagHandler { - /** - * @var TagRepository - */ - protected $tags; - - /** - * @var TagValidator - */ - protected $validator; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param TagRepository $tags - * @param TagValidator $validator - * @param Dispatcher $events - */ - public function __construct(TagRepository $tags, TagValidator $validator, Dispatcher $events) - { - $this->tags = $tags; - $this->validator = $validator; - $this->events = $events; + public function __construct( + protected TagRepository $tags, + protected TagValidator $validator, + protected Dispatcher $events + ) { } - /** - * @param EditTag $command - * @return \Flarum\Tags\Tag - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(EditTag $command) + public function handle(EditTag $command): Tag { $actor = $command->actor; $data = $command->data; diff --git a/extensions/tags/src/Content/Tag.php b/extensions/tags/src/Content/Tag.php index ab204c2cf..33b1855a6 100644 --- a/extensions/tags/src/Content/Tag.php +++ b/extensions/tags/src/Content/Tag.php @@ -13,55 +13,25 @@ use Flarum\Api\Client; use Flarum\Frontend\Document; use Flarum\Http\RequestUtil; use Flarum\Http\SlugManager; +use Flarum\Locale\TranslatorInterface; use Flarum\Tags\Tag as TagModel; use Flarum\Tags\TagRepository; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface as Request; -use Symfony\Contracts\Translation\TranslatorInterface; class Tag { - /** - * @var Client - */ - protected $api; - - /** - * @var Factory - */ - protected $view; - - /** - * @var TagRepository - */ - protected $tags; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var SlugManager - */ - protected $slugger; - public function __construct( - Client $api, - Factory $view, - TagRepository $tags, - TranslatorInterface $translator, - SlugManager $slugger + protected Client $api, + protected Factory $view, + protected TagRepository $tags, + protected TranslatorInterface $translator, + protected SlugManager $slugger ) { - $this->api = $api; - $this->view = $view; - $this->tags = $tags; - $this->translator = $translator; - $this->slugger = $slugger; } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): Document { $queryParams = $request->getQueryParams(); $actor = RequestUtil::getActor($request); @@ -110,10 +80,8 @@ class Tag /** * Get a map of sort query param values and their API sort params. - * - * @return array */ - protected function getSortMap() + protected function getSortMap(): array { return resolve('flarum.forum.discussions.sortmap'); } diff --git a/extensions/tags/src/Content/Tags.php b/extensions/tags/src/Content/Tags.php index 0f919e25d..993f21b7b 100644 --- a/extensions/tags/src/Content/Tags.php +++ b/extensions/tags/src/Content/Tags.php @@ -12,70 +12,26 @@ namespace Flarum\Tags\Content; use Flarum\Api\Client; use Flarum\Frontend\Document; use Flarum\Http\UrlGenerator; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Tags\TagRepository; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface as Request; -use Symfony\Contracts\Translation\TranslatorInterface; class Tags { - /** - * @var Client - */ - protected $api; - - /** - * @var Factory - */ - protected $view; - - /** - * @var TagRepository - */ - protected $tags; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param Client $api - * @param Factory $view - * @param TagRepository $tags - * @param TranslatorInterface $translator - * @param SettingsRepositoryInterface $settings - * @param UrlGenerator $url - */ public function __construct( - Client $api, - Factory $view, - TagRepository $tags, - TranslatorInterface $translator, - SettingsRepositoryInterface $settings, - UrlGenerator $url + protected Client $api, + protected Factory $view, + protected TagRepository $tags, + protected TranslatorInterface $translator, + protected SettingsRepositoryInterface $settings, + protected UrlGenerator $url ) { - $this->api = $api; - $this->view = $view; - $this->tags = $tags; - $this->settings = $settings; - $this->translator = $translator; - $this->url = $url; } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): Document { $apiDocument = $this->getTagsDocument($request); $tags = collect(Arr::get($apiDocument, 'data', [])); diff --git a/extensions/tags/src/Event/Creating.php b/extensions/tags/src/Event/Creating.php index 037307a52..c749a7d76 100644 --- a/extensions/tags/src/Event/Creating.php +++ b/extensions/tags/src/Event/Creating.php @@ -14,30 +14,10 @@ use Flarum\User\User; class Creating { - /** - * @var Tag - */ - public $tag; - - /** - * @var User - */ - public $actor; - - /** - * @var array - */ - public $data; - - /** - * @param Tag $tag - * @param User $actor - * @param array $data - */ - public function __construct(Tag $tag, User $actor, array $data) - { - $this->tag = $tag; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Tag $tag, + public User $actor, + public array $data + ) { } } diff --git a/extensions/tags/src/Event/Deleting.php b/extensions/tags/src/Event/Deleting.php index 79627552a..75a5cd868 100644 --- a/extensions/tags/src/Event/Deleting.php +++ b/extensions/tags/src/Event/Deleting.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Deleting { - /** - * @var Tag - */ - public $tag; - - /** - * @var User - */ - public $actor; - - /** - * @param Tag $tag - * @param User $actor - */ - public function __construct(Tag $tag, User $actor) - { - $this->tag = $tag; - $this->actor = $actor; + public function __construct( + public Tag $tag, + public User $actor + ) { } } diff --git a/extensions/tags/src/Event/DiscussionWasTagged.php b/extensions/tags/src/Event/DiscussionWasTagged.php index de1e047bb..752772832 100644 --- a/extensions/tags/src/Event/DiscussionWasTagged.php +++ b/extensions/tags/src/Event/DiscussionWasTagged.php @@ -10,34 +10,16 @@ namespace Flarum\Tags\Event; use Flarum\Discussion\Discussion; +use Flarum\Tags\Tag; use Flarum\User\User; class DiscussionWasTagged { - /** - * @var Discussion - */ - public $discussion; - - /** - * @var User - */ - public $actor; - - /** - * @var array - */ - public $oldTags; - - /** - * @param Discussion $discussion - * @param User $actor - * @param \Flarum\Tags\Tag[] $oldTags - */ - public function __construct(Discussion $discussion, User $actor, array $oldTags) - { - $this->discussion = $discussion; - $this->actor = $actor; - $this->oldTags = $oldTags; + public function __construct( + public Discussion $discussion, + public User $actor, + /** @var Tag[] */ + public array $oldTags + ) { } } diff --git a/extensions/tags/src/Event/Saving.php b/extensions/tags/src/Event/Saving.php index f9f045b2e..59e477ffa 100644 --- a/extensions/tags/src/Event/Saving.php +++ b/extensions/tags/src/Event/Saving.php @@ -14,30 +14,10 @@ use Flarum\User\User; class Saving { - /** - * @var Tag - */ - public $tag; - - /** - * @var User - */ - public $actor; - - /** - * @var array - */ - public $data; - - /** - * @param Tag $tag - * @param User $actor - * @param array $data - */ - public function __construct(Tag $tag, User $actor, array $data) - { - $this->tag = $tag; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Tag $tag, + public User $actor, + public array $data + ) { } } diff --git a/extensions/tags/src/Filter/HideHiddenTagsFromAllDiscussionsPage.php b/extensions/tags/src/Filter/HideHiddenTagsFromAllDiscussionsPage.php index b9f8cc4c1..b4ae373a0 100644 --- a/extensions/tags/src/Filter/HideHiddenTagsFromAllDiscussionsPage.php +++ b/extensions/tags/src/Filter/HideHiddenTagsFromAllDiscussionsPage.php @@ -15,7 +15,7 @@ use Flarum\Tags\Tag; class HideHiddenTagsFromAllDiscussionsPage { - public function __invoke(FilterState $filter, QueryCriteria $queryCriteria) + public function __invoke(FilterState $filter, QueryCriteria $queryCriteria): void { if (count($filter->getActiveFilters()) > 0) { return; diff --git a/extensions/tags/src/Filter/PostTagFilter.php b/extensions/tags/src/Filter/PostTagFilter.php index 7501fedfc..39709c2e1 100644 --- a/extensions/tags/src/Filter/PostTagFilter.php +++ b/extensions/tags/src/Filter/PostTagFilter.php @@ -22,7 +22,7 @@ class PostTagFilter implements FilterInterface return 'tag'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $ids = $this->asIntArray($filterValue); diff --git a/extensions/tags/src/Listener/CreatePostWhenTagsAreChanged.php b/extensions/tags/src/Listener/CreatePostWhenTagsAreChanged.php index 2ad235431..678c3afb3 100755 --- a/extensions/tags/src/Listener/CreatePostWhenTagsAreChanged.php +++ b/extensions/tags/src/Listener/CreatePostWhenTagsAreChanged.php @@ -15,11 +15,7 @@ use Illuminate\Support\Arr; class CreatePostWhenTagsAreChanged { - /** - * @param DiscussionWasTagged $event - * @return void - */ - public function handle(DiscussionWasTagged $event) + public function handle(DiscussionWasTagged $event): void { $post = DiscussionTaggedPost::reply( $event->discussion->id, diff --git a/extensions/tags/src/Listener/SaveTagsToDatabase.php b/extensions/tags/src/Listener/SaveTagsToDatabase.php index c6d04c4c5..c1eba2ae8 100755 --- a/extensions/tags/src/Listener/SaveTagsToDatabase.php +++ b/extensions/tags/src/Listener/SaveTagsToDatabase.php @@ -11,48 +11,23 @@ namespace Flarum\Tags\Listener; use Flarum\Discussion\Event\Saving; use Flarum\Foundation\ValidationException; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Tags\Event\DiscussionWasTagged; use Flarum\Tags\Tag; use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Contracts\Validation\Factory; -use Symfony\Contracts\Translation\TranslatorInterface; class SaveTagsToDatabase { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Factory - */ - protected $validator; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @param SettingsRepositoryInterface $settings - * @param Factory $validator - * @param TranslatorInterface $translator - */ - public function __construct(SettingsRepositoryInterface $settings, Factory $validator, TranslatorInterface $translator) - { - $this->settings = $settings; - $this->validator = $validator; - $this->translator = $translator; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected Factory $validator, + protected TranslatorInterface $translator + ) { } - /** - * @param Saving $event - * @throws PermissionDeniedException - * @throws ValidationException - */ - public function handle(Saving $event) + public function handle(Saving $event): void { $discussion = $event->discussion; $actor = $event->actor; @@ -123,12 +98,7 @@ class SaveTagsToDatabase } } - /** - * @param string $type - * @param int $count - * @throws ValidationException - */ - protected function validateTagCount($type, $count) + protected function validateTagCount(string $type, int $count): void { $min = $this->settings->get('flarum-tags.min_'.$type.'_tags'); $max = $this->settings->get('flarum-tags.max_'.$type.'_tags'); diff --git a/extensions/tags/src/Listener/UpdateTagMetadata.php b/extensions/tags/src/Listener/UpdateTagMetadata.php index f0f0132ed..c2d6e2505 100755 --- a/extensions/tags/src/Listener/UpdateTagMetadata.php +++ b/extensions/tags/src/Listener/UpdateTagMetadata.php @@ -27,35 +27,26 @@ use Illuminate\Support\Arr; class UpdateTagMetadata { - /** - * @param Dispatcher $events - */ - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Started::class, [$this, 'whenDiscussionIsStarted']); - $events->listen(DiscussionWasTagged::class, [$this, 'whenDiscussionWasTagged']); - $events->listen(Deleted::class, [$this, 'whenDiscussionIsDeleted']); - $events->listen(Hidden::class, [$this, 'whenDiscussionIsHidden']); - $events->listen(Restored::class, [$this, 'whenDiscussionIsRestored']); + $events->listen(Started::class, $this->whenDiscussionIsStarted(...)); + $events->listen(DiscussionWasTagged::class, $this->whenDiscussionWasTagged(...)); + $events->listen(Deleted::class, $this->whenDiscussionIsDeleted(...)); + $events->listen(Hidden::class, $this->whenDiscussionIsHidden(...)); + $events->listen(Restored::class, $this->whenDiscussionIsRestored(...)); - $events->listen(Posted::class, [$this, 'whenPostIsPosted']); - $events->listen(PostDeleted::class, [$this, 'whenPostIsDeleted']); - $events->listen(PostHidden::class, [$this, 'whenPostIsHidden']); - $events->listen(PostRestored::class, [$this, 'whenPostIsRestored']); + $events->listen(Posted::class, $this->whenPostIsPosted(...)); + $events->listen(PostDeleted::class, $this->whenPostIsDeleted(...)); + $events->listen(PostHidden::class, $this->whenPostIsHidden(...)); + $events->listen(PostRestored::class, $this->whenPostIsRestored(...)); } - /** - * @param Started $event - */ - public function whenDiscussionIsStarted(Started $event) + public function whenDiscussionIsStarted(Started $event): void { $this->updateTags($event->discussion, 1); } - /** - * @param DiscussionWasTagged $event - */ - public function whenDiscussionWasTagged(DiscussionWasTagged $event) + public function whenDiscussionWasTagged(DiscussionWasTagged $event): void { $oldTags = Tag::whereIn('id', Arr::pluck($event->oldTags, 'id'))->get(); @@ -63,10 +54,7 @@ class UpdateTagMetadata $this->updateTags($event->discussion, 1); } - /** - * @param Deleted $event - */ - public function whenDiscussionIsDeleted(Deleted $event) + public function whenDiscussionIsDeleted(Deleted $event): void { // If already soft deleted when permanently deleted, the -1 delta has already been applied in Hidden listener $delta = $event->discussion->hidden_at ? 0 : -1; @@ -75,63 +63,42 @@ class UpdateTagMetadata $event->discussion->tags()->detach(); } - /** - * @param Hidden $event - */ - public function whenDiscussionIsHidden(Hidden $event) + public function whenDiscussionIsHidden(Hidden $event): void { $this->updateTags($event->discussion, -1); } - /** - * @param Restored $event - */ - public function whenDiscussionIsRestored(Restored $event) + public function whenDiscussionIsRestored(Restored $event): void { $this->updateTags($event->discussion, 1); } - /** - * @param Posted $event - */ - public function whenPostIsPosted(Posted $event) + public function whenPostIsPosted(Posted $event): void { $this->updateTags($event->post->discussion); } - /** - * @param PostDeleted $event - */ - public function whenPostIsDeleted(PostDeleted $event) + public function whenPostIsDeleted(PostDeleted $event): void { $discussion = $event->post->discussion; $delta = ! $discussion->exists && $discussion->hidden_at === null ? -1 : 0; $this->updateTags($discussion, $delta); } - /** - * @param PostHidden $event - */ - public function whenPostIsHidden(PostHidden $event) + public function whenPostIsHidden(PostHidden $event): void + { + $this->updateTags($event->post->discussion, 0, null, $event->post); + } + + public function whenPostIsRestored(PostRestored $event): void { $this->updateTags($event->post->discussion, 0, null, $event->post); } /** - * @param PostRestored $event + * @param Post|null $post This is only used when a post has been hidden */ - public function whenPostIsRestored(PostRestored $event) - { - $this->updateTags($event->post->discussion, 0, null, $event->post); - } - - /** - * @param Discussion $discussion - * @param int $delta - * @param Collection|null $tags - * @param Post $post: This is only used when a post has been hidden - */ - protected function updateTags(Discussion $discussion, $delta = 0, $tags = null, $post = null) + protected function updateTags(Discussion $discussion, int $delta = 0, ?Collection $tags = null, ?Post $post = null): void { if (! $tags) { $tags = $discussion->tags; diff --git a/extensions/tags/src/LoadForumTagsRelationship.php b/extensions/tags/src/LoadForumTagsRelationship.php index 8ef3db33f..e0d8c7453 100755 --- a/extensions/tags/src/LoadForumTagsRelationship.php +++ b/extensions/tags/src/LoadForumTagsRelationship.php @@ -15,12 +15,7 @@ use Psr\Http\Message\ServerRequestInterface; class LoadForumTagsRelationship { - /** - * @param ShowForumController $controller - * @param $data - * @param ServerRequestInterface $request - */ - public function __invoke(ShowForumController $controller, &$data, ServerRequestInterface $request) + public function __invoke(ShowForumController $controller, array &$data, ServerRequestInterface $request): void { $actor = RequestUtil::getActor($request); diff --git a/extensions/tags/src/Post/DiscussionTaggedPost.php b/extensions/tags/src/Post/DiscussionTaggedPost.php index db482e561..aed4d8886 100755 --- a/extensions/tags/src/Post/DiscussionTaggedPost.php +++ b/extensions/tags/src/Post/DiscussionTaggedPost.php @@ -16,15 +16,9 @@ use Flarum\Post\Post; class DiscussionTaggedPost extends AbstractEventPost implements MergeableInterface { - /** - * {@inheritdoc} - */ - public static $type = 'discussionTagged'; + public static string $type = 'discussionTagged'; - /** - * {@inheritdoc} - */ - public function saveAfter(Post $previous = null) + public function saveAfter(Post $previous = null): static { // If the previous post is another 'discussion tagged' post, and it's // by the same user, then we can merge this post into it. If we find @@ -53,16 +47,7 @@ class DiscussionTaggedPost extends AbstractEventPost implements MergeableInterfa return $this; } - /** - * Create a new instance in reply to a discussion. - * - * @param int $discussionId - * @param int $userId - * @param array $oldTagIds - * @param array $newTagIds - * @return static - */ - public static function reply($discussionId, $userId, array $oldTagIds, array $newTagIds) + public static function reply(int $discussionId, int $userId, array $oldTagIds, array $newTagIds): static { $post = new static; @@ -74,15 +59,8 @@ class DiscussionTaggedPost extends AbstractEventPost implements MergeableInterfa return $post; } - /** - * Build the content attribute. - * - * @param array $oldTagIds - * @param array $newTagIds - * @return array - */ - public static function buildContent(array $oldTagIds, array $newTagIds) + public static function buildContent(array $oldTagIds, array $newTagIds): array { - return [array_map('intval', $oldTagIds), array_map('intval', $newTagIds)]; + return [array_map(intval(...), $oldTagIds), array_map(intval(...), $newTagIds)]; } } diff --git a/extensions/tags/src/Query/TagFilterGambit.php b/extensions/tags/src/Query/TagFilterGambit.php index 294d4924a..afa7a46a4 100644 --- a/extensions/tags/src/Query/TagFilterGambit.php +++ b/extensions/tags/src/Query/TagFilterGambit.php @@ -24,22 +24,17 @@ class TagFilterGambit extends AbstractRegexGambit implements FilterInterface { use ValidateFilterTrait; - /** - * @var SlugManager - */ - protected $slugger; - - public function __construct(SlugManager $slugger) - { - $this->slugger = $slugger; + public function __construct( + protected SlugManager $slugger + ) { } - protected function getGambitPattern() + protected function getGambitPattern(): string { return 'tag:(.+)'; } - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $matches[1], $negate, $search->getActor()); } @@ -49,12 +44,12 @@ class TagFilterGambit extends AbstractRegexGambit implements FilterInterface return 'tag'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $filterValue, $negate, $filterState->getActor()); } - protected function constrain(Builder $query, $rawSlugs, $negate, User $actor) + protected function constrain(Builder $query, string|array $rawSlugs, $negate, User $actor): void { $slugs = $this->asStringArray($rawSlugs); diff --git a/extensions/tags/src/Search/Gambit/FulltextGambit.php b/extensions/tags/src/Search/Gambit/FulltextGambit.php index 9cf7c99ed..ad8d59ca3 100644 --- a/extensions/tags/src/Search/Gambit/FulltextGambit.php +++ b/extensions/tags/src/Search/Gambit/FulltextGambit.php @@ -16,14 +16,9 @@ use Illuminate\Database\Eloquent\Builder; class FulltextGambit implements GambitInterface { - /** - * @var TagRepository - */ - protected $tags; - - public function __construct(TagRepository $tags) - { - $this->tags = $tags; + public function __construct( + protected TagRepository $tags + ) { } private function getTagSearchSubQuery(string $searchValue): Builder @@ -35,12 +30,12 @@ class FulltextGambit implements GambitInterface ->orWhere('slug', 'like', "$searchValue%"); } - public function apply(SearchState $search, $searchValue) + public function apply(SearchState $search, string $bit): bool { $search->getQuery() ->whereIn( 'id', - $this->getTagSearchSubQuery($searchValue) + $this->getTagSearchSubQuery($bit) ); return true; diff --git a/extensions/tags/src/Search/TagSearcher.php b/extensions/tags/src/Search/TagSearcher.php index 2c1666432..b92ef5960 100644 --- a/extensions/tags/src/Search/TagSearcher.php +++ b/extensions/tags/src/Search/TagSearcher.php @@ -17,16 +17,12 @@ use Illuminate\Database\Eloquent\Builder; class TagSearcher extends AbstractSearcher { - /** - * @var TagRepository - */ - protected $tags; - - public function __construct(TagRepository $tags, GambitManager $gambits, array $searchMutators) - { + public function __construct( + protected TagRepository $tags, + GambitManager $gambits, + array $searchMutators + ) { parent::__construct($gambits, $searchMutators); - - $this->tags = $tags; } protected function getQuery(User $actor): Builder diff --git a/extensions/tags/src/Tag.php b/extensions/tags/src/Tag.php index 2bcbab5c1..503bff0be 100644 --- a/extensions/tags/src/Tag.php +++ b/extensions/tags/src/Tag.php @@ -16,6 +16,11 @@ use Flarum\Group\Permission; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Database\Query\Builder as QueryBuilder; /** * @property int $id @@ -76,18 +81,7 @@ class Tag extends AbstractModel }); } - /** - * Create a new tag. - * - * @param string $name - * @param string $slug - * @param string $description - * @param string $color - * @param string $icon - * @param bool $isHidden - * @return static - */ - public static function build($name, $slug, $description, $color, $icon, $isHidden) + public static function build(?string $name, ?string $slug, ?string $description, ?string $color, ?string $icon, ?bool $isHidden): static { $tag = new static; @@ -101,32 +95,38 @@ class Tag extends AbstractModel return $tag; } - public function parent() + public function parent(): BelongsTo { return $this->belongsTo(self::class); } - public function children() + /** + * @return HasMany + */ + public function children(): HasMany { return $this->hasMany(self::class, 'parent_id'); } - public function lastPostedDiscussion() + public function lastPostedDiscussion(): BelongsTo { return $this->belongsTo(Discussion::class, 'last_posted_discussion_id'); } - public function lastPostedUser() + public function lastPostedUser(): BelongsTo { return $this->belongsTo(User::class, 'last_posted_user_id'); } - public function discussions() + /** + * @return BelongsToMany + */ + public function discussions(): BelongsToMany { return $this->belongsToMany(Discussion::class); } - public function refreshLastPostedDiscussion() + public function refreshLastPostedDiscussion(): static { if ($lastPostedDiscussion = $this->discussions()->where('is_private', false)->whereNull('hidden_at')->latest('last_posted_at')->first()) { $this->setLastPostedDiscussion($lastPostedDiscussion); @@ -137,7 +137,7 @@ class Tag extends AbstractModel return $this; } - public function setLastPostedDiscussion(Discussion $discussion = null) + public function setLastPostedDiscussion(Discussion $discussion = null): static { $this->last_posted_at = optional($discussion)->last_posted_at; $this->last_posted_discussion_id = optional($discussion)->id; @@ -146,12 +146,7 @@ class Tag extends AbstractModel return $this; } - /** - * Define the relationship with the tag's state for a particular user. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne - */ - public function state() + public function state(): HasOne { return $this->hasOne(TagState::class); } @@ -159,11 +154,8 @@ class Tag extends AbstractModel /** * Get the state model for a user, or instantiate a new one if it does not * exist. - * - * @param User $user - * @return TagState */ - public function stateFor(User $user) + public function stateFor(User $user): TagState { $state = $this->state()->where('user_id', $user->id)->first(); @@ -176,12 +168,7 @@ class Tag extends AbstractModel return $state; } - /** - * @param Builder $query - * @param User $user - * @return Builder - */ - public function scopeWithStateFor(Builder $query, User $user) + public function scopeWithStateFor(Builder $query, User $user): Builder { return $query->with([ 'state' => function ($query) use ($user) { @@ -192,10 +179,8 @@ class Tag extends AbstractModel /** * Has this tag been unrestricted recently? - * - * @return bool */ - public function wasUnrestricted() + public function wasUnrestricted(): bool { return ! $this->is_restricted && $this->wasChanged('is_restricted'); } @@ -203,12 +188,12 @@ class Tag extends AbstractModel /** * Delete all permissions belonging to this tag. */ - public function deletePermissions() + public function deletePermissions(): void { Permission::where('permission', 'like', "tag{$this->id}.%")->delete(); } - protected static function buildPermissionSubquery($base, $isAdmin, $hasGlobalPermission, $tagIdsWithPermission) + protected static function buildPermissionSubquery(QueryBuilder $base, bool $isAdmin, bool $hasGlobalPermission, iterable $tagIdsWithPermission): void { $base ->from('tags as perm_tags') @@ -239,7 +224,7 @@ class Tag extends AbstractModel $tagIdsWithPermission = collect($allPermissions) ->filter(function ($permission) use ($currPermission) { - return substr($permission, 0, 3) === 'tag' && strpos($permission, $currPermission) !== false; + return str_starts_with($permission, 'tag') && str_contains($permission, $currPermission); }) ->map(function ($permission) { $scopeFragment = explode('.', $permission, 2)[0]; @@ -254,13 +239,13 @@ class Tag extends AbstractModel ->whereIn('tags.id', function ($query) use ($isAdmin, $hasGlobalPermission, $tagIdsWithPermission) { static::buildPermissionSubquery($query, $isAdmin, $hasGlobalPermission, $tagIdsWithPermission); }) - ->where(function ($query) use ($isAdmin, $hasGlobalPermission, $tagIdsWithPermission) { - $query - ->whereIn('tags.parent_id', function ($query) use ($isAdmin, $hasGlobalPermission, $tagIdsWithPermission) { - static::buildPermissionSubquery($query, $isAdmin, $hasGlobalPermission, $tagIdsWithPermission); - }) - ->orWhere('tags.parent_id', null); - }); + ->where( + fn ($query) => $query + ->whereIn('tags.parent_id', function ($query) use ($isAdmin, $hasGlobalPermission, $tagIdsWithPermission) { + static::buildPermissionSubquery($query, $isAdmin, $hasGlobalPermission, $tagIdsWithPermission); + }) + ->orWhere('tags.parent_id', null) + ); }); } } diff --git a/extensions/tags/src/TagRepository.php b/extensions/tags/src/TagRepository.php index 8ea1b683b..e6522d8b7 100644 --- a/extensions/tags/src/TagRepository.php +++ b/extensions/tags/src/TagRepository.php @@ -11,17 +11,16 @@ namespace Flarum\Tags; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; class TagRepository { private const TAG_RELATIONS = ['children', 'parent', 'parent.children']; /** - * Get a new query builder for the tags table. - * - * @return Builder + * @return Builder */ - public function query() + public function query(): Builder { return Tag::query(); } @@ -32,21 +31,14 @@ class TagRepository } /** - * @param array|string $relations - * @param User $actor * @return Builder */ - public function with($relations, User $actor): Builder + public function with(array|string $relations, User $actor): Builder { return $this->query()->with($this->getAuthorizedRelations($relations, $actor)); } - /** - * @param array|string $relations - * @param User $actor - * @return array - */ - public function getAuthorizedRelations($relations, User $actor): array + public function getAuthorizedRelations(array|string $relations, User $actor): array { $relations = is_string($relations) ? explode(',', $relations) : $relations; $relationsArray = []; @@ -67,12 +59,8 @@ class TagRepository /** * Find a tag by ID, optionally making sure it is visible to a certain * user, or throw an exception. - * - * @param int $id - * @param User|null $actor - * @return Tag */ - public function findOrFail($id, User $actor = null) + public function findOrFail(int $id, User $actor = null): Tag { $query = Tag::where('id', $id); @@ -83,10 +71,9 @@ class TagRepository * Find all tags, optionally making sure they are visible to a * certain user. * - * @param User|null $user - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ - public function all(User $user = null) + public function all(User $user = null): Collection { $query = Tag::query(); @@ -95,12 +82,8 @@ class TagRepository /** * Get the ID of a tag with the given slug. - * - * @param string $slug - * @param User|null $user - * @return int */ - public function getIdForSlug($slug, User $user = null): ?int + public function getIdForSlug(string $slug, User $user = null): ?int { $query = Tag::where('slug', $slug); @@ -111,10 +94,9 @@ class TagRepository * Scope a query to only include records that are visible to a user. * * @param Builder $query - * @param User|null $user * @return Builder */ - protected function scopeVisibleTo(Builder $query, ?User $user = null) + protected function scopeVisibleTo(Builder $query, ?User $user = null): Builder { if ($user !== null) { $query->whereVisibleTo($user); diff --git a/extensions/tags/src/TagState.php b/extensions/tags/src/TagState.php index e697ccbb3..f020826d5 100644 --- a/extensions/tags/src/TagState.php +++ b/extensions/tags/src/TagState.php @@ -13,6 +13,7 @@ use Flarum\Database\AbstractModel; use Flarum\Foundation\EventGeneratorTrait; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @property int $user_id @@ -26,32 +27,16 @@ class TagState extends AbstractModel { use EventGeneratorTrait; - /** - * {@inheritdoc} - */ protected $table = 'tag_user'; - /** - * {@inheritdoc} - */ protected $dates = ['marked_as_read_at']; - /** - * Define the relationship with the tag that this state is for. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function tag() + public function tag(): BelongsTo { return $this->belongsTo(Tag::class); } - /** - * Define the relationship with the user that this state is for. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } diff --git a/extensions/tags/src/TagValidator.php b/extensions/tags/src/TagValidator.php index 6a064341a..d4cdbb435 100644 --- a/extensions/tags/src/TagValidator.php +++ b/extensions/tags/src/TagValidator.php @@ -13,10 +13,7 @@ use Flarum\Foundation\AbstractValidator; class TagValidator extends AbstractValidator { - /** - * {@inheritdoc} - */ - protected $rules = [ + protected array $rules = [ 'name' => ['required'], 'slug' => ['required', 'unique:tags', 'regex:/^[^\/\\ ]*$/i'], 'is_hidden' => ['bool'], diff --git a/extensions/tags/src/Utf8SlugDriver.php b/extensions/tags/src/Utf8SlugDriver.php index 36df9c9e4..2dce9c9f6 100644 --- a/extensions/tags/src/Utf8SlugDriver.php +++ b/extensions/tags/src/Utf8SlugDriver.php @@ -18,19 +18,13 @@ use Flarum\User\User; */ class Utf8SlugDriver implements SlugDriverInterface { - /** - * @var TagRepository - */ - protected $repository; - - public function __construct(TagRepository $repository) - { - $this->repository = $repository; + public function __construct( + protected TagRepository $repository + ) { } /** * @param Tag $instance - * @return string */ public function toSlug(AbstractModel $instance): string { @@ -38,8 +32,6 @@ class Utf8SlugDriver implements SlugDriverInterface } /** - * @param string $slug - * @param User $actor * @return Tag */ public function fromSlug(string $slug, User $actor): AbstractModel diff --git a/framework/core/composer.json b/framework/core/composer.json index bb1ebccc6..982c1f42a 100644 --- a/framework/core/composer.json +++ b/framework/core/composer.json @@ -36,7 +36,7 @@ "chat": "https://flarum.org/chat" }, "require": { - "php": ">=7.3 || ^8.0", + "php": "^8.1", "components/font-awesome": "^5.14.0", "dflydev/fig-cookies": "^3.0.0", "doctrine/dbal": "^2.7", diff --git a/framework/core/src/Admin/AdminServiceProvider.php b/framework/core/src/Admin/AdminServiceProvider.php index c5563aace..bde292eb2 100644 --- a/framework/core/src/Admin/AdminServiceProvider.php +++ b/framework/core/src/Admin/AdminServiceProvider.php @@ -32,10 +32,7 @@ use Laminas\Stratigility\MiddlewarePipe; class AdminServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->extend(UrlGenerator::class, function (UrlGenerator $url, Container $container) { return $url->addCollection('admin', $container->make('flarum.admin.routes'), 'admin'); @@ -118,10 +115,7 @@ class AdminServiceProvider extends AbstractServiceProvider }); } - /** - * {@inheritdoc} - */ - public function boot() + public function boot(): void { $this->loadViewsFrom(__DIR__.'/../../views', 'flarum.admin'); @@ -150,10 +144,7 @@ class AdminServiceProvider extends AbstractServiceProvider ); } - /** - * @param RouteCollection $routes - */ - protected function populateRoutes(RouteCollection $routes) + protected function populateRoutes(RouteCollection $routes): void { $factory = $this->container->make(RouteHandlerFactory::class); diff --git a/framework/core/src/Admin/Content/AdminPayload.php b/framework/core/src/Admin/Content/AdminPayload.php index 94d8ea6b6..d2e8af468 100644 --- a/framework/core/src/Admin/Content/AdminPayload.php +++ b/framework/core/src/Admin/Content/AdminPayload.php @@ -25,69 +25,18 @@ use Psr\Http\Message\ServerRequestInterface as Request; class AdminPayload { - /** - * @var Container; - */ - protected $container; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var ConnectionInterface - */ - protected $db; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var Config - */ - protected $config; - - /** - * @var ApplicationInfoProvider - */ - protected $appInfo; - - /** - * @param Container $container - * @param SettingsRepositoryInterface $settings - * @param ExtensionManager $extensions - * @param ConnectionInterface $db - * @param Dispatcher $events - * @param Config $config - * @param ApplicationInfoProvider $appInfo - */ public function __construct( - Container $container, - SettingsRepositoryInterface $settings, - ExtensionManager $extensions, - ConnectionInterface $db, - Dispatcher $events, - Config $config, - ApplicationInfoProvider $appInfo + protected Container $container, + protected SettingsRepositoryInterface $settings, + protected ExtensionManager $extensions, + protected ConnectionInterface $db, + protected Dispatcher $events, + protected Config $config, + protected ApplicationInfoProvider $appInfo ) { - $this->container = $container; - $this->settings = $settings; - $this->extensions = $extensions; - $this->db = $db; - $this->events = $events; - $this->config = $config; - $this->appInfo = $appInfo; } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): void { $settings = $this->settings->all(); @@ -124,7 +73,7 @@ class AdminPayload */ $document->payload['modelStatistics'] = [ 'users' => [ - 'total' => User::count() + 'total' => User::query()->count() ] ]; } diff --git a/framework/core/src/Admin/Content/Index.php b/framework/core/src/Admin/Content/Index.php index 2060955cb..b70466fb5 100644 --- a/framework/core/src/Admin/Content/Index.php +++ b/framework/core/src/Admin/Content/Index.php @@ -18,26 +18,11 @@ use Psr\Http\Message\ServerRequestInterface as Request; class Index { - /** - * @var Factory - */ - protected $view; - - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(Factory $view, ExtensionManager $extensions, SettingsRepositoryInterface $settings) - { - $this->view = $view; - $this->extensions = $extensions; - $this->settings = $settings; + public function __construct( + protected Factory $view, + protected ExtensionManager $extensions, + protected SettingsRepositoryInterface $settings + ) { } public function __invoke(Document $document, Request $request): Document diff --git a/framework/core/src/Admin/Controller/UpdateExtensionController.php b/framework/core/src/Admin/Controller/UpdateExtensionController.php index 61db18a59..1d93705b6 100644 --- a/framework/core/src/Admin/Controller/UpdateExtensionController.php +++ b/framework/core/src/Admin/Controller/UpdateExtensionController.php @@ -21,25 +21,12 @@ use Psr\Http\Server\RequestHandlerInterface; class UpdateExtensionController implements RequestHandlerInterface { - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(UrlGenerator $url, Dispatcher $bus) - { - $this->url = $url; - $this->bus = $bus; + public function __construct( + protected UrlGenerator $url, + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ public function handle(Request $request): ResponseInterface { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/ApiKey.php b/framework/core/src/Api/ApiKey.php index 4bdcdfa3b..9dcaaabbc 100644 --- a/framework/core/src/Api/ApiKey.php +++ b/framework/core/src/Api/ApiKey.php @@ -12,6 +12,7 @@ namespace Flarum\Api; use Carbon\Carbon; use Flarum\Database\AbstractModel; use Flarum\User\User; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Str; /** @@ -28,12 +29,7 @@ class ApiKey extends AbstractModel { protected $dates = ['last_activity_at']; - /** - * Generate an API key. - * - * @return static - */ - public static function generate() + public static function generate(): static { $key = new static; @@ -42,14 +38,14 @@ class ApiKey extends AbstractModel return $key; } - public function touch() + public function touch(): bool { $this->last_activity_at = Carbon::now(); return $this->save(); } - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } diff --git a/framework/core/src/Api/ApiServiceProvider.php b/framework/core/src/Api/ApiServiceProvider.php index 7d18e806b..acd7a8b63 100644 --- a/framework/core/src/Api/ApiServiceProvider.php +++ b/framework/core/src/Api/ApiServiceProvider.php @@ -26,10 +26,7 @@ use Laminas\Stratigility\MiddlewarePipe; class ApiServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->extend(UrlGenerator::class, function (UrlGenerator $url, Container $container) { return $url->addCollection('api', $container->make('flarum.api.routes'), 'api'); @@ -135,10 +132,7 @@ class ApiServiceProvider extends AbstractServiceProvider }); } - /** - * {@inheritdoc} - */ - public function boot(Container $container) + public function boot(Container $container): void { $this->setNotificationSerializers(); @@ -147,10 +141,7 @@ class ApiServiceProvider extends AbstractServiceProvider AbstractSerializer::setContainer($container); } - /** - * Register notification serializers. - */ - protected function setNotificationSerializers() + protected function setNotificationSerializers(): void { $serializers = $this->container->make('flarum.api.notification_serializers'); @@ -159,12 +150,7 @@ class ApiServiceProvider extends AbstractServiceProvider } } - /** - * Populate the API routes. - * - * @param RouteCollection $routes - */ - protected function populateRoutes(RouteCollection $routes) + protected function populateRoutes(RouteCollection $routes): void { $factory = $this->container->make(RouteHandlerFactory::class); diff --git a/framework/core/src/Api/Client.php b/framework/core/src/Api/Client.php index 11e3d45bc..3ef24084d 100644 --- a/framework/core/src/Api/Client.php +++ b/framework/core/src/Api/Client.php @@ -19,34 +19,14 @@ use Psr\Http\Message\ServerRequestInterface; class Client { - /** - * @var MiddlewarePipeInterface - */ - protected $pipe; + protected ?User $actor = null; + protected ?ServerRequestInterface $parent = null; + protected array $queryParams = []; + protected array $body = []; - /** - * @var User|null - */ - protected $actor; - - /** - * @var ServerRequestInterface|null - */ - protected $parent; - - /** - * @var array - */ - protected $queryParams = []; - - /** - * @var array - */ - protected $body = []; - - public function __construct(MiddlewarePipeInterface $pipe) - { - $this->pipe = $pipe; + public function __construct( + protected MiddlewarePipeInterface $pipe + ) { } /** @@ -114,10 +94,6 @@ class Client /** * Execute the given API action class, pass the input and return its response. * - * @param string $method - * @param string $path - * @return ResponseInterface - * * @internal */ public function send(string $method, string $path): ResponseInterface diff --git a/framework/core/src/Api/Controller/AbstractCreateController.php b/framework/core/src/Api/Controller/AbstractCreateController.php index 15522a63a..00b9c774b 100644 --- a/framework/core/src/Api/Controller/AbstractCreateController.php +++ b/framework/core/src/Api/Controller/AbstractCreateController.php @@ -14,9 +14,6 @@ use Psr\Http\Message\ServerRequestInterface; abstract class AbstractCreateController extends AbstractShowController { - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { return parent::handle($request)->withStatus(201); diff --git a/framework/core/src/Api/Controller/AbstractDeleteController.php b/framework/core/src/Api/Controller/AbstractDeleteController.php index 8aa2e92c4..b2702c79a 100644 --- a/framework/core/src/Api/Controller/AbstractDeleteController.php +++ b/framework/core/src/Api/Controller/AbstractDeleteController.php @@ -16,9 +16,6 @@ use Psr\Http\Server\RequestHandlerInterface; abstract class AbstractDeleteController implements RequestHandlerInterface { - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { $this->delete($request); @@ -26,10 +23,5 @@ abstract class AbstractDeleteController implements RequestHandlerInterface return new EmptyResponse(204); } - /** - * Delete the resource. - * - * @param ServerRequestInterface $request - */ - abstract protected function delete(ServerRequestInterface $request); + abstract protected function delete(ServerRequestInterface $request): void; } diff --git a/framework/core/src/Api/Controller/AbstractListController.php b/framework/core/src/Api/Controller/AbstractListController.php index 1f661c152..ac4fd8753 100644 --- a/framework/core/src/Api/Controller/AbstractListController.php +++ b/framework/core/src/Api/Controller/AbstractListController.php @@ -9,16 +9,18 @@ namespace Flarum\Api\Controller; +use Psr\Http\Message\ServerRequestInterface; use Tobscure\JsonApi\Collection; +use Tobscure\JsonApi\Document; +use Tobscure\JsonApi\ElementInterface; use Tobscure\JsonApi\SerializerInterface; abstract class AbstractListController extends AbstractSerializeController { - /** - * {@inheritdoc} - */ - protected function createElement($data, SerializerInterface $serializer) + protected function createElement(mixed $data, SerializerInterface $serializer): ElementInterface { return new Collection($data, $serializer); } + + abstract protected function data(ServerRequestInterface $request, Document $document): iterable; } diff --git a/framework/core/src/Api/Controller/AbstractSerializeController.php b/framework/core/src/Api/Controller/AbstractSerializeController.php index cd13ff5c2..2c65d74f0 100644 --- a/framework/core/src/Api/Controller/AbstractSerializeController.php +++ b/framework/core/src/Api/Controller/AbstractSerializeController.php @@ -10,6 +10,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\JsonApiResponse; +use Flarum\Api\Serializer\AbstractSerializer; use Illuminate\Contracts\Container\Container; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Arr; @@ -19,6 +20,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Tobscure\JsonApi\Document; +use Tobscure\JsonApi\ElementInterface; use Tobscure\JsonApi\Parameters; use Tobscure\JsonApi\SerializerInterface; @@ -27,80 +29,70 @@ abstract class AbstractSerializeController implements RequestHandlerInterface /** * The name of the serializer class to output results with. * - * @var string + * @var class-string|null */ - public $serializer; + public ?string $serializer; /** * The relationships that are included by default. * - * @var array + * @var string[] */ - public $include = []; + public array $include = []; /** * The relationships that are available to be included. * - * @var array + * @var string[] */ - public $optionalInclude = []; + public array $optionalInclude = []; /** * The maximum number of records that can be requested. - * - * @var int */ - public $maxLimit = 50; + public int $maxLimit = 50; /** * The number of records included by default. - * - * @var int */ - public $limit = 20; + public int $limit = 20; /** * The fields that are available to be sorted by. * - * @var array + * @var string[] */ - public $sortFields = []; + public array $sortFields = []; /** - * The default sort field and order to user. + * The default sort field and order to use. * - * @var array|null + * @var array|null */ - public $sort; + public ?array $sort = null; + + protected static Container $container; /** - * @var Container + * @var array, callable[]> */ - protected static $container; + protected static array $beforeDataCallbacks = []; /** - * @var array + * @var array, callable[]> */ - protected static $beforeDataCallbacks = []; - - /** - * @var array - */ - protected static $beforeSerializationCallbacks = []; + protected static array $beforeSerializationCallbacks = []; /** * @var string[][] */ - protected static $loadRelations = []; + protected static array $loadRelations = []; /** * @var array */ - protected static $loadRelationCallables = []; + protected static array $loadRelationCallables = []; - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { $document = new Document; @@ -141,21 +133,13 @@ abstract class AbstractSerializeController implements RequestHandlerInterface /** * Get the data to be serialized and assigned to the response document. - * - * @param ServerRequestInterface $request - * @param Document $document - * @return mixed */ - abstract protected function data(ServerRequestInterface $request, Document $document); + abstract protected function data(ServerRequestInterface $request, Document $document): mixed; /** * Create a PHP JSON-API Element for output in the document. - * - * @param mixed $data - * @param SerializerInterface $serializer - * @return \Tobscure\JsonApi\ElementInterface */ - abstract protected function createElement($data, SerializerInterface $serializer); + abstract protected function createElement(mixed $data, SerializerInterface $serializer): ElementInterface; /** * Returns the relations to load added by extenders. @@ -211,7 +195,7 @@ abstract class AbstractSerializeController implements RequestHandlerInterface }); foreach ($addedRelations as $relation) { - if (strpos($relation, '.') !== false) { + if (str_contains($relation, '.')) { $parentRelation = Str::beforeLast($relation, '.'); if (! in_array($parentRelation, $relations, true)) { @@ -252,69 +236,50 @@ abstract class AbstractSerializeController implements RequestHandlerInterface } /** - * @param ServerRequestInterface $request - * @return array * @throws \Tobscure\JsonApi\Exception\InvalidParameterException */ - protected function extractInclude(ServerRequestInterface $request) + protected function extractInclude(ServerRequestInterface $request): array { $available = array_merge($this->include, $this->optionalInclude); return $this->buildParameters($request)->getInclude($available) ?: $this->include; } - /** - * @param ServerRequestInterface $request - * @return array - */ - protected function extractFields(ServerRequestInterface $request) + protected function extractFields(ServerRequestInterface $request): array { return $this->buildParameters($request)->getFields(); } /** - * @param ServerRequestInterface $request - * @return array|null * @throws \Tobscure\JsonApi\Exception\InvalidParameterException */ - protected function extractSort(ServerRequestInterface $request) + protected function extractSort(ServerRequestInterface $request): ?array { return $this->buildParameters($request)->getSort($this->sortFields) ?: $this->sort; } /** - * @param ServerRequestInterface $request - * @return int * @throws \Tobscure\JsonApi\Exception\InvalidParameterException */ - protected function extractOffset(ServerRequestInterface $request) + protected function extractOffset(ServerRequestInterface $request): int { return (int) $this->buildParameters($request)->getOffset($this->extractLimit($request)) ?: 0; } /** - * @param ServerRequestInterface $request - * @return int + * @throws \Tobscure\JsonApi\Exception\InvalidParameterException */ - protected function extractLimit(ServerRequestInterface $request) + protected function extractLimit(ServerRequestInterface $request): int { return (int) $this->buildParameters($request)->getLimit($this->maxLimit) ?: $this->limit; } - /** - * @param ServerRequestInterface $request - * @return array - */ - protected function extractFilter(ServerRequestInterface $request) + protected function extractFilter(ServerRequestInterface $request): array { return $this->buildParameters($request)->getFilter() ?: []; } - /** - * @param ServerRequestInterface $request - * @return Parameters - */ - protected function buildParameters(ServerRequestInterface $request) + protected function buildParameters(ServerRequestInterface $request): Parameters { return new Parameters($request->getQueryParams()); } @@ -326,129 +291,101 @@ abstract class AbstractSerializeController implements RequestHandlerInterface /** * Set the serializer that will serialize data for the endpoint. - * - * @param string $serializer */ - public function setSerializer(string $serializer) + public function setSerializer(string $serializer): void { $this->serializer = $serializer; } /** * Include the given relationship by default. - * - * @param string|array $name */ - public function addInclude($name) + public function addInclude(array|string $name): void { $this->include = array_merge($this->include, (array) $name); } /** * Don't include the given relationship by default. - * - * @param string|array $name */ - public function removeInclude($name) + public function removeInclude(array|string $name): void { $this->include = array_diff($this->include, (array) $name); } /** * Make the given relationship available for inclusion. - * - * @param string|array $name */ - public function addOptionalInclude($name) + public function addOptionalInclude(array|string $name): void { $this->optionalInclude = array_merge($this->optionalInclude, (array) $name); } /** * Don't allow the given relationship to be included. - * - * @param string|array $name */ - public function removeOptionalInclude($name) + public function removeOptionalInclude(array|string $name): void { $this->optionalInclude = array_diff($this->optionalInclude, (array) $name); } /** * Set the default number of results. - * - * @param int $limit */ - public function setLimit(int $limit) + public function setLimit(int $limit): void { $this->limit = $limit; } /** * Set the maximum number of results. - * - * @param int $max */ - public function setMaxLimit(int $max) + public function setMaxLimit(int $max): void { $this->maxLimit = $max; } /** * Allow sorting results by the given field. - * - * @param string|array $field */ - public function addSortField($field) + public function addSortField(array|string $field): void { $this->sortFields = array_merge($this->sortFields, (array) $field); } /** * Disallow sorting results by the given field. - * - * @param string|array $field */ - public function removeSortField($field) + public function removeSortField(array|string $field): void { $this->sortFields = array_diff($this->sortFields, (array) $field); } /** * Set the default sort order for the results. - * - * @param array $sort */ - public function setSort(array $sort) + public function setSort(array $sort): void { $this->sort = $sort; } - /** - * @return Container - */ - public static function getContainer() + public static function getContainer(): Container { return static::$container; } /** - * @param Container $container - * * @internal */ - public static function setContainer(Container $container) + public static function setContainer(Container $container): void { static::$container = $container; } /** - * @param string $controllerClass - * @param callable $callback - * * @internal */ - public static function addDataPreparationCallback(string $controllerClass, callable $callback) + public static function addDataPreparationCallback(string $controllerClass, callable $callback): void { if (! isset(static::$beforeDataCallbacks[$controllerClass])) { static::$beforeDataCallbacks[$controllerClass] = []; @@ -458,12 +395,9 @@ abstract class AbstractSerializeController implements RequestHandlerInterface } /** - * @param string $controllerClass - * @param callable $callback - * * @internal */ - public static function addSerializationPreparationCallback(string $controllerClass, callable $callback) + public static function addSerializationPreparationCallback(string $controllerClass, callable $callback): void { if (! isset(static::$beforeSerializationCallbacks[$controllerClass])) { static::$beforeSerializationCallbacks[$controllerClass] = []; @@ -475,7 +409,7 @@ abstract class AbstractSerializeController implements RequestHandlerInterface /** * @internal */ - public static function setLoadRelations(string $controllerClass, array $relations) + public static function setLoadRelations(string $controllerClass, array $relations): void { if (! isset(static::$loadRelations[$controllerClass])) { static::$loadRelations[$controllerClass] = []; @@ -487,7 +421,7 @@ abstract class AbstractSerializeController implements RequestHandlerInterface /** * @internal */ - public static function setLoadRelationCallables(string $controllerClass, array $relations) + public static function setLoadRelationCallables(string $controllerClass, array $relations): void { if (! isset(static::$loadRelationCallables[$controllerClass])) { static::$loadRelationCallables[$controllerClass] = []; diff --git a/framework/core/src/Api/Controller/AbstractShowController.php b/framework/core/src/Api/Controller/AbstractShowController.php index 07cd9a6d5..b87b5c594 100644 --- a/framework/core/src/Api/Controller/AbstractShowController.php +++ b/framework/core/src/Api/Controller/AbstractShowController.php @@ -14,10 +14,7 @@ use Tobscure\JsonApi\SerializerInterface; abstract class AbstractShowController extends AbstractSerializeController { - /** - * {@inheritdoc} - */ - protected function createElement($data, SerializerInterface $serializer) + protected function createElement(mixed $data, SerializerInterface $serializer): \Tobscure\JsonApi\ElementInterface { return new Resource($data, $serializer); } diff --git a/framework/core/src/Api/Controller/ClearCacheController.php b/framework/core/src/Api/Controller/ClearCacheController.php index f498cd590..24352d1cb 100644 --- a/framework/core/src/Api/Controller/ClearCacheController.php +++ b/framework/core/src/Api/Controller/ClearCacheController.php @@ -13,37 +13,22 @@ use Flarum\Foundation\Console\AssetsPublishCommand; use Flarum\Foundation\Console\CacheClearCommand; use Flarum\Foundation\IOException; use Flarum\Http\RequestUtil; -use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ServerRequestInterface; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; class ClearCacheController extends AbstractDeleteController { - /** - * @var CacheClearCommand - */ - protected $command; - - /** - * @var AssetsPublishCommand - */ - protected $assetsPublishCommand; - - /** - * @param CacheClearCommand $command - */ - public function __construct(CacheClearCommand $command, AssetsPublishCommand $assetsPublishCommand) - { - $this->command = $command; - $this->assetsPublishCommand = $assetsPublishCommand; + public function __construct( + protected CacheClearCommand $command, + protected AssetsPublishCommand $assetsPublishCommand + ) { } /** - * {@inheritdoc} - * @throws IOException|\Flarum\User\Exception\PermissionDeniedException + * @throws IOException|\Flarum\User\Exception\PermissionDeniedException|\Symfony\Component\Console\Exception\ExceptionInterface */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { RequestUtil::getActor($request)->assertAdmin(); @@ -64,7 +49,5 @@ class ClearCacheController extends AbstractDeleteController if ($exitCode !== 0) { throw new IOException(); } - - return new EmptyResponse(204); } } diff --git a/framework/core/src/Api/Controller/CreateAccessTokenController.php b/framework/core/src/Api/Controller/CreateAccessTokenController.php index 10260ad14..4917d6bff 100644 --- a/framework/core/src/Api/Controller/CreateAccessTokenController.php +++ b/framework/core/src/Api/Controller/CreateAccessTokenController.php @@ -25,28 +25,15 @@ use Tobscure\JsonApi\Document; */ class CreateAccessTokenController extends AbstractCreateController { - public $serializer = AccessTokenSerializer::class; + public ?string $serializer = AccessTokenSerializer::class; - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var Factory - */ - protected $validation; - - public function __construct(Dispatcher $events, Factory $validation) - { - $this->events = $events; - $this->validation = $validation; + public function __construct( + protected Dispatcher $events, + protected Factory $validation + ) { } - /** - * {@inheritdoc} - */ - public function data(ServerRequestInterface $request, Document $document) + public function data(ServerRequestInterface $request, Document $document): DeveloperAccessToken { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/CreateDiscussionController.php b/framework/core/src/Api/Controller/CreateDiscussionController.php index 972876f33..fe5a28ee6 100644 --- a/framework/core/src/Api/Controller/CreateDiscussionController.php +++ b/framework/core/src/Api/Controller/CreateDiscussionController.php @@ -12,6 +12,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\DiscussionSerializer; use Flarum\Discussion\Command\ReadDiscussion; use Flarum\Discussion\Command\StartDiscussion; +use Flarum\Discussion\Discussion; use Flarum\Http\RequestUtil; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Database\Eloquent\Collection; @@ -21,15 +22,9 @@ use Tobscure\JsonApi\Document; class CreateDiscussionController extends AbstractCreateController { - /** - * {@inheritdoc} - */ - public $serializer = DiscussionSerializer::class; + public ?string $serializer = DiscussionSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'posts', 'user', 'lastPostedUser', @@ -37,23 +32,12 @@ class CreateDiscussionController extends AbstractCreateController 'lastPost' ]; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Discussion { $actor = RequestUtil::getActor($request); $ipAddress = $request->getAttribute('ipAddress'); @@ -63,7 +47,7 @@ class CreateDiscussionController extends AbstractCreateController ); // After creating the discussion, we assume that the user has seen all - // of the posts in the discussion; thus, we will mark the discussion + // the posts in the discussion; thus, we will mark the discussion // as read if they are logged in. if ($actor->exists) { $this->bus->dispatch( diff --git a/framework/core/src/Api/Controller/CreateGroupController.php b/framework/core/src/Api/Controller/CreateGroupController.php index a66c4b9bb..1d8ff85f3 100644 --- a/framework/core/src/Api/Controller/CreateGroupController.php +++ b/framework/core/src/Api/Controller/CreateGroupController.php @@ -11,6 +11,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\GroupSerializer; use Flarum\Group\Command\CreateGroup; +use Flarum\Group\Group; use Flarum\Http\RequestUtil; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; @@ -19,28 +20,14 @@ use Tobscure\JsonApi\Document; class CreateGroupController extends AbstractCreateController { - /** - * {@inheritdoc} - */ - public $serializer = GroupSerializer::class; + public ?string $serializer = GroupSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Group { return $this->bus->dispatch( new CreateGroup(RequestUtil::getActor($request), Arr::get($request->getParsedBody(), 'data', [])) diff --git a/framework/core/src/Api/Controller/CreatePostController.php b/framework/core/src/Api/Controller/CreatePostController.php index 499415af4..93e3e8e79 100644 --- a/framework/core/src/Api/Controller/CreatePostController.php +++ b/framework/core/src/Api/Controller/CreatePostController.php @@ -13,6 +13,7 @@ use Flarum\Api\Serializer\PostSerializer; use Flarum\Discussion\Command\ReadDiscussion; use Flarum\Http\RequestUtil; use Flarum\Post\Command\PostReply; +use Flarum\Post\CommentPost; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -20,38 +21,21 @@ use Tobscure\JsonApi\Document; class CreatePostController extends AbstractCreateController { - /** - * {@inheritdoc} - */ - public $serializer = PostSerializer::class; + public ?string $serializer = PostSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'user', 'discussion', 'discussion.posts', 'discussion.lastPostedUser' ]; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): CommentPost { $actor = RequestUtil::getActor($request); $data = Arr::get($request->getParsedBody(), 'data', []); diff --git a/framework/core/src/Api/Controller/CreateTokenController.php b/framework/core/src/Api/Controller/CreateTokenController.php index a60a27b21..adb7049d4 100644 --- a/framework/core/src/Api/Controller/CreateTokenController.php +++ b/framework/core/src/Api/Controller/CreateTokenController.php @@ -28,36 +28,13 @@ use Psr\Http\Server\RequestHandlerInterface; */ class CreateTokenController implements RequestHandlerInterface { - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @var BusDispatcher - */ - protected $bus; - - /** - * @var EventDispatcher - */ - protected $events; - - /** - * @param UserRepository $users - * @param BusDispatcher $bus - * @param EventDispatcher $events - */ - public function __construct(UserRepository $users, BusDispatcher $bus, EventDispatcher $events) - { - $this->users = $users; - $this->bus = $bus; - $this->events = $events; + public function __construct( + protected UserRepository $users, + protected BusDispatcher $bus, + protected EventDispatcher $events + ) { } - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { $body = $request->getParsedBody(); @@ -65,7 +42,9 @@ class CreateTokenController implements RequestHandlerInterface $identification = Arr::get($body, 'identification'); $password = Arr::get($body, 'password'); - $user = $this->users->findByIdentification($identification); + $user = $identification + ? $this->users->findByIdentification($identification) + : null; if (! $user || ! $user->checkPassword($password)) { throw new NotAuthenticatedException; diff --git a/framework/core/src/Api/Controller/CreateUserController.php b/framework/core/src/Api/Controller/CreateUserController.php index 28f238ba5..03c091607 100644 --- a/framework/core/src/Api/Controller/CreateUserController.php +++ b/framework/core/src/Api/Controller/CreateUserController.php @@ -12,6 +12,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\CurrentUserSerializer; use Flarum\Http\RequestUtil; use Flarum\User\Command\RegisterUser; +use Flarum\User\User; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -19,28 +20,14 @@ use Tobscure\JsonApi\Document; class CreateUserController extends AbstractCreateController { - /** - * {@inheritdoc} - */ - public $serializer = CurrentUserSerializer::class; + public ?string $serializer = CurrentUserSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): User { return $this->bus->dispatch( new RegisterUser(RequestUtil::getActor($request), Arr::get($request->getParsedBody(), 'data', [])) diff --git a/framework/core/src/Api/Controller/DeleteAccessTokenController.php b/framework/core/src/Api/Controller/DeleteAccessTokenController.php index 739901250..af2b224ec 100644 --- a/framework/core/src/Api/Controller/DeleteAccessTokenController.php +++ b/framework/core/src/Api/Controller/DeleteAccessTokenController.php @@ -15,15 +15,11 @@ use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Contracts\Session\Session; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Arr; -use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ServerRequestInterface; class DeleteAccessTokenController extends AbstractDeleteController { - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $actor = RequestUtil::getActor($request); $id = Arr::get($request->getQueryParams(), 'id'); @@ -46,7 +42,5 @@ class DeleteAccessTokenController extends AbstractDeleteController } $token->delete(); - - return new EmptyResponse(204); } } diff --git a/framework/core/src/Api/Controller/DeleteAllNotificationsController.php b/framework/core/src/Api/Controller/DeleteAllNotificationsController.php index 7e5d3df76..33f7620fe 100644 --- a/framework/core/src/Api/Controller/DeleteAllNotificationsController.php +++ b/framework/core/src/Api/Controller/DeleteAllNotificationsController.php @@ -16,23 +16,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeleteAllNotificationsController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new DeleteAllNotifications(RequestUtil::getActor($request)) diff --git a/framework/core/src/Api/Controller/DeleteAvatarController.php b/framework/core/src/Api/Controller/DeleteAvatarController.php index defee70cf..33baf6348 100644 --- a/framework/core/src/Api/Controller/DeleteAvatarController.php +++ b/framework/core/src/Api/Controller/DeleteAvatarController.php @@ -19,28 +19,14 @@ use Tobscure\JsonApi\Document; class DeleteAvatarController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = UserSerializer::class; + public ?string $serializer = UserSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): mixed { return $this->bus->dispatch( new DeleteAvatar(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request)) diff --git a/framework/core/src/Api/Controller/DeleteDiscussionController.php b/framework/core/src/Api/Controller/DeleteDiscussionController.php index 685653f9a..99319e4bd 100644 --- a/framework/core/src/Api/Controller/DeleteDiscussionController.php +++ b/framework/core/src/Api/Controller/DeleteDiscussionController.php @@ -17,23 +17,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeleteDiscussionController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/DeleteFaviconController.php b/framework/core/src/Api/Controller/DeleteFaviconController.php index 4afd9324d..3c7374d4b 100644 --- a/framework/core/src/Api/Controller/DeleteFaviconController.php +++ b/framework/core/src/Api/Controller/DeleteFaviconController.php @@ -13,35 +13,20 @@ use Flarum\Http\RequestUtil; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Filesystem; -use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ServerRequestInterface; class DeleteFaviconController extends AbstractDeleteController { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; + protected Filesystem $uploadDir; - /** - * @var Filesystem - */ - protected $uploadDir; - - /** - * @param SettingsRepositoryInterface $settings - * @param Factory $filesystemFactory - */ - public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings, + Factory $filesystemFactory + ) { $this->uploadDir = $filesystemFactory->disk('flarum-assets'); } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { RequestUtil::getActor($request)->assertAdmin(); @@ -52,7 +37,5 @@ class DeleteFaviconController extends AbstractDeleteController if ($this->uploadDir->exists($path)) { $this->uploadDir->delete($path); } - - return new EmptyResponse(204); } } diff --git a/framework/core/src/Api/Controller/DeleteGroupController.php b/framework/core/src/Api/Controller/DeleteGroupController.php index a942c3987..4acc0afea 100644 --- a/framework/core/src/Api/Controller/DeleteGroupController.php +++ b/framework/core/src/Api/Controller/DeleteGroupController.php @@ -17,23 +17,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeleteGroupController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new DeleteGroup(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request)) diff --git a/framework/core/src/Api/Controller/DeleteLogoController.php b/framework/core/src/Api/Controller/DeleteLogoController.php index 121698c6d..8485f3219 100644 --- a/framework/core/src/Api/Controller/DeleteLogoController.php +++ b/framework/core/src/Api/Controller/DeleteLogoController.php @@ -13,35 +13,20 @@ use Flarum\Http\RequestUtil; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Filesystem; -use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ServerRequestInterface; class DeleteLogoController extends AbstractDeleteController { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; + protected Filesystem $uploadDir; - /** - * @var Filesystem - */ - protected $uploadDir; - - /** - * @param SettingsRepositoryInterface $settings - * @param Factory $filesystemFactory - */ - public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings, + Factory $filesystemFactory + ) { $this->uploadDir = $filesystemFactory->disk('flarum-assets'); } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { RequestUtil::getActor($request)->assertAdmin(); @@ -52,7 +37,5 @@ class DeleteLogoController extends AbstractDeleteController if ($this->uploadDir->exists($path)) { $this->uploadDir->delete($path); } - - return new EmptyResponse(204); } } diff --git a/framework/core/src/Api/Controller/DeletePostController.php b/framework/core/src/Api/Controller/DeletePostController.php index 4e5416074..3e61c55f8 100644 --- a/framework/core/src/Api/Controller/DeletePostController.php +++ b/framework/core/src/Api/Controller/DeletePostController.php @@ -17,23 +17,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeletePostController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new DeletePost(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request)) diff --git a/framework/core/src/Api/Controller/DeleteUserController.php b/framework/core/src/Api/Controller/DeleteUserController.php index f79962d0e..07329b6bc 100644 --- a/framework/core/src/Api/Controller/DeleteUserController.php +++ b/framework/core/src/Api/Controller/DeleteUserController.php @@ -17,23 +17,12 @@ use Psr\Http\Message\ServerRequestInterface; class DeleteUserController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new DeleteUser(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request)) diff --git a/framework/core/src/Api/Controller/ForgotPasswordController.php b/framework/core/src/Api/Controller/ForgotPasswordController.php index 1bb741fa2..00a2fcf85 100644 --- a/framework/core/src/Api/Controller/ForgotPasswordController.php +++ b/framework/core/src/Api/Controller/ForgotPasswordController.php @@ -20,25 +20,12 @@ use Psr\Http\Server\RequestHandlerInterface; class ForgotPasswordController implements RequestHandlerInterface { - /** - * @var Queue - */ - protected $queue; - - /** - * @var ForgotPasswordValidator - */ - protected $validator; - - public function __construct(Queue $queue, ForgotPasswordValidator $validator) - { - $this->queue = $queue; - $this->validator = $validator; + public function __construct( + protected Queue $queue, + protected ForgotPasswordValidator $validator + ) { } - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { $params = $request->getParsedBody(); diff --git a/framework/core/src/Api/Controller/ListAccessTokensController.php b/framework/core/src/Api/Controller/ListAccessTokensController.php index bad5b5135..5b6b425ba 100644 --- a/framework/core/src/Api/Controller/ListAccessTokensController.php +++ b/framework/core/src/Api/Controller/ListAccessTokensController.php @@ -19,28 +19,15 @@ use Tobscure\JsonApi\Document; class ListAccessTokensController extends AbstractListController { - public $serializer = AccessTokenSerializer::class; + public ?string $serializer = AccessTokenSerializer::class; - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var AccessTokenFilterer - */ - protected $filterer; - - public function __construct(UrlGenerator $url, AccessTokenFilterer $filterer) - { - $this->url = $url; - $this->filterer = $filterer; + public function __construct( + protected UrlGenerator $url, + protected AccessTokenFilterer $filterer + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/ListDiscussionsController.php b/framework/core/src/Api/Controller/ListDiscussionsController.php index 7bfef5acd..ca34a1881 100644 --- a/framework/core/src/Api/Controller/ListDiscussionsController.php +++ b/framework/core/src/Api/Controller/ListDiscussionsController.php @@ -21,70 +21,32 @@ use Tobscure\JsonApi\Document; class ListDiscussionsController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = DiscussionSerializer::class; + public ?string $serializer = DiscussionSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'user', 'lastPostedUser', 'mostRelevantPost', 'mostRelevantPost.user' ]; - /** - * {@inheritdoc} - */ - public $optionalInclude = [ + public array $optionalInclude = [ 'firstPost', 'lastPost' ]; - /** - * {@inheritDoc} - */ - public $sort = ['lastPostedAt' => 'desc']; + public ?array $sort = ['lastPostedAt' => 'desc']; - /** - * {@inheritdoc} - */ - public $sortFields = ['lastPostedAt', 'commentCount', 'createdAt']; + public array $sortFields = ['lastPostedAt', 'commentCount', 'createdAt']; - /** - * @var DiscussionFilterer - */ - protected $filterer; - - /** - * @var DiscussionSearcher - */ - protected $searcher; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param DiscussionFilterer $filterer - * @param DiscussionSearcher $searcher - * @param UrlGenerator $url - */ - public function __construct(DiscussionFilterer $filterer, DiscussionSearcher $searcher, UrlGenerator $url) - { - $this->filterer = $filterer; - $this->searcher = $searcher; - $this->url = $url; + public function __construct( + protected DiscussionFilterer $filterer, + protected DiscussionSearcher $searcher, + protected UrlGenerator $url + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); $filters = $this->extractFilter($request); diff --git a/framework/core/src/Api/Controller/ListGroupsController.php b/framework/core/src/Api/Controller/ListGroupsController.php index 8128c0de8..df5c90467 100644 --- a/framework/core/src/Api/Controller/ListGroupsController.php +++ b/framework/core/src/Api/Controller/ListGroupsController.php @@ -19,47 +19,19 @@ use Tobscure\JsonApi\Document; class ListGroupsController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = GroupSerializer::class; + public ?string $serializer = GroupSerializer::class; - /** - * {@inheritdoc} - */ - public $sortFields = ['nameSingular', 'namePlural', 'isHidden']; + public array $sortFields = ['nameSingular', 'namePlural', 'isHidden']; - /** - * {@inheritdoc} - * - * @var int - */ - public $limit = -1; + public int $limit = -1; - /** - * @var GroupFilterer - */ - protected $filterer; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param GroupFilterer $filterer - * @param UrlGenerator $url - */ - public function __construct(GroupFilterer $filterer, UrlGenerator $url) - { - $this->filterer = $filterer; - $this->url = $url; + public function __construct( + protected GroupFilterer $filterer, + protected UrlGenerator $url + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/ListNotificationsController.php b/framework/core/src/Api/Controller/ListNotificationsController.php index 2ad3bb634..354478ca1 100644 --- a/framework/core/src/Api/Controller/ListNotificationsController.php +++ b/framework/core/src/Api/Controller/ListNotificationsController.php @@ -19,44 +19,21 @@ use Tobscure\JsonApi\Document; class ListNotificationsController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = NotificationSerializer::class; + public ?string $serializer = NotificationSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'fromUser', 'subject', 'subject.discussion' ]; - /** - * @var NotificationRepository - */ - protected $notifications; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param NotificationRepository $notifications - * @param UrlGenerator $url - */ - public function __construct(NotificationRepository $notifications, UrlGenerator $url) - { - $this->notifications = $notifications; - $this->url = $url; + public function __construct( + protected NotificationRepository $notifications, + protected UrlGenerator $url + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); @@ -103,7 +80,7 @@ class ListNotificationsController extends AbstractListController /** * @param \Flarum\Notification\Notification[] $notifications */ - private function loadSubjectDiscussions(array $notifications) + private function loadSubjectDiscussions(array $notifications): void { $ids = []; diff --git a/framework/core/src/Api/Controller/ListPostsController.php b/framework/core/src/Api/Controller/ListPostsController.php index ef12729c9..5a6a0cf1c 100644 --- a/framework/core/src/Api/Controller/ListPostsController.php +++ b/framework/core/src/Api/Controller/ListPostsController.php @@ -22,15 +22,9 @@ use Tobscure\JsonApi\Exception\InvalidParameterException; class ListPostsController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = PostSerializer::class; + public ?string $serializer = PostSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'user', 'user.groups', 'editedUser', @@ -38,42 +32,16 @@ class ListPostsController extends AbstractListController 'discussion' ]; - /** - * {@inheritdoc} - */ - public $sortFields = ['number', 'createdAt']; + public array $sortFields = ['number', 'createdAt']; - /** - * @var PostFilterer - */ - protected $filterer; - - /** - * @var PostRepository - */ - protected $posts; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param PostFilterer $filterer - * @param PostRepository $posts - * @param UrlGenerator $url - */ - public function __construct(PostFilterer $filterer, PostRepository $posts, UrlGenerator $url) - { - $this->filterer = $filterer; - $this->posts = $posts; - $this->url = $url; + public function __construct( + protected PostFilterer $filterer, + protected PostRepository $posts, + protected UrlGenerator $url + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); @@ -116,7 +84,7 @@ class ListPostsController extends AbstractListController /** * @link https://github.com/flarum/framework/pull/3506 */ - protected function extractSort(ServerRequestInterface $request) + protected function extractSort(ServerRequestInterface $request): ?array { $sort = []; @@ -127,10 +95,7 @@ class ListPostsController extends AbstractListController return $sort; } - /** - * {@inheritdoc} - */ - protected function extractOffset(ServerRequestInterface $request) + protected function extractOffset(ServerRequestInterface $request): int { $actor = RequestUtil::getActor($request); $queryParams = $request->getQueryParams(); diff --git a/framework/core/src/Api/Controller/ListUsersController.php b/framework/core/src/Api/Controller/ListUsersController.php index c48ca37dc..792635341 100644 --- a/framework/core/src/Api/Controller/ListUsersController.php +++ b/framework/core/src/Api/Controller/ListUsersController.php @@ -20,20 +20,11 @@ use Tobscure\JsonApi\Document; class ListUsersController extends AbstractListController { - /** - * {@inheritdoc} - */ - public $serializer = UserSerializer::class; + public ?string $serializer = UserSerializer::class; - /** - * {@inheritdoc} - */ - public $include = ['groups']; + public array $include = ['groups']; - /** - * {@inheritdoc} - */ - public $sortFields = [ + public array $sortFields = [ 'username', 'commentCount', 'discussionCount', @@ -41,37 +32,14 @@ class ListUsersController extends AbstractListController 'joinedAt' ]; - /** - * @var UserFilterer - */ - protected $filterer; - - /** - * @var UserSearcher - */ - protected $searcher; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param UserFilterer $filterer - * @param UserSearcher $searcher - * @param UrlGenerator $url - */ - public function __construct(UserFilterer $filterer, UserSearcher $searcher, UrlGenerator $url) - { - $this->filterer = $filterer; - $this->searcher = $searcher; - $this->url = $url; + public function __construct( + protected UserFilterer $filterer, + protected UserSearcher $searcher, + protected UrlGenerator $url + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/ReadAllNotificationsController.php b/framework/core/src/Api/Controller/ReadAllNotificationsController.php index 27c121fce..ca806a6be 100644 --- a/framework/core/src/Api/Controller/ReadAllNotificationsController.php +++ b/framework/core/src/Api/Controller/ReadAllNotificationsController.php @@ -16,23 +16,12 @@ use Psr\Http\Message\ServerRequestInterface; class ReadAllNotificationsController extends AbstractDeleteController { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $this->bus->dispatch( new ReadAllNotifications(RequestUtil::getActor($request)) diff --git a/framework/core/src/Api/Controller/SendConfirmationEmailController.php b/framework/core/src/Api/Controller/SendConfirmationEmailController.php index 4935abd77..dadde03a3 100644 --- a/framework/core/src/Api/Controller/SendConfirmationEmailController.php +++ b/framework/core/src/Api/Controller/SendConfirmationEmailController.php @@ -11,6 +11,7 @@ namespace Flarum\Api\Controller; use Flarum\Http\RequestUtil; use Flarum\Http\UrlGenerator; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\AccountActivationMailerTrait; use Flarum\User\Exception\PermissionDeniedException; @@ -20,49 +21,19 @@ use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use Symfony\Contracts\Translation\TranslatorInterface; class SendConfirmationEmailController implements RequestHandlerInterface { use AccountActivationMailerTrait; - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Queue - */ - protected $queue; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @param \Flarum\Settings\SettingsRepositoryInterface $settings - * @param Queue $queue - * @param UrlGenerator $url - * @param TranslatorInterface $translator - */ - public function __construct(SettingsRepositoryInterface $settings, Queue $queue, UrlGenerator $url, TranslatorInterface $translator) - { - $this->settings = $settings; - $this->queue = $queue; - $this->url = $url; - $this->translator = $translator; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected Queue $queue, + protected UrlGenerator $url, + protected TranslatorInterface $translator + ) { } - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { $id = Arr::get($request->getQueryParams(), 'id'); diff --git a/framework/core/src/Api/Controller/SendTestMailController.php b/framework/core/src/Api/Controller/SendTestMailController.php index a30c985e0..388510bb5 100644 --- a/framework/core/src/Api/Controller/SendTestMailController.php +++ b/framework/core/src/Api/Controller/SendTestMailController.php @@ -10,24 +10,20 @@ namespace Flarum\Api\Controller; use Flarum\Http\RequestUtil; +use Flarum\Locale\TranslatorInterface; use Illuminate\Contracts\Mail\Mailer; use Illuminate\Mail\Message; use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use Symfony\Contracts\Translation\TranslatorInterface; class SendTestMailController implements RequestHandlerInterface { - protected $mailer; - - protected $translator; - - public function __construct(Mailer $mailer, TranslatorInterface $translator) - { - $this->mailer = $mailer; - $this->translator = $translator; + public function __construct( + protected Mailer $mailer, + protected TranslatorInterface $translator + ) { } public function handle(ServerRequestInterface $request): ResponseInterface diff --git a/framework/core/src/Api/Controller/SetPermissionController.php b/framework/core/src/Api/Controller/SetPermissionController.php index 57b502eb2..533321637 100644 --- a/framework/core/src/Api/Controller/SetPermissionController.php +++ b/framework/core/src/Api/Controller/SetPermissionController.php @@ -19,9 +19,6 @@ use Psr\Http\Server\RequestHandlerInterface; class SetPermissionController implements RequestHandlerInterface { - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { RequestUtil::getActor($request)->assertAdmin(); diff --git a/framework/core/src/Api/Controller/SetSettingsController.php b/framework/core/src/Api/Controller/SetSettingsController.php index 6d0615c98..38c8b8ca4 100644 --- a/framework/core/src/Api/Controller/SetSettingsController.php +++ b/framework/core/src/Api/Controller/SetSettingsController.php @@ -20,28 +20,12 @@ use Psr\Http\Server\RequestHandlerInterface; class SetSettingsController implements RequestHandlerInterface { - /** - * @var \Flarum\Settings\SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Dispatcher - */ - protected $dispatcher; - - /** - * @param SettingsRepositoryInterface $settings - */ - public function __construct(SettingsRepositoryInterface $settings, Dispatcher $dispatcher) - { - $this->settings = $settings; - $this->dispatcher = $dispatcher; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected Dispatcher $dispatcher + ) { } - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { RequestUtil::getActor($request)->assertAdmin(); diff --git a/framework/core/src/Api/Controller/ShowDiscussionController.php b/framework/core/src/Api/Controller/ShowDiscussionController.php index 251254675..4fb894a81 100644 --- a/framework/core/src/Api/Controller/ShowDiscussionController.php +++ b/framework/core/src/Api/Controller/ShowDiscussionController.php @@ -14,8 +14,10 @@ use Flarum\Discussion\Discussion; use Flarum\Discussion\DiscussionRepository; use Flarum\Http\RequestUtil; use Flarum\Http\SlugManager; +use Flarum\Post\Post; use Flarum\Post\PostRepository; use Flarum\User\User; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Arr; use Illuminate\Support\Str; @@ -24,30 +26,9 @@ use Tobscure\JsonApi\Document; class ShowDiscussionController extends AbstractShowController { - /** - * @var \Flarum\Discussion\DiscussionRepository - */ - protected $discussions; + public ?string $serializer = DiscussionSerializer::class; - /** - * @var PostRepository - */ - protected $posts; - - /** - * @var SlugManager - */ - protected $slugManager; - - /** - * {@inheritdoc} - */ - public $serializer = DiscussionSerializer::class; - - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'user', 'posts', 'posts.discussion', @@ -57,32 +38,21 @@ class ShowDiscussionController extends AbstractShowController 'posts.hiddenUser' ]; - /** - * {@inheritdoc} - */ - public $optionalInclude = [ + public array $optionalInclude = [ 'user', 'lastPostedUser', 'firstPost', 'lastPost' ]; - /** - * @param \Flarum\Discussion\DiscussionRepository $discussions - * @param \Flarum\Post\PostRepository $posts - * @param \Flarum\Http\SlugManager $slugManager - */ - public function __construct(DiscussionRepository $discussions, PostRepository $posts, SlugManager $slugManager) - { - $this->discussions = $discussions; - $this->posts = $posts; - $this->slugManager = $slugManager; + public function __construct( + protected DiscussionRepository $discussions, + protected PostRepository $posts, + protected SlugManager $slugManager + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Discussion { $discussionId = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); @@ -108,12 +78,7 @@ class ShowDiscussionController extends AbstractShowController return $discussion; } - /** - * @param Discussion $discussion - * @param ServerRequestInterface $request - * @param array $include - */ - private function includePosts(Discussion $discussion, ServerRequestInterface $request, array $include) + private function includePosts(Discussion $discussion, ServerRequestInterface $request, array $include): void { $actor = RequestUtil::getActor($request); $limit = $this->extractLimit($request); @@ -124,15 +89,10 @@ class ShowDiscussionController extends AbstractShowController array_splice($allPosts, $offset, $limit, $loadedPosts); - $discussion->setRelation('posts', $allPosts); + $discussion->setRelation('posts', (new Post)->newCollection($allPosts)); } - /** - * @param Discussion $discussion - * @param User $actor - * @return array - */ - private function loadPostIds(Discussion $discussion, User $actor) + private function loadPostIds(Discussion $discussion, User $actor): array { return $discussion->posts()->whereVisibleTo($actor)->orderBy('number')->pluck('id')->all(); } @@ -151,13 +111,7 @@ class ShowDiscussionController extends AbstractShowController return $relationships; } - /** - * @param ServerRequestInterface $request - * @param Discussion$discussion - * @param int $limit - * @return int - */ - private function getPostsOffset(ServerRequestInterface $request, Discussion $discussion, $limit) + private function getPostsOffset(ServerRequestInterface $request, Discussion $discussion, int $limit): int { $queryParams = $request->getQueryParams(); $actor = RequestUtil::getActor($request); @@ -172,22 +126,16 @@ class ShowDiscussionController extends AbstractShowController return $offset; } - /** - * @param Discussion $discussion - * @param User $actor - * @param int $offset - * @param int $limit - * @param array $include - * @return mixed - */ - private function loadPosts($discussion, $actor, $offset, $limit, array $include, ServerRequestInterface $request) + private function loadPosts(Discussion $discussion, User $actor, int $offset, int $limit, array $include, ServerRequestInterface $request): array { + /** @var Builder $query */ $query = $discussion->posts()->whereVisibleTo($actor); $query->orderBy('number')->skip($offset)->take($limit); $posts = $query->get(); + /** @var Post $post */ foreach ($posts as $post) { $post->discussion = $discussion; } diff --git a/framework/core/src/Api/Controller/ShowExtensionReadmeController.php b/framework/core/src/Api/Controller/ShowExtensionReadmeController.php index 4a1e29823..034d6d0e3 100644 --- a/framework/core/src/Api/Controller/ShowExtensionReadmeController.php +++ b/framework/core/src/Api/Controller/ShowExtensionReadmeController.php @@ -10,6 +10,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\ExtensionReadmeSerializer; +use Flarum\Extension\Extension; use Flarum\Extension\ExtensionManager; use Flarum\Http\RequestUtil; use Illuminate\Support\Arr; @@ -18,25 +19,14 @@ use Tobscure\JsonApi\Document; class ShowExtensionReadmeController extends AbstractShowController { - /** - * @var ExtensionManager - */ - protected $extensions; + public ?string $serializer = ExtensionReadmeSerializer::class; - /** - * {@inheritdoc} - */ - public $serializer = ExtensionReadmeSerializer::class; - - public function __construct(ExtensionManager $extensions) - { - $this->extensions = $extensions; + public function __construct( + protected ExtensionManager $extensions + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): ?Extension { $extensionName = Arr::get($request->getQueryParams(), 'name'); diff --git a/framework/core/src/Api/Controller/ShowForumController.php b/framework/core/src/Api/Controller/ShowForumController.php index 9194fc895..f0c005513 100644 --- a/framework/core/src/Api/Controller/ShowForumController.php +++ b/framework/core/src/Api/Controller/ShowForumController.php @@ -17,20 +17,11 @@ use Tobscure\JsonApi\Document; class ShowForumController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = ForumSerializer::class; + public ?string $serializer = ForumSerializer::class; - /** - * {@inheritdoc} - */ - public $include = ['groups', 'actor', 'actor.groups']; + public array $include = ['groups', 'actor', 'actor.groups']; - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): array { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/ShowGroupController.php b/framework/core/src/Api/Controller/ShowGroupController.php index 9aee28f6d..6787be3cc 100644 --- a/framework/core/src/Api/Controller/ShowGroupController.php +++ b/framework/core/src/Api/Controller/ShowGroupController.php @@ -10,6 +10,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\GroupSerializer; +use Flarum\Group\Group; use Flarum\Group\GroupRepository; use Flarum\Http\RequestUtil; use Illuminate\Support\Arr; @@ -18,28 +19,14 @@ use Tobscure\JsonApi\Document; class ShowGroupController extends AbstractShowController { - /** - * @var GroupRepository - */ - protected $groups; + public ?string $serializer = GroupSerializer::class; - /** - * {@inheritdoc} - */ - public $serializer = GroupSerializer::class; - - /** - * @param \Flarum\Group\GroupRepository $groups - */ - public function __construct(GroupRepository $groups) - { - $this->groups = $groups; + public function __construct( + protected GroupRepository $groups + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Group { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/ShowMailSettingsController.php b/framework/core/src/Api/Controller/ShowMailSettingsController.php index b359137c3..90a4dc654 100644 --- a/framework/core/src/Api/Controller/ShowMailSettingsController.php +++ b/framework/core/src/Api/Controller/ShowMailSettingsController.php @@ -18,15 +18,9 @@ use Tobscure\JsonApi\Document; class ShowMailSettingsController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = MailSettingsSerializer::class; + public ?string $serializer = MailSettingsSerializer::class; - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): array { RequestUtil::getActor($request)->assertAdmin(); diff --git a/framework/core/src/Api/Controller/ShowPostController.php b/framework/core/src/Api/Controller/ShowPostController.php index 43d239b6b..25f7715b0 100644 --- a/framework/core/src/Api/Controller/ShowPostController.php +++ b/framework/core/src/Api/Controller/ShowPostController.php @@ -11,6 +11,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\PostSerializer; use Flarum\Http\RequestUtil; +use Flarum\Post\Post; use Flarum\Post\PostRepository; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Arr; @@ -19,15 +20,9 @@ use Tobscure\JsonApi\Document; class ShowPostController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = PostSerializer::class; + public ?string $serializer = PostSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'user', 'user.groups', 'editedUser', @@ -35,23 +30,12 @@ class ShowPostController extends AbstractShowController 'discussion' ]; - /** - * @var \Flarum\Post\PostRepository - */ - protected $posts; - - /** - * @param \Flarum\Post\PostRepository $posts - */ - public function __construct(PostRepository $posts) - { - $this->posts = $posts; + public function __construct( + protected PostRepository $posts + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Post { $post = $this->posts->findOrFail(Arr::get($request->getQueryParams(), 'id'), RequestUtil::getActor($request)); diff --git a/framework/core/src/Api/Controller/ShowUserController.php b/framework/core/src/Api/Controller/ShowUserController.php index 56506acf4..779d5e5f0 100644 --- a/framework/core/src/Api/Controller/ShowUserController.php +++ b/framework/core/src/Api/Controller/ShowUserController.php @@ -21,40 +21,17 @@ use Tobscure\JsonApi\Document; class ShowUserController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = UserSerializer::class; + public ?string $serializer = UserSerializer::class; - /** - * {@inheritdoc} - */ - public $include = ['groups']; + public array $include = ['groups']; - /** - * @var SlugManager - */ - protected $slugManager; - - /** - * @var UserRepository - */ - protected $users; - - /** - * @param SlugManager $slugManager - * @param UserRepository $users - */ - public function __construct(SlugManager $slugManager, UserRepository $users) - { - $this->slugManager = $slugManager; - $this->users = $users; + public function __construct( + protected SlugManager $slugManager, + protected UserRepository $users + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): User { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/TerminateAllOtherSessionsController.php b/framework/core/src/Api/Controller/TerminateAllOtherSessionsController.php index d2280da7a..559a73cdb 100644 --- a/framework/core/src/Api/Controller/TerminateAllOtherSessionsController.php +++ b/framework/core/src/Api/Controller/TerminateAllOtherSessionsController.php @@ -13,15 +13,11 @@ use Flarum\Http\RememberAccessToken; use Flarum\Http\RequestUtil; use Flarum\Http\SessionAccessToken; use Illuminate\Database\Eloquent\Builder; -use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ServerRequestInterface; class TerminateAllOtherSessionsController extends AbstractDeleteController { - /** - * {@inheritdoc} - */ - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { $actor = RequestUtil::getActor($request); @@ -39,7 +35,5 @@ class TerminateAllOtherSessionsController extends AbstractDeleteController ->where('type', SessionAccessToken::$type) ->orWhere('type', RememberAccessToken::$type); })->delete(); - - return new EmptyResponse(204); } } diff --git a/framework/core/src/Api/Controller/UninstallExtensionController.php b/framework/core/src/Api/Controller/UninstallExtensionController.php index bcaadf978..8f0cfb01e 100644 --- a/framework/core/src/Api/Controller/UninstallExtensionController.php +++ b/framework/core/src/Api/Controller/UninstallExtensionController.php @@ -16,20 +16,12 @@ use Psr\Http\Message\ServerRequestInterface; class UninstallExtensionController extends AbstractDeleteController { - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @param \Flarum\Extension\ExtensionManager $extensions - */ - public function __construct(ExtensionManager $extensions) - { - $this->extensions = $extensions; + public function __construct( + protected ExtensionManager $extensions + ) { } - protected function delete(ServerRequestInterface $request) + protected function delete(ServerRequestInterface $request): void { RequestUtil::getActor($request)->assertAdmin(); diff --git a/framework/core/src/Api/Controller/UpdateDiscussionController.php b/framework/core/src/Api/Controller/UpdateDiscussionController.php index 53c84a626..49305e980 100644 --- a/framework/core/src/Api/Controller/UpdateDiscussionController.php +++ b/framework/core/src/Api/Controller/UpdateDiscussionController.php @@ -12,6 +12,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\DiscussionSerializer; use Flarum\Discussion\Command\EditDiscussion; use Flarum\Discussion\Command\ReadDiscussion; +use Flarum\Discussion\Discussion; use Flarum\Http\RequestUtil; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Database\Eloquent\Collection; @@ -21,28 +22,14 @@ use Tobscure\JsonApi\Document; class UpdateDiscussionController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = DiscussionSerializer::class; + public ?string $serializer = DiscussionSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Discussion { $actor = RequestUtil::getActor($request); $discussionId = Arr::get($request->getQueryParams(), 'id'); diff --git a/framework/core/src/Api/Controller/UpdateExtensionController.php b/framework/core/src/Api/Controller/UpdateExtensionController.php index 0a9e4e59e..bd6765896 100644 --- a/framework/core/src/Api/Controller/UpdateExtensionController.php +++ b/framework/core/src/Api/Controller/UpdateExtensionController.php @@ -9,9 +9,9 @@ namespace Flarum\Api\Controller; -use Flarum\Bus\Dispatcher; use Flarum\Extension\Command\ToggleExtension; use Flarum\Http\RequestUtil; +use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ResponseInterface; @@ -20,19 +20,11 @@ use Psr\Http\Server\RequestHandlerInterface; class UpdateExtensionController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ public function handle(ServerRequestInterface $request): ResponseInterface { $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/UpdateGroupController.php b/framework/core/src/Api/Controller/UpdateGroupController.php index 968d642c4..aa59e8970 100644 --- a/framework/core/src/Api/Controller/UpdateGroupController.php +++ b/framework/core/src/Api/Controller/UpdateGroupController.php @@ -11,6 +11,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\GroupSerializer; use Flarum\Group\Command\EditGroup; +use Flarum\Group\Group; use Flarum\Http\RequestUtil; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; @@ -19,28 +20,14 @@ use Tobscure\JsonApi\Document; class UpdateGroupController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = GroupSerializer::class; + public ?string $serializer = GroupSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Group { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/UpdateNotificationController.php b/framework/core/src/Api/Controller/UpdateNotificationController.php index 38ef7e458..153f37ced 100644 --- a/framework/core/src/Api/Controller/UpdateNotificationController.php +++ b/framework/core/src/Api/Controller/UpdateNotificationController.php @@ -12,6 +12,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\NotificationSerializer; use Flarum\Http\RequestUtil; use Flarum\Notification\Command\ReadNotification; +use Flarum\Notification\Notification; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -19,28 +20,14 @@ use Tobscure\JsonApi\Document; class UpdateNotificationController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = NotificationSerializer::class; + public ?string $serializer = NotificationSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Notification { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/UpdatePostController.php b/framework/core/src/Api/Controller/UpdatePostController.php index c4db51e8b..0935836b9 100644 --- a/framework/core/src/Api/Controller/UpdatePostController.php +++ b/framework/core/src/Api/Controller/UpdatePostController.php @@ -12,6 +12,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\PostSerializer; use Flarum\Http\RequestUtil; use Flarum\Post\Command\EditPost; +use Flarum\Post\Post; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -19,36 +20,19 @@ use Tobscure\JsonApi\Document; class UpdatePostController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = PostSerializer::class; + public ?string $serializer = PostSerializer::class; - /** - * {@inheritdoc} - */ - public $include = [ + public array $include = [ 'editedUser', 'discussion' ]; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): Post { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/UpdateUserController.php b/framework/core/src/Api/Controller/UpdateUserController.php index 5d639c00d..1651880fc 100644 --- a/framework/core/src/Api/Controller/UpdateUserController.php +++ b/framework/core/src/Api/Controller/UpdateUserController.php @@ -14,6 +14,7 @@ use Flarum\Api\Serializer\UserSerializer; use Flarum\Http\RequestUtil; use Flarum\User\Command\EditUser; use Flarum\User\Exception\NotAuthenticatedException; +use Flarum\User\User; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -21,33 +22,16 @@ use Tobscure\JsonApi\Document; class UpdateUserController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = UserSerializer::class; + public ?string $serializer = UserSerializer::class; - /** - * {@inheritdoc} - */ - public $include = ['groups']; + public array $include = ['groups']; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): User { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/UploadAvatarController.php b/framework/core/src/Api/Controller/UploadAvatarController.php index a15b96458..015fc3e08 100644 --- a/framework/core/src/Api/Controller/UploadAvatarController.php +++ b/framework/core/src/Api/Controller/UploadAvatarController.php @@ -12,6 +12,7 @@ namespace Flarum\Api\Controller; use Flarum\Api\Serializer\UserSerializer; use Flarum\Http\RequestUtil; use Flarum\User\Command\UploadAvatar; +use Flarum\User\User; use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; @@ -19,28 +20,14 @@ use Tobscure\JsonApi\Document; class UploadAvatarController extends AbstractShowController { - /** - * {@inheritdoc} - */ - public $serializer = UserSerializer::class; + public ?string $serializer = UserSerializer::class; - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @param Dispatcher $bus - */ - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; + public function __construct( + protected Dispatcher $bus + ) { } - /** - * {@inheritdoc} - */ - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): User { $id = Arr::get($request->getQueryParams(), 'id'); $actor = RequestUtil::getActor($request); diff --git a/framework/core/src/Api/Controller/UploadFaviconController.php b/framework/core/src/Api/Controller/UploadFaviconController.php index 442a4c35a..8b2e71210 100644 --- a/framework/core/src/Api/Controller/UploadFaviconController.php +++ b/framework/core/src/Api/Controller/UploadFaviconController.php @@ -10,44 +10,27 @@ namespace Flarum\Api\Controller; use Flarum\Foundation\ValidationException; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Filesystem\Factory; use Intervention\Image\Image; use Intervention\Image\ImageManager; use Psr\Http\Message\UploadedFileInterface; -use Symfony\Contracts\Translation\TranslatorInterface; class UploadFaviconController extends UploadImageController { - protected $filePathSettingKey = 'favicon_path'; + protected string $filePathSettingKey = 'favicon_path'; + protected string $filenamePrefix = 'favicon'; - protected $filenamePrefix = 'favicon'; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var ImageManager - */ - protected $imageManager; - - /** - * @param SettingsRepositoryInterface $settings - * @param Factory $filesystemFactory - */ - public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory, TranslatorInterface $translator, ImageManager $imageManager) - { + public function __construct( + SettingsRepositoryInterface $settings, + Factory $filesystemFactory, + protected TranslatorInterface $translator, + protected ImageManager $imageManager + ) { parent::__construct($settings, $filesystemFactory); - - $this->translator = $translator; - $this->imageManager = $imageManager; } - /** - * {@inheritdoc} - */ protected function makeImage(UploadedFileInterface $file): Image { $this->fileExtension = pathinfo($file->getClientFilename(), PATHINFO_EXTENSION); diff --git a/framework/core/src/Api/Controller/UploadImageController.php b/framework/core/src/Api/Controller/UploadImageController.php index f00b70733..3e9e2e7d4 100644 --- a/framework/core/src/Api/Controller/UploadImageController.php +++ b/framework/core/src/Api/Controller/UploadImageController.php @@ -22,45 +22,19 @@ use Tobscure\JsonApi\Document; abstract class UploadImageController extends ShowForumController { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; + protected Filesystem $uploadDir; + protected string $fileExtension = 'png'; + protected string $filePathSettingKey = ''; + protected string $filenamePrefix = ''; - /** - * @var Filesystem - */ - protected $uploadDir; - - /** - * @var string - */ - protected $fileExtension = 'png'; - - /** - * @var string - */ - protected $filePathSettingKey = ''; - - /** - * @var string - */ - protected $filenamePrefix = ''; - - /** - * @param SettingsRepositoryInterface $settings - * @param Factory $filesystemFactory - */ - public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings, + Factory $filesystemFactory + ) { $this->uploadDir = $filesystemFactory->disk('flarum-assets'); } - /** - * {@inheritdoc} - */ - public function data(ServerRequestInterface $request, Document $document) + public function data(ServerRequestInterface $request, Document $document): array { RequestUtil::getActor($request)->assertAdmin(); @@ -81,9 +55,5 @@ abstract class UploadImageController extends ShowForumController return parent::data($request, $document); } - /** - * @param UploadedFileInterface $file - * @return Image - */ abstract protected function makeImage(UploadedFileInterface $file): Image; } diff --git a/framework/core/src/Api/Controller/UploadLogoController.php b/framework/core/src/Api/Controller/UploadLogoController.php index 683737755..c461ec460 100644 --- a/framework/core/src/Api/Controller/UploadLogoController.php +++ b/framework/core/src/Api/Controller/UploadLogoController.php @@ -17,25 +17,17 @@ use Psr\Http\Message\UploadedFileInterface; class UploadLogoController extends UploadImageController { - protected $filePathSettingKey = 'logo_path'; + protected string $filePathSettingKey = 'logo_path'; + protected string $filenamePrefix = 'logo'; - protected $filenamePrefix = 'logo'; - - /** - * @var ImageManager - */ - protected $imageManager; - - public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory, ImageManager $imageManager) - { + public function __construct( + SettingsRepositoryInterface $settings, + Factory $filesystemFactory, + protected ImageManager $imageManager + ) { parent::__construct($settings, $filesystemFactory); - - $this->imageManager = $imageManager; } - /** - * {@inheritdoc} - */ protected function makeImage(UploadedFileInterface $file): Image { $encodedImage = $this->imageManager->make($file->getStream()->getMetadata('uri'))->heighten(60, function ($constraint) { diff --git a/framework/core/src/Api/ForgotPasswordValidator.php b/framework/core/src/Api/ForgotPasswordValidator.php index 80f596c31..bd30837e5 100644 --- a/framework/core/src/Api/ForgotPasswordValidator.php +++ b/framework/core/src/Api/ForgotPasswordValidator.php @@ -9,21 +9,11 @@ namespace Flarum\Api; -/* - * This file is part of Flarum. - * - * For detailed copyright and license information, please view the - * LICENSE file that was distributed with this source code. - */ - use Flarum\Foundation\AbstractValidator; class ForgotPasswordValidator extends AbstractValidator { - /** - * {@inheritdoc} - */ - protected $rules = [ + protected array $rules = [ 'email' => ['required', 'email'] ]; } diff --git a/framework/core/src/Api/JsonApiResponse.php b/framework/core/src/Api/JsonApiResponse.php index 135202a93..b05a5dcb6 100644 --- a/framework/core/src/Api/JsonApiResponse.php +++ b/framework/core/src/Api/JsonApiResponse.php @@ -14,16 +14,10 @@ use Tobscure\JsonApi\Document; class JsonApiResponse extends JsonResponse { - /** - * {@inheritdoc} - */ public function __construct(Document $document, $status = 200, array $headers = [], $encodingOptions = 15) { $headers['content-type'] = 'application/vnd.api+json'; - // The call to jsonSerialize prevents rare issues with json_encode() failing with a - // syntax error even though Document implements the JsonSerializable interface. - // See https://github.com/flarum/core/issues/685 - parent::__construct($document->jsonSerialize(), $status, $headers, $encodingOptions); + parent::__construct($document, $status, $headers, $encodingOptions); } } diff --git a/framework/core/src/Api/Serializer/AbstractSerializer.php b/framework/core/src/Api/Serializer/AbstractSerializer.php index 69efef3eb..dce3a7c69 100644 --- a/framework/core/src/Api/Serializer/AbstractSerializer.php +++ b/framework/core/src/Api/Serializer/AbstractSerializer.php @@ -26,60 +26,37 @@ use Tobscure\JsonApi\SerializerInterface; abstract class AbstractSerializer extends BaseAbstractSerializer { - /** - * @var Request - */ - protected $request; - - /** - * @var User - */ - protected $actor; - - /** - * @var Container - */ - protected static $container; + protected Request $request; + protected User $actor; + protected static Container $container; /** * @var array */ - protected static $attributeMutators = []; + protected static array $attributeMutators = []; /** * @var array> */ - protected static $customRelations = []; + protected static array $customRelations = []; - /** - * @return Request - */ - public function getRequest() + public function getRequest(): Request { return $this->request; } - /** - * @param Request $request - */ - public function setRequest(Request $request) + public function setRequest(Request $request): void { $this->request = $request; $this->actor = RequestUtil::getActor($request); } - /** - * @return User - */ - public function getActor() + public function getActor(): User { return $this->actor; } - /** - * {@inheritdoc} - */ - public function getAttributes($model, array $fields = null) + public function getAttributes(mixed $model, array $fields = null): array { if (! is_object($model) && ! is_array($model)) { return []; @@ -103,26 +80,14 @@ abstract class AbstractSerializer extends BaseAbstractSerializer /** * Get the default set of serialized attributes for a model. - * - * @param object|array $model - * @return array */ - abstract protected function getDefaultAttributes($model); + abstract protected function getDefaultAttributes(object|array $model): array; - /** - * @param DateTime|null $date - * @return string|null - */ - public function formatDate(DateTime $date = null) + public function formatDate(DateTime $date = null): ?string { - if ($date) { - return $date->format(DateTime::RFC3339); - } + return $date?->format(DateTime::RFC3339); } - /** - * {@inheritdoc} - */ public function getRelationship($model, $name) { if ($relationship = $this->getCustomRelationship($model, $name)) { @@ -134,12 +99,8 @@ abstract class AbstractSerializer extends BaseAbstractSerializer /** * Get a custom relationship. - * - * @param mixed $model - * @param string $name - * @return Relationship|null */ - protected function getCustomRelationship($model, $name) + protected function getCustomRelationship(object|array $model, string $name): ?Relationship { foreach (array_merge([static::class], class_parents($this)) as $class) { $callback = Arr::get(static::$customRelations, "$class.$name"); @@ -156,42 +117,27 @@ abstract class AbstractSerializer extends BaseAbstractSerializer return $relationship; } } + + return null; } /** * Get a relationship builder for a has-one relationship. - * - * @param mixed $model - * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer - * @param string|Closure|null $relation - * @return Relationship */ - public function hasOne($model, $serializer, $relation = null) + public function hasOne(object|array $model, SerializerInterface|Closure|string $serializer, string $relation = null): ?Relationship { return $this->buildRelationship($model, $serializer, $relation); } /** * Get a relationship builder for a has-many relationship. - * - * @param mixed $model - * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer - * @param string|null $relation - * @return Relationship */ - public function hasMany($model, $serializer, $relation = null) + public function hasMany(object|array $model, SerializerInterface|Closure|string $serializer, string $relation = null): ?Relationship { return $this->buildRelationship($model, $serializer, $relation, true); } - /** - * @param mixed $model - * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer - * @param string|null $relation - * @param bool $many - * @return Relationship|null - */ - protected function buildRelationship($model, $serializer, $relation = null, $many = false) + protected function buildRelationship(object|array $model, SerializerInterface|Closure|string $serializer, string $relation = null, bool $many = false): ?Relationship { if (is_null($relation)) { list(, , $caller) = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 3); @@ -214,28 +160,21 @@ abstract class AbstractSerializer extends BaseAbstractSerializer return null; } - /** - * @param mixed $model - * @param string $relation - * @return mixed - */ - protected function getRelationshipData($model, $relation) + protected function getRelationshipData(object|array $model, string $relation): mixed { if (is_object($model)) { return $model->$relation; } elseif (is_array($model)) { return $model[$relation]; } + + return null; } /** - * @param mixed $serializer - * @param mixed $model - * @param mixed $data - * @return SerializerInterface * @throws InvalidArgumentException */ - protected function resolveSerializer($serializer, $model, $data) + protected function resolveSerializer(SerializerInterface|Closure|string $serializer, object|array $model, mixed $data): SerializerInterface { if ($serializer instanceof Closure) { $serializer = call_user_func($serializer, $model, $data); @@ -253,11 +192,7 @@ abstract class AbstractSerializer extends BaseAbstractSerializer return $serializer; } - /** - * @param string $class - * @return object - */ - protected function resolveSerializerClass($class) + protected function resolveSerializerClass(string $class): object { $serializer = static::$container->make($class); @@ -266,28 +201,20 @@ abstract class AbstractSerializer extends BaseAbstractSerializer return $serializer; } - /** - * @return Container - */ - public static function getContainer() + public static function getContainer(): Container { return static::$container; } /** - * @param Container $container - * * @internal */ - public static function setContainer(Container $container) + public static function setContainer(Container $container): void { static::$container = $container; } /** - * @param string $serializerClass - * @param callable $callback - * * @internal */ public static function addAttributeMutator(string $serializerClass, callable $callback): void @@ -300,10 +227,6 @@ abstract class AbstractSerializer extends BaseAbstractSerializer } /** - * @param string $serializerClass - * @param string $relation - * @param callable $callback - * * @internal */ public static function setRelationship(string $serializerClass, string $relation, callable $callback): void diff --git a/framework/core/src/Api/Serializer/AccessTokenSerializer.php b/framework/core/src/Api/Serializer/AccessTokenSerializer.php index 9caaf4ae1..383122096 100644 --- a/framework/core/src/Api/Serializer/AccessTokenSerializer.php +++ b/framework/core/src/Api/Serializer/AccessTokenSerializer.php @@ -10,48 +10,41 @@ namespace Flarum\Api\Serializer; use Flarum\Http\AccessToken; +use Flarum\Locale\TranslatorInterface; +use InvalidArgumentException; use Jenssegers\Agent\Agent; -use Symfony\Contracts\Translation\TranslatorInterface; class AccessTokenSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'access-tokens'; - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @param TranslatorInterface $translator - */ - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + protected TranslatorInterface $translator + ) { } - /** - * @param AccessToken $token - */ - protected function getDefaultAttributes($token) + protected function getDefaultAttributes(object|array $model): array { + if (! ($model instanceof AccessToken)) { + throw new InvalidArgumentException( + get_class($this).' can only serialize instances of '.AccessToken::class + ); + } + $session = $this->request->getAttribute('session'); $agent = new Agent(); - $agent->setUserAgent($token->last_user_agent); + $agent->setUserAgent($model->last_user_agent); $attributes = [ - 'token' => $token->token, - 'userId' => $token->user_id, - 'createdAt' => $this->formatDate($token->created_at), - 'lastActivityAt' => $this->formatDate($token->last_activity_at), - 'isCurrent' => $session && $session->get('access_token') === $token->token, - 'isSessionToken' => in_array($token->type, ['session', 'session_remember'], true), - 'title' => $token->title, - 'lastIpAddress' => $token->last_ip_address, + 'token' => $model->token, + 'userId' => $model->user_id, + 'createdAt' => $this->formatDate($model->created_at), + 'lastActivityAt' => $this->formatDate($model->last_activity_at), + 'isCurrent' => $session && $session->get('access_token') === $model->token, + 'isSessionToken' => in_array($model->type, ['session', 'session_remember'], true), + 'title' => $model->title, + 'lastIpAddress' => $model->last_ip_address, 'device' => $this->translator->trans('core.forum.security.browser_on_operating_system', [ 'browser' => $agent->browser(), 'os' => $agent->platform(), @@ -59,12 +52,12 @@ class AccessTokenSerializer extends AbstractSerializer ]; // Unset hidden attributes (like the token value on session tokens) - foreach ($token->getHidden() as $name) { + foreach ($model->getHidden() as $name) { unset($attributes[$name]); } // Hide the token value to non-actors no matter who they are. - if (isset($attributes['token']) && $this->getActor()->id !== $token->user_id) { + if (isset($attributes['token']) && $this->getActor()->id !== $model->user_id) { unset($attributes['token']); } diff --git a/framework/core/src/Api/Serializer/BasicDiscussionSerializer.php b/framework/core/src/Api/Serializer/BasicDiscussionSerializer.php index 64bbca752..c155e448b 100644 --- a/framework/core/src/Api/Serializer/BasicDiscussionSerializer.php +++ b/framework/core/src/Api/Serializer/BasicDiscussionSerializer.php @@ -12,96 +12,65 @@ namespace Flarum\Api\Serializer; use Flarum\Discussion\Discussion; use Flarum\Http\SlugManager; use InvalidArgumentException; +use Tobscure\JsonApi\Relationship; class BasicDiscussionSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'discussions'; - /** - * @var SlugManager - */ - protected $slugManager; - - public function __construct(SlugManager $slugManager) - { - $this->slugManager = $slugManager; + public function __construct( + protected SlugManager $slugManager + ) { } /** - * {@inheritdoc} - * - * @param Discussion $discussion * @throws InvalidArgumentException */ - protected function getDefaultAttributes($discussion) + protected function getDefaultAttributes(object|array $model): array { - if (! ($discussion instanceof Discussion)) { + if (! ($model instanceof Discussion)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.Discussion::class ); } return [ - 'title' => $discussion->title, - 'slug' => $this->slugManager->forResource(Discussion::class)->toSlug($discussion), + 'title' => $model->title, + 'slug' => $this->slugManager->forResource(Discussion::class)->toSlug($model), ]; } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function user($discussion) + protected function user($discussion): ?Relationship { return $this->hasOne($discussion, BasicUserSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function firstPost($discussion) + protected function firstPost($discussion): ?Relationship { return $this->hasOne($discussion, BasicPostSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function lastPostedUser($discussion) + protected function lastPostedUser($discussion): ?Relationship { return $this->hasOne($discussion, BasicUserSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function lastPost($discussion) + protected function lastPost($discussion): ?Relationship { return $this->hasOne($discussion, BasicPostSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function posts($discussion) + protected function posts($discussion): ?Relationship { return $this->hasMany($discussion, PostSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function mostRelevantPost($discussion) + protected function mostRelevantPost($discussion): ?Relationship { return $this->hasOne($discussion, PostSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function hiddenUser($discussion) + protected function hiddenUser($discussion): ?Relationship { return $this->hasOne($discussion, BasicUserSerializer::class); } diff --git a/framework/core/src/Api/Serializer/BasicPostSerializer.php b/framework/core/src/Api/Serializer/BasicPostSerializer.php index 55f04533a..c9aee3f0e 100644 --- a/framework/core/src/Api/Serializer/BasicPostSerializer.php +++ b/framework/core/src/Api/Serializer/BasicPostSerializer.php @@ -11,56 +11,42 @@ namespace Flarum\Api\Serializer; use Exception; use Flarum\Foundation\ErrorHandling\LogReporter; +use Flarum\Locale\TranslatorInterface; use Flarum\Post\CommentPost; use Flarum\Post\Post; use InvalidArgumentException; -use Symfony\Contracts\Translation\TranslatorInterface; +use Tobscure\JsonApi\Relationship; class BasicPostSerializer extends AbstractSerializer { - /** - * @var LogReporter - */ - protected $log; - - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(LogReporter $log, TranslatorInterface $translator) - { - $this->log = $log; - $this->translator = $translator; - } - /** - * {@inheritdoc} - */ protected $type = 'posts'; + public function __construct( + protected LogReporter $log, + protected TranslatorInterface $translator + ) { + } + /** - * {@inheritdoc} - * - * @param \Flarum\Post\Post $post * @throws InvalidArgumentException */ - protected function getDefaultAttributes($post) + protected function getDefaultAttributes(object|array $model): array { - if (! ($post instanceof Post)) { + if (! ($model instanceof Post)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.Post::class ); } $attributes = [ - 'number' => (int) $post->number, - 'createdAt' => $this->formatDate($post->created_at), - 'contentType' => $post->type + 'number' => (int) $model->number, + 'createdAt' => $this->formatDate($model->created_at), + 'contentType' => $model->type ]; - if ($post instanceof CommentPost) { + if ($model instanceof CommentPost) { try { - $attributes['contentHtml'] = $post->formatContent($this->request); + $attributes['contentHtml'] = $model->formatContent($this->request); $attributes['renderFailed'] = false; } catch (Exception $e) { $attributes['contentHtml'] = $this->translator->trans('core.lib.error.render_failed_message'); @@ -68,24 +54,18 @@ class BasicPostSerializer extends AbstractSerializer $attributes['renderFailed'] = true; } } else { - $attributes['content'] = $post->content; + $attributes['content'] = $model->content; } return $attributes; } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function user($post) + protected function user(Post $post): ?Relationship { return $this->hasOne($post, BasicUserSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function discussion($post) + protected function discussion(Post $post): ?Relationship { return $this->hasOne($post, BasicDiscussionSerializer::class); } diff --git a/framework/core/src/Api/Serializer/BasicUserSerializer.php b/framework/core/src/Api/Serializer/BasicUserSerializer.php index e024d338d..3f14efa13 100644 --- a/framework/core/src/Api/Serializer/BasicUserSerializer.php +++ b/framework/core/src/Api/Serializer/BasicUserSerializer.php @@ -12,50 +12,37 @@ namespace Flarum\Api\Serializer; use Flarum\Http\SlugManager; use Flarum\User\User; use InvalidArgumentException; +use Tobscure\JsonApi\Relationship; class BasicUserSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'users'; - /** - * @var SlugManager - */ - protected $slugManager; - - public function __construct(SlugManager $slugManager) - { - $this->slugManager = $slugManager; + public function __construct( + protected SlugManager $slugManager + ) { } /** - * {@inheritdoc} - * - * @param User $user * @throws InvalidArgumentException */ - protected function getDefaultAttributes($user) + protected function getDefaultAttributes(object|array $model): array { - if (! ($user instanceof User)) { + if (! ($model instanceof User)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.User::class ); } return [ - 'username' => $user->username, - 'displayName' => $user->display_name, - 'avatarUrl' => $user->avatar_url, - 'slug' => $this->slugManager->forResource(User::class)->toSlug($user) + 'username' => $model->username, + 'displayName' => $model->display_name, + 'avatarUrl' => $model->avatar_url, + 'slug' => $this->slugManager->forResource(User::class)->toSlug($model) ]; } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function groups($user) + protected function groups($user): Relationship { if ($this->getActor()->can('viewHiddenGroups')) { return $this->hasMany($user, GroupSerializer::class); diff --git a/framework/core/src/Api/Serializer/CurrentUserSerializer.php b/framework/core/src/Api/Serializer/CurrentUserSerializer.php index 24a9417a7..4328c15a7 100644 --- a/framework/core/src/Api/Serializer/CurrentUserSerializer.php +++ b/framework/core/src/Api/Serializer/CurrentUserSerializer.php @@ -9,24 +9,29 @@ namespace Flarum\Api\Serializer; +use Flarum\User\User; +use InvalidArgumentException; + class CurrentUserSerializer extends UserSerializer { - /** - * @param \Flarum\User\User $user - * @return array - */ - protected function getDefaultAttributes($user) + protected function getDefaultAttributes(object|array $model): array { - $attributes = parent::getDefaultAttributes($user); + if (! ($model instanceof User)) { + throw new InvalidArgumentException( + get_class($this).' can only serialize instances of '.User::class + ); + } + + $attributes = parent::getDefaultAttributes($model); $attributes += [ - 'isEmailConfirmed' => (bool) $user->is_email_confirmed, - 'email' => $user->email, - 'markedAllAsReadAt' => $this->formatDate($user->marked_all_as_read_at), - 'unreadNotificationCount' => (int) $user->getUnreadNotificationCount(), - 'newNotificationCount' => (int) $user->getNewNotificationCount(), - 'preferences' => (array) $user->preferences, - 'isAdmin' => $user->isAdmin(), + 'isEmailConfirmed' => (bool) $model->is_email_confirmed, + 'email' => $model->email, + 'markedAllAsReadAt' => $this->formatDate($model->marked_all_as_read_at), + 'unreadNotificationCount' => (int) $model->getUnreadNotificationCount(), + 'newNotificationCount' => (int) $model->getNewNotificationCount(), + 'preferences' => (array) $model->preferences, + 'isAdmin' => $model->isAdmin(), ]; return $attributes; diff --git a/framework/core/src/Api/Serializer/DiscussionSerializer.php b/framework/core/src/Api/Serializer/DiscussionSerializer.php index c12670d29..a4274e71d 100644 --- a/framework/core/src/Api/Serializer/DiscussionSerializer.php +++ b/framework/core/src/Api/Serializer/DiscussionSerializer.php @@ -14,30 +14,30 @@ use Flarum\Discussion\Discussion; class DiscussionSerializer extends BasicDiscussionSerializer { /** - * {@inheritdoc} + * @param Discussion $model */ - protected function getDefaultAttributes($discussion) + protected function getDefaultAttributes(object|array $model): array { - $attributes = parent::getDefaultAttributes($discussion) + [ - 'commentCount' => (int) $discussion->comment_count, - 'participantCount' => (int) $discussion->participant_count, - 'createdAt' => $this->formatDate($discussion->created_at), - 'lastPostedAt' => $this->formatDate($discussion->last_posted_at), - 'lastPostNumber' => (int) $discussion->last_post_number, - 'canReply' => $this->actor->can('reply', $discussion), - 'canRename' => $this->actor->can('rename', $discussion), - 'canDelete' => $this->actor->can('delete', $discussion), - 'canHide' => $this->actor->can('hide', $discussion) + $attributes = parent::getDefaultAttributes($model) + [ + 'commentCount' => (int) $model->comment_count, + 'participantCount' => (int) $model->participant_count, + 'createdAt' => $this->formatDate($model->created_at), + 'lastPostedAt' => $this->formatDate($model->last_posted_at), + 'lastPostNumber' => (int) $model->last_post_number, + 'canReply' => $this->actor->can('reply', $model), + 'canRename' => $this->actor->can('rename', $model), + 'canDelete' => $this->actor->can('delete', $model), + 'canHide' => $this->actor->can('hide', $model) ]; - if ($discussion->hidden_at) { + if ($model->hidden_at) { $attributes['isHidden'] = true; - $attributes['hiddenAt'] = $this->formatDate($discussion->hidden_at); + $attributes['hiddenAt'] = $this->formatDate($model->hidden_at); } Discussion::setStateUser($this->actor); - if ($state = $discussion->state) { + if ($state = $model->state) { $attributes += [ 'lastReadAt' => $this->formatDate($state->last_read_at), 'lastReadPostNumber' => (int) $state->last_read_post_number diff --git a/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php b/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php index 7f40eebef..4396cd045 100644 --- a/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php +++ b/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php @@ -9,19 +9,18 @@ namespace Flarum\Api\Serializer; +use Flarum\Extension\Extension; + class ExtensionReadmeSerializer extends AbstractSerializer { /** - * @param \Flarum\Extension\Extension $extension - * @return array + * @param Extension $model */ - protected function getDefaultAttributes($extension) + protected function getDefaultAttributes(object|array $model): array { - $attributes = [ - 'content' => $extension->getReadme() + return [ + 'content' => $model->getReadme() ]; - - return $attributes; } public function getId($extension) diff --git a/framework/core/src/Api/Serializer/ForumSerializer.php b/framework/core/src/Api/Serializer/ForumSerializer.php index 3e40dd58e..afe0a744c 100644 --- a/framework/core/src/Api/Serializer/ForumSerializer.php +++ b/framework/core/src/Api/Serializer/ForumSerializer.php @@ -19,9 +19,6 @@ use Tobscure\JsonApi\Relationship; class ForumSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'forums'; /** @@ -58,18 +55,15 @@ class ForumSerializer extends AbstractSerializer $this->url = $url; } - /** - * {@inheritdoc} - */ public function getId($model) { return '1'; } /** - * {@inheritdoc} + * @param array $model */ - protected function getDefaultAttributes($model): array + protected function getDefaultAttributes(object|array $model): array { $attributes = [ 'title' => $this->settings->get('forum_title'), @@ -106,17 +100,11 @@ class ForumSerializer extends AbstractSerializer return $attributes; } - /** - * @return Relationship - */ - protected function groups($model): Relationship + protected function groups($model): ?Relationship { return $this->hasMany($model, GroupSerializer::class); } - /** - * @return null|string - */ protected function getLogoUrl(): ?string { $logoPath = $this->settings->get('logo_path'); @@ -124,9 +112,6 @@ class ForumSerializer extends AbstractSerializer return $logoPath ? $this->getAssetUrl($logoPath) : null; } - /** - * @return null|string - */ protected function getFaviconUrl(): ?string { $faviconPath = $this->settings->get('favicon_path'); @@ -139,9 +124,6 @@ class ForumSerializer extends AbstractSerializer return $this->assetsFilesystem->url($assetPath); } - /** - * @return Relationship|null - */ protected function actor($model): ?Relationship { return $this->hasOne($model, CurrentUserSerializer::class); diff --git a/framework/core/src/Api/Serializer/GroupSerializer.php b/framework/core/src/Api/Serializer/GroupSerializer.php index cac9cb578..86eeda86e 100644 --- a/framework/core/src/Api/Serializer/GroupSerializer.php +++ b/framework/core/src/Api/Serializer/GroupSerializer.php @@ -10,57 +10,39 @@ namespace Flarum\Api\Serializer; use Flarum\Group\Group; +use Flarum\Locale\TranslatorInterface; use InvalidArgumentException; -use Symfony\Contracts\Translation\TranslatorInterface; class GroupSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'groups'; - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @param TranslatorInterface $translator - */ - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + protected TranslatorInterface $translator + ) { } /** - * {@inheritdoc} - * - * @param Group $group * @throws InvalidArgumentException */ - protected function getDefaultAttributes($group) + protected function getDefaultAttributes(object|array $model): array { - if (! ($group instanceof Group)) { + if (! ($model instanceof Group)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.Group::class ); } return [ - 'nameSingular' => $this->translateGroupName($group->name_singular), - 'namePlural' => $this->translateGroupName($group->name_plural), - 'color' => $group->color, - 'icon' => $group->icon, - 'isHidden' => $group->is_hidden + 'nameSingular' => $this->translateGroupName($model->name_singular), + 'namePlural' => $this->translateGroupName($model->name_plural), + 'color' => $model->color, + 'icon' => $model->icon, + 'isHidden' => $model->is_hidden ]; } - /** - * @param string $name - * @return string - */ - private function translateGroupName($name) + private function translateGroupName(string $name): string { $translation = $this->translator->trans($key = 'core.group.'.strtolower($name)); diff --git a/framework/core/src/Api/Serializer/MailSettingsSerializer.php b/framework/core/src/Api/Serializer/MailSettingsSerializer.php index 20cf512fd..bff907e53 100644 --- a/framework/core/src/Api/Serializer/MailSettingsSerializer.php +++ b/framework/core/src/Api/Serializer/MailSettingsSerializer.php @@ -14,27 +14,21 @@ use InvalidArgumentException; class MailSettingsSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'mail-settings'; /** - * {@inheritdoc} - * - * @param array $settings * @throws InvalidArgumentException */ - protected function getDefaultAttributes($settings) + protected function getDefaultAttributes(object|array $model): array { return [ - 'fields' => array_map([$this, 'serializeDriver'], $settings['drivers']), - 'sending' => $settings['sending'], - 'errors' => $settings['errors'], + 'fields' => array_map([$this, 'serializeDriver'], $model['drivers']), + 'sending' => $model['sending'], + 'errors' => $model['errors'], ]; } - private function serializeDriver(DriverInterface $driver) + private function serializeDriver(DriverInterface $driver): array { return $driver->availableSettings(); } diff --git a/framework/core/src/Api/Serializer/NotificationSerializer.php b/framework/core/src/Api/Serializer/NotificationSerializer.php index 9a7bdfc8a..0c6ee7e51 100644 --- a/framework/core/src/Api/Serializer/NotificationSerializer.php +++ b/framework/core/src/Api/Serializer/NotificationSerializer.php @@ -11,78 +11,55 @@ namespace Flarum\Api\Serializer; use Flarum\Notification\Notification; use InvalidArgumentException; +use Tobscure\JsonApi\Relationship; class NotificationSerializer extends AbstractSerializer { - /** - * {@inheritdoc} - */ protected $type = 'notifications'; /** * A map of notification types (key) to the serializer that should be used * to output the notification's subject (value). - * - * @var array */ - protected static $subjectSerializers = []; + protected static array $subjectSerializers = []; /** - * {@inheritdoc} - * - * @param \Flarum\Notification\Notification $notification * @throws InvalidArgumentException */ - protected function getDefaultAttributes($notification) + protected function getDefaultAttributes(object|array $model): array { - if (! ($notification instanceof Notification)) { + if (! ($model instanceof Notification)) { throw new InvalidArgumentException( get_class($this).' can only serialize instances of '.Notification::class ); } return [ - 'contentType' => $notification->type, - 'content' => $notification->data, - 'createdAt' => $this->formatDate($notification->created_at), - 'isRead' => (bool) $notification->read_at + 'contentType' => $model->type, + 'content' => $model->data, + 'createdAt' => $this->formatDate($model->created_at), + 'isRead' => (bool) $model->read_at ]; } - /** - * @param Notification $notification - * @return \Tobscure\JsonApi\Relationship - */ - protected function user($notification) + protected function user(Notification $notification): ?Relationship { return $this->hasOne($notification, BasicUserSerializer::class); } - /** - * @param Notification $notification - * @return \Tobscure\JsonApi\Relationship - */ - protected function fromUser($notification) + protected function fromUser(Notification $notification): ?Relationship { return $this->hasOne($notification, BasicUserSerializer::class); } - /** - * @param Notification $notification - * @return \Tobscure\JsonApi\Relationship - */ - protected function subject($notification) + protected function subject(Notification $notification): ?Relationship { - return $this->hasOne($notification, function ($notification) { + return $this->hasOne($notification, function (Notification $notification) { return static::$subjectSerializers[$notification->type]; }); } - /** - * @param $type - * @param $serializer - */ - public static function setSubjectSerializer($type, $serializer) + public static function setSubjectSerializer(string $type, string $serializer): void { static::$subjectSerializers[$type] = $serializer; } diff --git a/framework/core/src/Api/Serializer/PostSerializer.php b/framework/core/src/Api/Serializer/PostSerializer.php index 325c2d781..79a80d5c4 100644 --- a/framework/core/src/Api/Serializer/PostSerializer.php +++ b/framework/core/src/Api/Serializer/PostSerializer.php @@ -10,77 +10,67 @@ namespace Flarum\Api\Serializer; use Flarum\Post\CommentPost; +use Flarum\Post\Post; +use Tobscure\JsonApi\Relationship; class PostSerializer extends BasicPostSerializer { /** - * {@inheritdoc} + * @param Post $model */ - protected function getDefaultAttributes($post) + protected function getDefaultAttributes(object|array $model): array { - $attributes = parent::getDefaultAttributes($post); + $attributes = parent::getDefaultAttributes($model); unset($attributes['content']); - $canEdit = $this->actor->can('edit', $post); + $canEdit = $this->actor->can('edit', $model); - if ($post instanceof CommentPost) { + if ($model instanceof CommentPost) { if ($canEdit) { - $attributes['content'] = $post->content; + $attributes['content'] = $model->content; } - if ($this->actor->can('viewIps', $post)) { - $attributes['ipAddress'] = $post->ip_address; + if ($this->actor->can('viewIps', $model)) { + $attributes['ipAddress'] = $model->ip_address; } } else { - $attributes['content'] = $post->content; + $attributes['content'] = $model->content; } - if ($post->edited_at) { - $attributes['editedAt'] = $this->formatDate($post->edited_at); + if ($model->edited_at) { + $attributes['editedAt'] = $this->formatDate($model->edited_at); } - if ($post->hidden_at) { + if ($model->hidden_at) { $attributes['isHidden'] = true; - $attributes['hiddenAt'] = $this->formatDate($post->hidden_at); + $attributes['hiddenAt'] = $this->formatDate($model->hidden_at); } $attributes += [ 'canEdit' => $canEdit, - 'canDelete' => $this->actor->can('delete', $post), - 'canHide' => $this->actor->can('hide', $post) + 'canDelete' => $this->actor->can('delete', $model), + 'canHide' => $this->actor->can('hide', $model) ]; return $attributes; } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function user($post) + protected function user(Post $post): ?Relationship { return $this->hasOne($post, UserSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function discussion($post) + protected function discussion(Post $post): ?Relationship { return $this->hasOne($post, BasicDiscussionSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function editedUser($post) + protected function editedUser(Post $post): ?Relationship { return $this->hasOne($post, BasicUserSerializer::class); } - /** - * @return \Tobscure\JsonApi\Relationship - */ - protected function hiddenUser($post) + protected function hiddenUser(Post $post): ?Relationship { return $this->hasOne($post, BasicUserSerializer::class); } diff --git a/framework/core/src/Api/Serializer/UserSerializer.php b/framework/core/src/Api/Serializer/UserSerializer.php index 9f9d3fc97..353514d4d 100644 --- a/framework/core/src/Api/Serializer/UserSerializer.php +++ b/framework/core/src/Api/Serializer/UserSerializer.php @@ -9,36 +9,37 @@ namespace Flarum\Api\Serializer; +use Flarum\User\User; + class UserSerializer extends BasicUserSerializer { /** - * @param \Flarum\User\User $user - * @return array + * @param User $model */ - protected function getDefaultAttributes($user) + protected function getDefaultAttributes(object|array $model): array { - $attributes = parent::getDefaultAttributes($user); + $attributes = parent::getDefaultAttributes($model); $attributes += [ - 'joinTime' => $this->formatDate($user->joined_at), - 'discussionCount' => (int) $user->discussion_count, - 'commentCount' => (int) $user->comment_count, - 'canEdit' => $this->actor->can('edit', $user), - 'canEditCredentials' => $this->actor->can('editCredentials', $user), - 'canEditGroups' => $this->actor->can('editGroups', $user), - 'canDelete' => $this->actor->can('delete', $user), + 'joinTime' => $this->formatDate($model->joined_at), + 'discussionCount' => (int) $model->discussion_count, + 'commentCount' => (int) $model->comment_count, + 'canEdit' => $this->actor->can('edit', $model), + 'canEditCredentials' => $this->actor->can('editCredentials', $model), + 'canEditGroups' => $this->actor->can('editGroups', $model), + 'canDelete' => $this->actor->can('delete', $model), ]; - if ($user->getPreference('discloseOnline') || $this->actor->can('viewLastSeenAt', $user)) { + if ($model->getPreference('discloseOnline') || $this->actor->can('viewLastSeenAt', $model)) { $attributes += [ - 'lastSeenAt' => $this->formatDate($user->last_seen_at) + 'lastSeenAt' => $this->formatDate($model->last_seen_at) ]; } - if ($attributes['canEditCredentials'] || $this->actor->id === $user->id) { + if ($attributes['canEditCredentials'] || $this->actor->id === $model->id) { $attributes += [ - 'isEmailConfirmed' => (bool) $user->is_email_confirmed, - 'email' => $user->email + 'isEmailConfirmed' => (bool) $model->is_email_confirmed, + 'email' => $model->email ]; } diff --git a/framework/core/src/Bus/BusServiceProvider.php b/framework/core/src/Bus/BusServiceProvider.php index d3455f7bc..86a69ae77 100644 --- a/framework/core/src/Bus/BusServiceProvider.php +++ b/framework/core/src/Bus/BusServiceProvider.php @@ -18,7 +18,7 @@ use Illuminate\Contracts\Queue\Factory as QueueFactoryContract; class BusServiceProvider extends AbstractServiceProvider { - public function register() + public function register(): void { $this->container->bind(BaseDispatcher::class, function (Container $container) { return new Dispatcher($container, function ($connection = null) use ($container) { diff --git a/framework/core/src/Console/AbstractCommand.php b/framework/core/src/Console/AbstractCommand.php index 902ccc3ea..4e758185d 100644 --- a/framework/core/src/Console/AbstractCommand.php +++ b/framework/core/src/Console/AbstractCommand.php @@ -16,20 +16,10 @@ use Symfony\Component\Console\Output\OutputInterface; abstract class AbstractCommand extends Command { - /** - * @var InputInterface - */ - protected $input; + protected InputInterface $input; + protected OutputInterface $output; - /** - * @var OutputInterface - */ - protected $output; - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->input = $input; $this->output = $output; @@ -37,40 +27,23 @@ abstract class AbstractCommand extends Command return $this->fire() ?: 0; } - /** - * Fire the command. - */ - abstract protected function fire(); + abstract protected function fire(): int; - /** - * Did the user pass the given option? - * - * @param string $name - * @return bool - */ - protected function hasOption($name) + protected function hasOption(string $name): bool { return $this->input->hasOption($name); } - /** - * Send an info message to the user. - * - * @param string $message - */ - protected function info($message) + protected function info(string $message): void { $this->output->writeln("$message"); } /** * Send an error or warning message to the user. - * * If possible, this will send the message via STDERR. - * - * @param string $message */ - protected function error($message) + protected function error(string $message): void { if ($this->output instanceof ConsoleOutputInterface) { $this->output->getErrorOutput()->writeln("$message"); diff --git a/framework/core/src/Console/Cache/Factory.php b/framework/core/src/Console/Cache/Factory.php index e6ef1c391..446b973be 100644 --- a/framework/core/src/Console/Cache/Factory.php +++ b/framework/core/src/Console/Cache/Factory.php @@ -15,23 +15,12 @@ use Illuminate\Contracts\Container\Container; class Factory implements FactoryContract { - /** - * @var Container - */ - private $container; - - public function __construct(Container $container) - { - $this->container = $container; + public function __construct( + protected Container $container + ) { } - /** - * Get a cache store instance by name. - * - * @param string|null $name - * @return Repository - */ - public function store($name = null) + public function store($name = null): Repository { return $this->container['cache.store']; } diff --git a/framework/core/src/Console/ConsoleServiceProvider.php b/framework/core/src/Console/ConsoleServiceProvider.php index d026b71fc..09ef2e366 100644 --- a/framework/core/src/Console/ConsoleServiceProvider.php +++ b/framework/core/src/Console/ConsoleServiceProvider.php @@ -28,10 +28,7 @@ use Illuminate\Contracts\Container\Container; class ConsoleServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { // Used by Laravel to proxy artisan commands to its binary. // Flarum uses a similar binary, but it's called flarum. @@ -76,10 +73,7 @@ class ConsoleServiceProvider extends AbstractServiceProvider }); } - /** - * {@inheritDoc} - */ - public function boot(Container $container) + public function boot(Container $container): void { $schedule = $container->make(LaravelSchedule::class); diff --git a/framework/core/src/Console/Schedule.php b/framework/core/src/Console/Schedule.php index e59e57169..858dc6a44 100644 --- a/framework/core/src/Console/Schedule.php +++ b/framework/core/src/Console/Schedule.php @@ -15,15 +15,14 @@ use Illuminate\Support\Collection; class Schedule extends LaravelSchedule { - public function dueEvents($container) + public function dueEvents($app) { - return (new Collection($this->events))->filter->isDue(new class($container) { - /** @var Config */ - protected $config; + return (new Collection($this->events))->filter->isDue(new class($app) { + protected Config $config; - public function __construct($container) + public function __construct($app) { - $this->config = $container->make(Config::class); + $this->config = $app->make(Config::class); } public function isDownForMaintenance(): bool diff --git a/framework/core/src/Console/Server.php b/framework/core/src/Console/Server.php index 98ef6b951..4c90d04a2 100644 --- a/framework/core/src/Console/Server.php +++ b/framework/core/src/Console/Server.php @@ -20,14 +20,12 @@ use Symfony\Component\EventDispatcher\EventDispatcher; class Server { - private $site; - - public function __construct(SiteInterface $site) - { - $this->site = $site; + public function __construct( + private readonly SiteInterface $site + ) { } - public function listen() + public function listen(): never { $app = $this->site->bootApp(); @@ -42,7 +40,7 @@ class Server exit($console->run()); } - private function handleErrors(Application $console) + private function handleErrors(Application $console): void { $dispatcher = new EventDispatcher(); diff --git a/framework/core/src/Database/AbstractModel.php b/framework/core/src/Database/AbstractModel.php index f1b69f30d..7a4679d75 100644 --- a/framework/core/src/Database/AbstractModel.php +++ b/framework/core/src/Database/AbstractModel.php @@ -22,8 +22,6 @@ use LogicException; * Adds the ability for custom relations to be added to a model during runtime. * These relations behave in the same way that you would expect; they can be * queried, eager loaded, and accessed as an attribute. - * - * @property-read int|null $id */ abstract class AbstractModel extends Eloquent { @@ -39,41 +37,37 @@ abstract class AbstractModel extends Eloquent * * @var callable[] */ - protected $afterSaveCallbacks = []; + protected array $afterSaveCallbacks = []; /** * An array of callbacks to be run once after the model is deleted. * * @var callable[] */ - protected $afterDeleteCallbacks = []; + protected array $afterDeleteCallbacks = []; /** * @internal */ - public static $customRelations = []; + public static array $customRelations = []; /** * @internal */ - public static $customCasts = []; + public static array $customCasts = []; /** * @internal */ - public static $defaults = []; + public static array $defaults = []; /** * An alias for the table name, used in queries. * - * @var string|null * @internal */ - protected $tableAlias = null; + protected ?string $tableAlias = null; - /** - * {@inheritdoc} - */ public static function boot() { parent::boot(); @@ -91,9 +85,6 @@ abstract class AbstractModel extends Eloquent }); } - /** - * {@inheritdoc} - */ public function __construct(array $attributes = []) { $this->attributes = []; @@ -109,10 +100,7 @@ abstract class AbstractModel extends Eloquent parent::__construct($attributes); } - /** - * {@inheritdoc} - */ - public function getCasts() + public function getCasts(): array { $casts = parent::getCasts(); @@ -126,9 +114,6 @@ abstract class AbstractModel extends Eloquent /** * Get an attribute from the model. If nothing is found, attempt to load * a custom relation method with this key. - * - * @param string $key - * @return mixed */ public function getAttribute($key) { @@ -148,42 +133,37 @@ abstract class AbstractModel extends Eloquent return $this->relations[$key] = $relation->getResults(); } + + return null; } /** * Get a custom relation object. - * - * @param string $name - * @return mixed */ - protected function getCustomRelation($name) + protected function getCustomRelation(string $name): mixed { foreach (array_merge([static::class], class_parents($this)) as $class) { - $relation = Arr::get(static::$customRelations, $class.".$name", null); + $relation = Arr::get(static::$customRelations, $class.".$name"); if (! is_null($relation)) { return $relation($this); } } + + return null; } /** * Register a callback to be run once after the model is saved. - * - * @param callable $callback - * @return void */ - public function afterSave($callback) + public function afterSave(callable $callback): void { $this->afterSaveCallbacks[] = $callback; } /** * Register a callback to be run once after the model is deleted. - * - * @param callable $callback - * @return void */ - public function afterDelete($callback) + public function afterDelete(callable $callback): void { $this->afterDeleteCallbacks[] = $callback; } @@ -191,7 +171,7 @@ abstract class AbstractModel extends Eloquent /** * @return callable[] */ - public function releaseAfterSaveCallbacks() + public function releaseAfterSaveCallbacks(): array { $callbacks = $this->afterSaveCallbacks; @@ -203,7 +183,7 @@ abstract class AbstractModel extends Eloquent /** * @return callable[] */ - public function releaseAfterDeleteCallbacks() + public function releaseAfterDeleteCallbacks(): array { $callbacks = $this->afterDeleteCallbacks; @@ -212,16 +192,13 @@ abstract class AbstractModel extends Eloquent return $callbacks; } - /** - * {@inheritdoc} - */ - public function __call($method, $arguments) + public function __call($method, $parameters) { if ($relation = $this->getCustomRelation($method)) { return $relation; } - return parent::__call($method, $arguments); + return parent::__call($method, $parameters); } public function newModelQuery() @@ -244,7 +221,7 @@ abstract class AbstractModel extends Eloquent return ($this->tableAlias ?? $this->getTable()).'.'.$column; } - public function withTableAlias(callable $callback) + public function withTableAlias(callable $callback): mixed { static $aliasCount = 0; $this->tableAlias = 'flarum_reserved_'.++$aliasCount; @@ -256,10 +233,7 @@ abstract class AbstractModel extends Eloquent return $result; } - /** - * @param \Illuminate\Support\Collection|array $models - */ - public function newCollection($models = []) + public function newCollection(array $models = []): Collection { return new Collection($models); } diff --git a/framework/core/src/Database/Console/GenerateDumpCommand.php b/framework/core/src/Database/Console/GenerateDumpCommand.php index eb958792e..559f41ab2 100644 --- a/framework/core/src/Database/Console/GenerateDumpCommand.php +++ b/framework/core/src/Database/Console/GenerateDumpCommand.php @@ -13,48 +13,28 @@ use Flarum\Console\AbstractCommand; use Flarum\Foundation\Paths; use Illuminate\Database\Connection; use Illuminate\Database\MySqlConnection; +use Symfony\Component\Console\Command\Command; class GenerateDumpCommand extends AbstractCommand { - /** - * @var Connection - */ - protected $connection; - - /** - * @var Paths - */ - protected $paths; - - /** - * @param Connection $connection - * @param Paths $paths - */ - public function __construct(Connection $connection, Paths $paths) - { - $this->connection = $connection; - $this->paths = $paths; - + public function __construct( + protected Connection $connection, + protected Paths $paths + ) { parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('schema:dump') ->setDescription('Dump DB schema'); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $dumpPath = __DIR__.'/../../../migrations/install.dump'; - /** @var Connection&MySqlConnection */ + /** @var Connection&MySqlConnection $connection */ $connection = resolve('db.connection'); $connection @@ -76,7 +56,7 @@ class GenerateDumpCommand extends AbstractCommand $dump = file($dumpPath); foreach ($dump as $line) { foreach ($coreDataMigrations as $excludeMigrationId) { - if (strpos($line, $excludeMigrationId) !== false) { + if (str_contains($line, $excludeMigrationId)) { continue 2; } } @@ -84,5 +64,7 @@ class GenerateDumpCommand extends AbstractCommand } file_put_contents($dumpPath, implode($newDump)); + + return Command::SUCCESS; } } diff --git a/framework/core/src/Database/Console/MigrateCommand.php b/framework/core/src/Database/Console/MigrateCommand.php index 309b20f85..2390a24d2 100644 --- a/framework/core/src/Database/Console/MigrateCommand.php +++ b/framework/core/src/Database/Console/MigrateCommand.php @@ -18,54 +18,36 @@ use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Container\Container; use Illuminate\Database\ConnectionInterface; use Illuminate\Database\Schema\Builder; +use Symfony\Component\Console\Command\Command; class MigrateCommand extends AbstractCommand { - /** - * @var Container - */ - protected $container; - - /** - * @var Paths - */ - protected $paths; - - /** - * @param Container $container - * @param Paths $paths - */ - public function __construct(Container $container, Paths $paths) - { - $this->container = $container; - $this->paths = $paths; - + public function __construct( + protected Container $container, + protected Paths $paths + ) { parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('migrate') ->setDescription('Run outstanding migrations'); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $this->info('Migrating Flarum...'); $this->upgrade(); $this->info('DONE.'); + + return Command::SUCCESS; } - public function upgrade() + public function upgrade(): void { $this->container->bind(Builder::class, function ($container) { return $container->make(ConnectionInterface::class)->getSchemaBuilder(); diff --git a/framework/core/src/Database/Console/ResetCommand.php b/framework/core/src/Database/Console/ResetCommand.php index 4a04ae7a1..a9c039475 100644 --- a/framework/core/src/Database/Console/ResetCommand.php +++ b/framework/core/src/Database/Console/ResetCommand.php @@ -11,29 +11,18 @@ namespace Flarum\Database\Console; use Flarum\Console\AbstractCommand; use Flarum\Extension\ExtensionManager; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; class ResetCommand extends AbstractCommand { - /** - * @var ExtensionManager - */ - protected $manager; - - /** - * @param ExtensionManager $manager - */ - public function __construct(ExtensionManager $manager) - { - $this->manager = $manager; - + public function __construct( + protected ExtensionManager $manager + ) { parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('migrate:reset') @@ -46,17 +35,14 @@ class ResetCommand extends AbstractCommand ); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $extensionName = $this->input->getOption('extension'); if (! $extensionName) { $this->info('No extension specified. Please check command syntax.'); - return; + return Command::INVALID; } $extension = $this->manager->getExtension($extensionName); @@ -64,7 +50,7 @@ class ResetCommand extends AbstractCommand if (! $extension) { $this->info('Could not find extension '.$extensionName); - return; + return Command::FAILURE; } $this->info('Rolling back extension: '.$extensionName); @@ -73,5 +59,7 @@ class ResetCommand extends AbstractCommand $this->manager->migrateDown($extension); $this->info('DONE.'); + + return Command::SUCCESS; } } diff --git a/framework/core/src/Database/DatabaseMigrationRepository.php b/framework/core/src/Database/DatabaseMigrationRepository.php index 04f32e5d4..9bd1fba42 100644 --- a/framework/core/src/Database/DatabaseMigrationRepository.php +++ b/framework/core/src/Database/DatabaseMigrationRepository.php @@ -10,42 +10,17 @@ namespace Flarum\Database; use Illuminate\Database\ConnectionInterface; +use Illuminate\Database\Query\Builder; class DatabaseMigrationRepository implements MigrationRepositoryInterface { - /** - * The name of the database connection to use. - * - * @var ConnectionInterface - */ - protected $connection; - - /** - * The name of the migration table. - * - * @var string - */ - protected $table; - - /** - * Create a new database migration repository instance. - * - * @param ConnectionInterface $connection - * @param string $table - */ - public function __construct(ConnectionInterface $connection, $table) - { - $this->connection = $connection; - $this->table = $table; + public function __construct( + protected ConnectionInterface $connection, + protected string $table + ) { } - /** - * Get the ran migrations. - * - * @param string $extension - * @return array - */ - public function getRan($extension = null) + public function getRan(?string $extension = null): array { return $this->table() ->where('extension', $extension) @@ -54,28 +29,14 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface ->toArray(); } - /** - * Log that a migration was run. - * - * @param string $file - * @param string $extension - * @return void - */ - public function log($file, $extension = null) + public function log(string $file, ?string $extension = null): void { $record = ['migration' => $file, 'extension' => $extension]; $this->table()->insert($record); } - /** - * Remove a migration from the log. - * - * @param string $file - * @param string $extension - * @return void - */ - public function delete($file, $extension = null) + public function delete(string $file, ?string $extension = null): void { $query = $this->table()->where('migration', $file); @@ -88,12 +49,7 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface $query->delete(); } - /** - * Determine if the migration repository exists. - * - * @return bool - */ - public function repositoryExists() + public function repositoryExists(): bool { $schema = $this->connection->getSchemaBuilder(); @@ -102,10 +58,8 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface /** * Get a query builder for the migration table. - * - * @return \Illuminate\Database\Query\Builder */ - protected function table() + protected function table(): Builder { return $this->connection->table($this->table); } diff --git a/framework/core/src/Database/DatabaseServiceProvider.php b/framework/core/src/Database/DatabaseServiceProvider.php index a23295a0a..dfae3d6ac 100644 --- a/framework/core/src/Database/DatabaseServiceProvider.php +++ b/framework/core/src/Database/DatabaseServiceProvider.php @@ -18,10 +18,7 @@ use Illuminate\Database\ConnectionResolverInterface; class DatabaseServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton(Manager::class, function (ContainerImplementation $container) { $manager = new Manager($container); @@ -66,7 +63,7 @@ class DatabaseServiceProvider extends AbstractServiceProvider }); } - public function boot(Container $container) + public function boot(Container $container): void { AbstractModel::setConnectionResolver($container->make(ConnectionResolverInterface::class)); AbstractModel::setEventDispatcher($container->make('events')); diff --git a/framework/core/src/Database/Eloquent/Collection.php b/framework/core/src/Database/Eloquent/Collection.php index fbdd67de7..6fc32a410 100644 --- a/framework/core/src/Database/Eloquent/Collection.php +++ b/framework/core/src/Database/Eloquent/Collection.php @@ -37,7 +37,7 @@ class Collection extends BaseCollection * * @link https://github.com/flarum/framework/pull/3780 */ - public function loadAggregate($relations, $column, $function = null) + public function loadAggregate($relations, $column, $function = null): self { if ($this->isEmpty()) { return $this; diff --git a/framework/core/src/Database/Exception/MigrationKeyMissing.php b/framework/core/src/Database/Exception/MigrationKeyMissing.php index 9d955f59f..6e9b36771 100644 --- a/framework/core/src/Database/Exception/MigrationKeyMissing.php +++ b/framework/core/src/Database/Exception/MigrationKeyMissing.php @@ -13,14 +13,10 @@ use Exception; class MigrationKeyMissing extends Exception { - protected $direction; - - public function __construct(string $direction, string $file = null) + public function __construct(protected string $direction, string $file = null) { - $this->direction = $direction; - $fileNameWithSpace = $file ? ' '.realpath($file) : ''; - parent::__construct("Migration file$fileNameWithSpace should contain an array with up/down (looking for $direction)"); + parent::__construct("Migration file $fileNameWithSpace should contain an array with up/down (looking for $direction)"); } public function withFile(string $file = null): self diff --git a/framework/core/src/Database/Migration.php b/framework/core/src/Database/Migration.php index 7e51f68eb..bef6760e8 100644 --- a/framework/core/src/Database/Migration.php +++ b/framework/core/src/Database/Migration.php @@ -21,10 +21,7 @@ use Illuminate\Database\Schema\Builder; */ abstract class Migration { - /** - * Create a table. - */ - public static function createTable($name, callable $definition) + public static function createTable($name, callable $definition): array { return [ 'up' => function (Builder $schema) use ($name, $definition) { @@ -38,10 +35,7 @@ abstract class Migration ]; } - /** - * Create a table if it doesn't already exist. - */ - public static function createTableIfNotExists($name, callable $definition) + public static function createTableIfNotExists($name, callable $definition): array { return [ 'up' => function (Builder $schema) use ($name, $definition) { @@ -57,10 +51,7 @@ abstract class Migration ]; } - /** - * Rename a table. - */ - public static function renameTable($from, $to) + public static function renameTable($from, $to): array { return [ 'up' => function (Builder $schema) use ($from, $to) { @@ -72,10 +63,7 @@ abstract class Migration ]; } - /** - * Add columns to a table. - */ - public static function addColumns($tableName, array $columnDefinitions) + public static function addColumns($tableName, array $columnDefinitions): array { return [ 'up' => function (Builder $schema) use ($tableName, $columnDefinitions) { @@ -94,10 +82,7 @@ abstract class Migration ]; } - /** - * Drop columns from a table. - */ - public static function dropColumns($tableName, array $columnDefinitions) + public static function dropColumns($tableName, array $columnDefinitions): array { $inverse = static::addColumns($tableName, $columnDefinitions); @@ -107,18 +92,12 @@ abstract class Migration ]; } - /** - * Rename a column. - */ - public static function renameColumn($tableName, $from, $to) + public static function renameColumn($tableName, $from, $to): array { return static::renameColumns($tableName, [$from => $to]); } - /** - * Rename multiple columns. - */ - public static function renameColumns($tableName, array $columnNames) + public static function renameColumns($tableName, array $columnNames): array { return [ 'up' => function (Builder $schema) use ($tableName, $columnNames) { @@ -144,7 +123,7 @@ abstract class Migration * @deprecated Use the Settings extender's `default` method instead to register settings. * @see Settings::default() */ - public static function addSettings(array $defaults) + public static function addSettings(array $defaults): array { return [ 'up' => function (Builder $schema) use ($defaults) { @@ -168,10 +147,7 @@ abstract class Migration ]; } - /** - * Add default permissions. - */ - public static function addPermissions(array $permissions) + public static function addPermissions(array $permissions): array { $rows = []; diff --git a/framework/core/src/Database/MigrationRepositoryInterface.php b/framework/core/src/Database/MigrationRepositoryInterface.php index ef71cc85d..e4820a456 100644 --- a/framework/core/src/Database/MigrationRepositoryInterface.php +++ b/framework/core/src/Database/MigrationRepositoryInterface.php @@ -13,34 +13,21 @@ interface MigrationRepositoryInterface { /** * Get the ran migrations for the given extension. - * - * @param string $extension - * @return array */ - public function getRan($extension = null); + public function getRan(?string $extension = null): array; /** * Log that a migration was run. - * - * @param string $file - * @param string $extension - * @return void */ - public function log($file, $extension = null); + public function log(string $file, ?string $extension = null): void; /** * Remove a migration from the log. - * - * @param string $file - * @param string $extension - * @return void */ - public function delete($file, $extension = null); + public function delete(string $file, ?string $extension = null): void; /** * Determine if the migration repository exists. - * - * @return bool */ - public function repositoryExists(); + public function repositoryExists(): bool; } diff --git a/framework/core/src/Database/Migrator.php b/framework/core/src/Database/Migrator.php index 58d25288d..15432ef0c 100644 --- a/framework/core/src/Database/Migrator.php +++ b/framework/core/src/Database/Migrator.php @@ -11,10 +11,12 @@ namespace Flarum\Database; use Flarum\Database\Exception\MigrationKeyMissing; use Flarum\Extension\Extension; +use Illuminate\Contracts\Filesystem\FileNotFoundException; use Illuminate\Database\ConnectionInterface; use Illuminate\Database\MySqlConnection; use Illuminate\Filesystem\Filesystem; use InvalidArgumentException; +use RuntimeException; use Symfony\Component\Console\Output\OutputInterface; /** @@ -22,84 +24,40 @@ use Symfony\Component\Console\Output\OutputInterface; */ class Migrator { - /** - * The migration repository implementation. - * - * @var \Flarum\Database\MigrationRepositoryInterface - */ - protected $repository; + protected ?OutputInterface $output = null; - /** - * The filesystem instance. - * - * @var \Illuminate\Filesystem\Filesystem - */ - protected $files; - - /** - * The output interface implementation. - * - * @var OutputInterface|null - */ - protected $output; - - /** - * @var ConnectionInterface - */ - protected $connection; - - /** - * Create a new migrator instance. - */ public function __construct( - MigrationRepositoryInterface $repository, - ConnectionInterface $connection, - Filesystem $files + protected MigrationRepositoryInterface $repository, + protected ConnectionInterface $connection, + protected Filesystem $files ) { - $this->files = $files; - $this->repository = $repository; - if (! ($connection instanceof MySqlConnection)) { throw new InvalidArgumentException('Only MySQL connections are supported'); } - $this->connection = $connection; - // Workaround for https://github.com/laravel/framework/issues/1186 $connection->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); } /** * Run the outstanding migrations at a given path. - * - * @param string $path - * @param Extension|null $extension - * @return void */ - public function run($path, Extension $extension = null) + public function run(string $path, ?Extension $extension = null): void { $files = $this->getMigrationFiles($path); - $ran = $this->repository->getRan($extension ? $extension->getId() : null); + $ran = $this->repository->getRan($extension?->getId()); $migrations = array_diff($files, $ran); $this->runMigrationList($path, $migrations, $extension); } - /** - * Run an array of migrations. - * - * @param string $path - * @param array $migrations - * @param Extension|null $extension - * @return void - */ - public function runMigrationList($path, $migrations, Extension $extension = null) + public function runMigrationList(string $path, array $migrations, ?Extension $extension = null): void { // First we will just make sure that there are any migrations to run. If there // aren't, we will just make a note of it to the developer so they're aware - // that all of the migrations have been run against this database system. + // that all the migrations have been run against this database system. if (count($migrations) == 0) { $this->note('Nothing to migrate.'); @@ -116,32 +74,23 @@ class Migrator /** * Run "up" a migration instance. - * - * @param string $path - * @param string $file - * @param Extension|null $extension - * @return void */ - protected function runUp($path, $file, Extension $extension = null) + protected function runUp(string $path, string $file, ?Extension $extension = null): void { $this->resolveAndRunClosureMigration($path, $file); // Once we have run a migrations class, we will log that it was run in this // repository so that we don't try to run it next time we do a migration // in the application. A migration repository keeps the migrate order. - $this->repository->log($file, $extension ? $extension->getId() : null); + $this->repository->log($file, $extension?->getId()); $this->note("Migrated: $file"); } /** - * Rolls all of the currently applied migrations back. - * - * @param string $path - * @param Extension|null $extension - * @return int + * Rolls all the currently applied migrations back. */ - public function reset($path, Extension $extension = null) + public function reset(string $path, ?Extension $extension = null): int { $migrations = array_reverse($this->repository->getRan( $extension ? $extension->getId() : null @@ -162,21 +111,15 @@ class Migrator /** * Run "down" a migration instance. - * - * @param string $path - * @param string $file - * @param string $path - * @param Extension $extension - * @return void */ - protected function runDown($path, $file, Extension $extension = null) + protected function runDown(string $path, string $file, ?Extension $extension = null): void { $this->resolveAndRunClosureMigration($path, $file, 'down'); // Once we have successfully run the migration "down" we will remove it from - // the migration repository so it will be considered to have not been run + // the migration repository, so it will be considered to have not been run // by the application then will be able to fire by any later operation. - $this->repository->delete($file, $extension ? $extension->getId() : null); + $this->repository->delete($file, $extension?->getId()); $this->note("Rolled back: $file"); } @@ -184,13 +127,11 @@ class Migrator /** * Runs a closure migration based on the migrate direction. * - * @param $migration - * @param string $direction * @throws MigrationKeyMissing */ - protected function runClosureMigration($migration, $direction = 'up') + protected function runClosureMigration(array $migration, string $direction = 'up'): void { - if (is_array($migration) && array_key_exists($direction, $migration)) { + if (array_key_exists($direction, $migration)) { call_user_func($migration[$direction], $this->connection->getSchemaBuilder()); } else { throw new MigrationKeyMissing($direction); @@ -200,12 +141,9 @@ class Migrator /** * Resolves and run a migration and assign the filename to the exception if needed. * - * @param string $path - * @param string $file - * @param string $direction - * @throws MigrationKeyMissing + * @throws MigrationKeyMissing|FileNotFoundException */ - protected function resolveAndRunClosureMigration(string $path, string $file, string $direction = 'up') + protected function resolveAndRunClosureMigration(string $path, string $file, string $direction = 'up'): void { $migration = $this->resolve($path, $file); @@ -245,16 +183,20 @@ class Migrator /** * Resolve a migration instance from a file. * - * @param string $path - * @param string $file - * @return array + * @throws FileNotFoundException|RuntimeException */ - public function resolve($path, $file) + public function resolve(string $path, string $file): array { $migration = "$path/$file.php"; if ($this->files->exists($migration)) { - return $this->files->getRequire($migration); + $migrationContents = $this->files->getRequire($migration); + + if (! is_array($migrationContents)) { + throw new RuntimeException('Migration must return an array with up and down keys'); + } + + return $migrationContents; } return []; @@ -265,7 +207,7 @@ class Migrator * * @param string $path to the directory containing the dump. */ - public function installFromSchema(string $path) + public function installFromSchema(string $path): void { $schemaPath = "$path/install.dump"; @@ -278,7 +220,7 @@ class Migrator foreach (explode(';', $dump) as $statement) { $statement = trim($statement); - if (empty($statement) || substr($statement, 0, 2) === '/*') { + if (empty($statement) || str_starts_with($statement, '/*')) { continue; } @@ -296,38 +238,19 @@ class Migrator $this->note('Loaded stored database schema. ('.$runTime.'ms)'); } - /** - * Set the output implementation that should be used by the console. - * - * @param OutputInterface $output - * @return $this - */ - public function setOutput(OutputInterface $output) + public function setOutput(OutputInterface $output): static { $this->output = $output; return $this; } - /** - * Write a note to the conosle's output. - * - * @param string $message - * @return void - */ - protected function note($message) + protected function note(string $message): void { - if ($this->output) { - $this->output->writeln($message); - } + $this->output?->writeln($message); } - /** - * Determine if the migration repository exists. - * - * @return bool - */ - public function repositoryExists() + public function repositoryExists(): bool { return $this->repository->repositoryExists(); } diff --git a/framework/core/src/Database/ScopeVisibilityTrait.php b/framework/core/src/Database/ScopeVisibilityTrait.php index ddcdb3cab..0d3ebfe8a 100644 --- a/framework/core/src/Database/ScopeVisibilityTrait.php +++ b/framework/core/src/Database/ScopeVisibilityTrait.php @@ -15,15 +15,18 @@ use Illuminate\Support\Arr; trait ScopeVisibilityTrait { - protected static $visibilityScopers = []; + /** + * @todo: define clear scoper interfaces. + * + * @var array> + */ + protected static array $visibilityScopers = []; - public static function registerVisibilityScoper($scoper, $ability = null) + public static function registerVisibilityScoper($scoper, ?string $ability = null): void { $model = static::class; - if ($ability === null) { - $ability = '*'; - } + $ability ??= '*'; if (! Arr::has(static::$visibilityScopers, "$model.$ability")) { Arr::set(static::$visibilityScopers, "$model.$ability", []); @@ -34,11 +37,8 @@ trait ScopeVisibilityTrait /** * Scope a query to only include records that are visible to a user. - * - * @param Builder $query - * @param User $actor */ - public function scopeWhereVisibleTo(Builder $query, User $actor, string $ability = 'view') + public function scopeWhereVisibleTo(Builder $query, User $actor, string $ability = 'view'): Builder { foreach (array_reverse(array_merge([static::class], class_parents($this))) as $class) { foreach (Arr::get(static::$visibilityScopers, "$class.*", []) as $listener) { diff --git a/framework/core/src/Discussion/Access/DiscussionPolicy.php b/framework/core/src/Discussion/Access/DiscussionPolicy.php index c0124257c..e1dfb50e3 100644 --- a/framework/core/src/Discussion/Access/DiscussionPolicy.php +++ b/framework/core/src/Discussion/Access/DiscussionPolicy.php @@ -16,33 +16,18 @@ use Flarum\User\User; class DiscussionPolicy extends AbstractPolicy { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param User $actor - * @param string $ability - * @return string|void - */ - public function can(User $actor, $ability) + public function can(User $actor, string $ability) { if ($actor->hasPermission('discussion.'.$ability)) { return $this->allow(); } } - /** - * @param User $actor - * @param \Flarum\Discussion\Discussion $discussion - * @return bool|null - */ public function rename(User $actor, Discussion $discussion) { if ($discussion->user_id == $actor->id && $actor->can('reply', $discussion)) { @@ -56,11 +41,6 @@ class DiscussionPolicy extends AbstractPolicy } } - /** - * @param User $actor - * @param \Flarum\Discussion\Discussion $discussion - * @return bool|null - */ public function hide(User $actor, Discussion $discussion) { if ($discussion->user_id == $actor->id diff --git a/framework/core/src/Discussion/Access/ScopeDiscussionVisibility.php b/framework/core/src/Discussion/Access/ScopeDiscussionVisibility.php index 9875eb63d..023b87939 100644 --- a/framework/core/src/Discussion/Access/ScopeDiscussionVisibility.php +++ b/framework/core/src/Discussion/Access/ScopeDiscussionVisibility.php @@ -14,11 +14,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopeDiscussionVisibility { - /** - * @param User $actor - * @param Builder $query - */ - public function __invoke(User $actor, $query) + public function __invoke(User $actor, Builder $query): void { if ($actor->cannot('viewForum')) { $query->whereRaw('FALSE'); diff --git a/framework/core/src/Discussion/Command/DeleteDiscussion.php b/framework/core/src/Discussion/Command/DeleteDiscussion.php index c41006eb0..805a63fec 100644 --- a/framework/core/src/Discussion/Command/DeleteDiscussion.php +++ b/framework/core/src/Discussion/Command/DeleteDiscussion.php @@ -13,38 +13,10 @@ use Flarum\User\User; class DeleteDiscussion { - /** - * The ID of the discussion to delete. - * - * @var int - */ - public $discussionId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * Any other user input associated with the action. This is unused by - * default, but may be used by extensions. - * - * @var array - */ - public $data; - - /** - * @param int $discussionId The ID of the discussion to delete. - * @param User $actor The user performing the action. - * @param array $data Any other user input associated with the action. This - * is unused by default, but may be used by extensions. - */ - public function __construct($discussionId, User $actor, array $data = []) - { - $this->discussionId = $discussionId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $discussionId, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/Discussion/Command/DeleteDiscussionHandler.php b/framework/core/src/Discussion/Command/DeleteDiscussionHandler.php index ac8027497..82ac60531 100644 --- a/framework/core/src/Discussion/Command/DeleteDiscussionHandler.php +++ b/framework/core/src/Discussion/Command/DeleteDiscussionHandler.php @@ -9,37 +9,23 @@ namespace Flarum\Discussion\Command; +use Flarum\Discussion\Discussion; use Flarum\Discussion\DiscussionRepository; use Flarum\Discussion\Event\Deleting; use Flarum\Foundation\DispatchEventsTrait; -use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Contracts\Events\Dispatcher; class DeleteDiscussionHandler { use DispatchEventsTrait; - /** - * @var \Flarum\Discussion\DiscussionRepository - */ - protected $discussions; - - /** - * @param Dispatcher $events - * @param DiscussionRepository $discussions - */ - public function __construct(Dispatcher $events, DiscussionRepository $discussions) - { - $this->events = $events; - $this->discussions = $discussions; + public function __construct( + protected Dispatcher $events, + protected DiscussionRepository $discussions + ) { } - /** - * @param DeleteDiscussion $command - * @return \Flarum\Discussion\Discussion - * @throws PermissionDeniedException - */ - public function handle(DeleteDiscussion $command) + public function handle(DeleteDiscussion $command): Discussion { $actor = $command->actor; diff --git a/framework/core/src/Discussion/Command/EditDiscussion.php b/framework/core/src/Discussion/Command/EditDiscussion.php index 781473287..b3dfabc7a 100644 --- a/framework/core/src/Discussion/Command/EditDiscussion.php +++ b/framework/core/src/Discussion/Command/EditDiscussion.php @@ -13,36 +13,10 @@ use Flarum\User\User; class EditDiscussion { - /** - * The ID of the discussion to edit. - * - * @var int - */ - public $discussionId; - - /** - * The user performing the action. - * - * @var \Flarum\User\User - */ - public $actor; - - /** - * The attributes to update on the discussion. - * - * @var array - */ - public $data; - - /** - * @param int $discussionId The ID of the discussion to edit. - * @param \Flarum\User\User $actor The user performing the action. - * @param array $data The attributes to update on the discussion. - */ - public function __construct($discussionId, User $actor, array $data) - { - $this->discussionId = $discussionId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public $discussionId, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Discussion/Command/EditDiscussionHandler.php b/framework/core/src/Discussion/Command/EditDiscussionHandler.php index 8ffd23eb8..786aaacf0 100644 --- a/framework/core/src/Discussion/Command/EditDiscussionHandler.php +++ b/framework/core/src/Discussion/Command/EditDiscussionHandler.php @@ -9,6 +9,7 @@ namespace Flarum\Discussion\Command; +use Flarum\Discussion\Discussion; use Flarum\Discussion\DiscussionRepository; use Flarum\Discussion\DiscussionValidator; use Flarum\Discussion\Event\Saving; @@ -20,34 +21,14 @@ class EditDiscussionHandler { use DispatchEventsTrait; - /** - * @var DiscussionRepository - */ - protected $discussions; - - /** - * @var DiscussionValidator - */ - protected $validator; - - /** - * @param Dispatcher $events - * @param DiscussionRepository $discussions - * @param DiscussionValidator $validator - */ - public function __construct(Dispatcher $events, DiscussionRepository $discussions, DiscussionValidator $validator) - { - $this->events = $events; - $this->discussions = $discussions; - $this->validator = $validator; + public function __construct( + protected Dispatcher $events, + protected DiscussionRepository $discussions, + protected DiscussionValidator $validator + ) { } - /** - * @param EditDiscussion $command - * @return \Flarum\Discussion\Discussion - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(EditDiscussion $command) + public function handle(EditDiscussion $command): Discussion { $actor = $command->actor; $data = $command->data; diff --git a/framework/core/src/Discussion/Command/ReadDiscussion.php b/framework/core/src/Discussion/Command/ReadDiscussion.php index 913683efd..9963bdb52 100644 --- a/framework/core/src/Discussion/Command/ReadDiscussion.php +++ b/framework/core/src/Discussion/Command/ReadDiscussion.php @@ -13,36 +13,12 @@ use Flarum\User\User; class ReadDiscussion { - /** - * The ID of the discussion to mark as read. - * - * @var int - */ - public $discussionId; - - /** - * The user to mark the discussion as read for. - * - * @var User - */ - public $actor; - - /** - * The number of the post to mark as read. - * - * @var int - */ - public $lastReadPostNumber; - - /** - * @param int $discussionId The ID of the discussion to mark as read. - * @param User $actor The user to mark the discussion as read for. - * @param int $lastReadPostNumber The number of the post to mark as read. - */ - public function __construct($discussionId, User $actor, $lastReadPostNumber) - { - $this->discussionId = $discussionId; - $this->actor = $actor; - $this->lastReadPostNumber = $lastReadPostNumber; + public function __construct( + public $discussionId, + /** The user to mark the discussion as read for */ + public User $actor, + /** The number of the post to mark as read */ + public $lastReadPostNumber + ) { } } diff --git a/framework/core/src/Discussion/Command/ReadDiscussionHandler.php b/framework/core/src/Discussion/Command/ReadDiscussionHandler.php index c62a405ed..1c25841d1 100644 --- a/framework/core/src/Discussion/Command/ReadDiscussionHandler.php +++ b/framework/core/src/Discussion/Command/ReadDiscussionHandler.php @@ -11,6 +11,7 @@ namespace Flarum\Discussion\Command; use Flarum\Discussion\DiscussionRepository; use Flarum\Discussion\Event\UserDataSaving; +use Flarum\Discussion\UserState; use Flarum\Foundation\DispatchEventsTrait; use Illuminate\Contracts\Events\Dispatcher; @@ -18,27 +19,13 @@ class ReadDiscussionHandler { use DispatchEventsTrait; - /** - * @var DiscussionRepository - */ - protected $discussions; - - /** - * @param Dispatcher $events - * @param DiscussionRepository $discussions - */ - public function __construct(Dispatcher $events, DiscussionRepository $discussions) - { - $this->events = $events; - $this->discussions = $discussions; + public function __construct( + protected Dispatcher $events, + protected DiscussionRepository $discussions + ) { } - /** - * @param ReadDiscussion $command - * @return \Flarum\Discussion\UserState - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(ReadDiscussion $command) + public function handle(ReadDiscussion $command): UserState { $actor = $command->actor; diff --git a/framework/core/src/Discussion/Command/StartDiscussion.php b/framework/core/src/Discussion/Command/StartDiscussion.php index 90c14d037..e3d8756bf 100644 --- a/framework/core/src/Discussion/Command/StartDiscussion.php +++ b/framework/core/src/Discussion/Command/StartDiscussion.php @@ -13,36 +13,10 @@ use Flarum\User\User; class StartDiscussion { - /** - * The user authoring the discussion. - * - * @var User - */ - public $actor; - - /** - * The discussion attributes. - * - * @var array - */ - public $data; - - /** - * The current ip address of the actor. - * - * @var string - */ - public $ipAddress; - - /** - * @param User $actor The user authoring the discussion. - * @param array $data The discussion attributes. - * @param string $ipAddress The current ip address of the actor. - */ - public function __construct(User $actor, array $data, string $ipAddress) - { - $this->actor = $actor; - $this->data = $data; - $this->ipAddress = $ipAddress; + public function __construct( + public User $actor, + public array $data, + public string $ipAddress + ) { } } diff --git a/framework/core/src/Discussion/Command/StartDiscussionHandler.php b/framework/core/src/Discussion/Command/StartDiscussionHandler.php index 25f7b09bd..fd7fdc8cf 100644 --- a/framework/core/src/Discussion/Command/StartDiscussionHandler.php +++ b/framework/core/src/Discussion/Command/StartDiscussionHandler.php @@ -23,34 +23,14 @@ class StartDiscussionHandler { use DispatchEventsTrait; - /** - * @var BusDispatcher - */ - protected $bus; - - /** - * @var \Flarum\Discussion\DiscussionValidator - */ - protected $validator; - - /** - * @param EventDispatcher $events - * @param BusDispatcher $bus - * @param \Flarum\Discussion\DiscussionValidator $validator - */ - public function __construct(EventDispatcher $events, BusDispatcher $bus, DiscussionValidator $validator) - { - $this->events = $events; - $this->bus = $bus; - $this->validator = $validator; + public function __construct( + protected EventDispatcher $events, + protected BusDispatcher $bus, + protected DiscussionValidator $validator + ) { } - /** - * @param StartDiscussion $command - * @return mixed - * @throws Exception - */ - public function handle(StartDiscussion $command) + public function handle(StartDiscussion $command): Discussion { $actor = $command->actor; $data = $command->data; diff --git a/framework/core/src/Discussion/Discussion.php b/framework/core/src/Discussion/Discussion.php index 22e602aff..97562111a 100644 --- a/framework/core/src/Discussion/Discussion.php +++ b/framework/core/src/Discussion/Discussion.php @@ -23,6 +23,10 @@ use Flarum\Post\MergeableInterface; use Flarum\Post\Post; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\User; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Support\Str; @@ -63,7 +67,7 @@ class Discussion extends AbstractModel * * @var array */ - protected $modifiedPosts = []; + protected array $modifiedPosts = []; /** * The attributes that should be mutated to dates. @@ -83,16 +87,9 @@ class Discussion extends AbstractModel /** * The user for which the state relationship should be loaded. - * - * @var User|null */ - protected static $stateUser; + protected static ?User $stateUser; - /** - * Boot the model. - * - * @return void - */ public static function boot() { parent::boot(); @@ -112,14 +109,7 @@ class Discussion extends AbstractModel }); } - /** - * Start a new discussion. Raises the DiscussionWasStarted event. - * - * @param string $title - * @param User $user - * @return static - */ - public static function start($title, User $user) + public static function start(string $title, User $user): static { $discussion = new static; @@ -134,13 +124,7 @@ class Discussion extends AbstractModel return $discussion; } - /** - * Rename the discussion. Raises the DiscussionWasRenamed event. - * - * @param string $title - * @return $this - */ - public function rename($title) + public function rename(string $title): static { if ($this->title !== $title) { $oldTitle = $this->title; @@ -152,17 +136,11 @@ class Discussion extends AbstractModel return $this; } - /** - * Hide the discussion. - * - * @param User $actor - * @return $this - */ - public function hide(User $actor = null) + public function hide(?User $actor = null): static { if (! $this->hidden_at) { $this->hidden_at = Carbon::now(); - $this->hidden_user_id = $actor ? $actor->id : null; + $this->hidden_user_id = $actor?->id; $this->raise(new Hidden($this)); } @@ -170,12 +148,7 @@ class Discussion extends AbstractModel return $this; } - /** - * Restore the discussion. - * - * @return $this - */ - public function restore() + public function restore(): static { if ($this->hidden_at !== null) { $this->hidden_at = null; @@ -187,13 +160,7 @@ class Discussion extends AbstractModel return $this; } - /** - * Set the discussion's first post details. - * - * @param Post $post - * @return $this - */ - public function setFirstPost(Post $post) + public function setFirstPost(Post $post): static { $this->created_at = $post->created_at; $this->user_id = $post->user_id; @@ -202,13 +169,7 @@ class Discussion extends AbstractModel return $this; } - /** - * Set the discussion's last post details. - * - * @param Post $post - * @return $this - */ - public function setLastPost(Post $post) + public function setLastPost(Post $post): static { $this->last_posted_at = $post->created_at; $this->last_posted_user_id = $post->user_id; @@ -218,12 +179,7 @@ class Discussion extends AbstractModel return $this; } - /** - * Refresh a discussion's last post details. - * - * @return $this - */ - public function refreshLastPost() + public function refreshLastPost(): static { if ($lastPost = $this->comments()->latest()->first()) { /** @var Post $lastPost */ @@ -233,24 +189,14 @@ class Discussion extends AbstractModel return $this; } - /** - * Refresh the discussion's comment count. - * - * @return $this - */ - public function refreshCommentCount() + public function refreshCommentCount(): static { $this->comment_count = $this->comments()->count(); return $this; } - /** - * Refresh the discussion's participant count. - * - * @return $this - */ - public function refreshParticipantCount() + public function refreshParticipantCount(): static { $this->participant_count = $this->participants()->count('users.id'); @@ -265,13 +211,13 @@ class Discussion extends AbstractModel * DiscussionRenamedPost, and delete if the title has been reverted * completely.) * - * @template T of \Flarum\Post\MergeableInterface + * @template T of MergeableInterface * @param T $post The post to save. * @return T The resulting post. It may or may not be the same post as * was originally intended to be saved. It also may not exist, if the * merge logic resulted in deletion. */ - public function mergePost(MergeableInterface $post) + public function mergePost(MergeableInterface $post): MergeableInterface { $lastPost = $this->posts()->latest()->first(); @@ -282,30 +228,26 @@ class Discussion extends AbstractModel /** * Get the posts that have been modified during this request. - * - * @return array */ - public function getModifiedPosts() + public function getModifiedPosts(): array { return $this->modifiedPosts; } /** - * Define the relationship with the discussion's posts. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function posts() + public function posts(): HasMany { return $this->hasMany(Post::class); } /** - * Define the relationship with the discussion's publicly-visible comments. + * The discussion's publicly-visible comments. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function comments() + public function comments(): HasMany { return $this->posts() ->where('is_private', false) @@ -317,9 +259,9 @@ class Discussion extends AbstractModel * Query the discussion's participants (a list of unique users who have * posted in the discussion). * - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function participants() + public function participants(): Builder { return User::join('posts', 'posts.user_id', '=', 'users.id') ->where('posts.discussion_id', $this->id) @@ -329,83 +271,50 @@ class Discussion extends AbstractModel ->distinct(); } - /** - * Define the relationship with the discussion's first post. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function firstPost() + public function firstPost(): BelongsTo { return $this->belongsTo(Post::class, 'first_post_id'); } - /** - * Define the relationship with the discussion's author. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); } - /** - * Define the relationship with the discussion's last post. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function lastPost() + public function lastPost(): BelongsTo { return $this->belongsTo(Post::class, 'last_post_id'); } - /** - * Define the relationship with the discussion's most recent author. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function lastPostedUser() + public function lastPostedUser(): BelongsTo { return $this->belongsTo(User::class, 'last_posted_user_id'); } - /** - * Define the relationship with the discussion's most relevant post. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function mostRelevantPost() + public function mostRelevantPost(): BelongsTo { return $this->belongsTo(Post::class, 'most_relevant_post_id'); } /** - * Define the relationship with the discussion's readers. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return BelongsToMany */ - public function readers() + public function readers(): BelongsToMany { return $this->belongsToMany(User::class); } /** - * Define the relationship with the discussion's state for a particular - * user. - * * If no user is passed (i.e. in the case of eager loading the 'state' * relation), then the static `$stateUser` property is used. * - * @param User|null $user - * @return HasOne - * * @see Discussion::setStateUser() */ - public function state(User $user = null): HasOne + public function state(?User $user = null): HasOne { $user = $user ?: static::$stateUser; - return $this->hasOne(UserState::class)->where('user_id', $user ? $user->id : null); + return $this->hasOne(UserState::class)->where('user_id', $user?->id); } /** @@ -429,7 +338,7 @@ class Discussion extends AbstractModel /** * Set the user for which the state relationship should be loaded. */ - public static function setStateUser(User $user) + public static function setStateUser(User $user): void { static::$stateUser = $user; } @@ -439,7 +348,7 @@ class Discussion extends AbstractModel * * This automatically creates a matching slug for the discussion. */ - protected function setTitleAttribute(string $title) + protected function setTitleAttribute(string $title): void { $this->attributes['title'] = $title; $this->slug = Str::slug( diff --git a/framework/core/src/Discussion/DiscussionMetadataUpdater.php b/framework/core/src/Discussion/DiscussionMetadataUpdater.php index c61dcd186..3e9966ab2 100644 --- a/framework/core/src/Discussion/DiscussionMetadataUpdater.php +++ b/framework/core/src/Discussion/DiscussionMetadataUpdater.php @@ -18,15 +18,15 @@ use Illuminate\Contracts\Events\Dispatcher; class DiscussionMetadataUpdater { - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Posted::class, [$this, 'whenPostWasPosted']); - $events->listen(Deleted::class, [$this, 'whenPostWasDeleted']); - $events->listen(Hidden::class, [$this, 'whenPostWasHidden']); - $events->listen(Restored::class, [$this, 'whenPostWasRestored']); + $events->listen(Posted::class, $this->whenPostWasPosted(...)); + $events->listen(Deleted::class, $this->whenPostWasDeleted(...)); + $events->listen(Hidden::class, $this->whenPostWasHidden(...)); + $events->listen(Restored::class, $this->whenPostWasRestored(...)); } - public function whenPostWasPosted(Posted $event) + public function whenPostWasPosted(Posted $event): void { $discussion = $event->post->discussion; @@ -38,7 +38,7 @@ class DiscussionMetadataUpdater } } - public function whenPostWasDeleted(Deleted $event) + public function whenPostWasDeleted(Deleted $event): void { $this->removePost($event->post); @@ -49,12 +49,12 @@ class DiscussionMetadataUpdater } } - public function whenPostWasHidden(Hidden $event) + public function whenPostWasHidden(Hidden $event): void { $this->removePost($event->post); } - public function whenPostWasRestored(Restored $event) + public function whenPostWasRestored(Restored $event): void { $discussion = $event->post->discussion; @@ -66,7 +66,7 @@ class DiscussionMetadataUpdater } } - protected function removePost(Post $post) + protected function removePost(Post $post): void { $discussion = $post->discussion; diff --git a/framework/core/src/Discussion/DiscussionRenamedLogger.php b/framework/core/src/Discussion/DiscussionRenamedLogger.php index a5b473d0a..3b1f3e63d 100644 --- a/framework/core/src/Discussion/DiscussionRenamedLogger.php +++ b/framework/core/src/Discussion/DiscussionRenamedLogger.php @@ -16,17 +16,12 @@ use Flarum\Post\DiscussionRenamedPost; class DiscussionRenamedLogger { - /** - * @var NotificationSyncer - */ - protected $notifications; - - public function __construct(NotificationSyncer $notifications) - { - $this->notifications = $notifications; + public function __construct( + protected NotificationSyncer $notifications + ) { } - public function handle(Renamed $event) + public function handle(Renamed $event): void { $post = DiscussionRenamedPost::reply( $event->discussion->id, @@ -35,6 +30,7 @@ class DiscussionRenamedLogger $event->discussion->title ); + /** @var DiscussionRenamedPost $post */ $post = $event->discussion->mergePost($post); if ($event->discussion->user_id !== $event->actor->id) { diff --git a/framework/core/src/Discussion/DiscussionRepository.php b/framework/core/src/Discussion/DiscussionRepository.php index 87793f5b7..434c65c77 100644 --- a/framework/core/src/Discussion/DiscussionRepository.php +++ b/framework/core/src/Discussion/DiscussionRepository.php @@ -11,15 +11,14 @@ namespace Flarum\Discussion; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; class DiscussionRepository { /** - * Get a new query builder for the discussions table. - * * @return Builder */ - public function query() + public function query(): Builder { return Discussion::query(); } @@ -27,12 +26,8 @@ class DiscussionRepository /** * Find a discussion by ID, optionally making sure it is visible to a * certain user, or throw an exception. - * - * @param int|string $id - * @param User|null $user - * @return \Flarum\Discussion\Discussion */ - public function findOrFail($id, User $user = null) + public function findOrFail(int|string $id, ?User $user = null): Discussion { $query = $this->query()->where('id', $id); @@ -43,10 +38,10 @@ class DiscussionRepository * Get the IDs of discussions which a user has read completely. * * @param User $user - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection * @deprecated 1.3 Use `getReadIdsQuery` instead */ - public function getReadIds(User $user) + public function getReadIds(User $user): Collection { return $this->getReadIdsQuery($user)->get(); } @@ -73,7 +68,7 @@ class DiscussionRepository * @param User|null $user * @return Builder */ - protected function scopeVisibleTo(Builder $query, User $user = null) + protected function scopeVisibleTo(Builder $query, ?User $user = null): Builder { if ($user !== null) { $query->whereVisibleTo($user); diff --git a/framework/core/src/Discussion/DiscussionServiceProvider.php b/framework/core/src/Discussion/DiscussionServiceProvider.php index d369839e8..554b7f401 100644 --- a/framework/core/src/Discussion/DiscussionServiceProvider.php +++ b/framework/core/src/Discussion/DiscussionServiceProvider.php @@ -16,7 +16,7 @@ use Illuminate\Contracts\Events\Dispatcher; class DiscussionServiceProvider extends AbstractServiceProvider { - public function boot(Dispatcher $events) + public function boot(Dispatcher $events): void { $events->subscribe(DiscussionMetadataUpdater::class); $events->subscribe(UserStateUpdater::class); diff --git a/framework/core/src/Discussion/DiscussionValidator.php b/framework/core/src/Discussion/DiscussionValidator.php index 15d2a329c..48013e62d 100644 --- a/framework/core/src/Discussion/DiscussionValidator.php +++ b/framework/core/src/Discussion/DiscussionValidator.php @@ -13,7 +13,7 @@ use Flarum\Foundation\AbstractValidator; class DiscussionValidator extends AbstractValidator { - protected $rules = [ + protected array $rules = [ 'title' => [ 'required', 'min:3', diff --git a/framework/core/src/Discussion/Event/Deleted.php b/framework/core/src/Discussion/Event/Deleted.php index 558d0fe74..ce2663fd9 100644 --- a/framework/core/src/Discussion/Event/Deleted.php +++ b/framework/core/src/Discussion/Event/Deleted.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Deleted { - /** - * @var \Flarum\Discussion\Discussion - */ - public $discussion; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Discussion\Discussion $discussion - * @param User $actor - */ - public function __construct(Discussion $discussion, User $actor = null) - { - $this->discussion = $discussion; - $this->actor = $actor; + public function __construct( + public Discussion $discussion, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Discussion/Event/Deleting.php b/framework/core/src/Discussion/Event/Deleting.php index 309de4775..76099ec45 100644 --- a/framework/core/src/Discussion/Event/Deleting.php +++ b/framework/core/src/Discussion/Event/Deleting.php @@ -14,36 +14,10 @@ use Flarum\User\User; class Deleting { - /** - * The discussion that is going to be deleted. - * - * @var Discussion - */ - public $discussion; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * Any user input associated with the command. - * - * @var array - */ - public $data; - - /** - * @param Discussion $discussion - * @param User $actor - * @param array $data - */ - public function __construct(Discussion $discussion, User $actor, array $data = []) - { - $this->discussion = $discussion; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Discussion $discussion, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/Discussion/Event/Hidden.php b/framework/core/src/Discussion/Event/Hidden.php index 8a9990d67..44e4787c8 100644 --- a/framework/core/src/Discussion/Event/Hidden.php +++ b/framework/core/src/Discussion/Event/Hidden.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Hidden { - /** - * @var \Flarum\Discussion\Discussion - */ - public $discussion; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Discussion\Discussion $discussion - * @param User $actor - */ - public function __construct(Discussion $discussion, User $actor = null) - { - $this->discussion = $discussion; - $this->actor = $actor; + public function __construct( + public Discussion $discussion, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Discussion/Event/Renamed.php b/framework/core/src/Discussion/Event/Renamed.php index da8636e3e..d8f79885a 100644 --- a/framework/core/src/Discussion/Event/Renamed.php +++ b/framework/core/src/Discussion/Event/Renamed.php @@ -14,30 +14,10 @@ use Flarum\User\User; class Renamed { - /** - * @var Discussion - */ - public $discussion; - - /** - * @var string - */ - public $oldTitle; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Discussion\Discussion $discussion - * @param User $actor - * @param string $oldTitle - */ - public function __construct(Discussion $discussion, $oldTitle, User $actor = null) - { - $this->discussion = $discussion; - $this->oldTitle = $oldTitle; - $this->actor = $actor; + public function __construct( + public Discussion $discussion, + public string $oldTitle, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Discussion/Event/Restored.php b/framework/core/src/Discussion/Event/Restored.php index b5ca34c84..eff434bda 100644 --- a/framework/core/src/Discussion/Event/Restored.php +++ b/framework/core/src/Discussion/Event/Restored.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Restored { - /** - * @var \Flarum\Discussion\Discussion - */ - public $discussion; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Discussion\Discussion $discussion - * @param User $actor - */ - public function __construct(Discussion $discussion, User $actor = null) - { - $this->discussion = $discussion; - $this->actor = $actor; + public function __construct( + public Discussion $discussion, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Discussion/Event/Saving.php b/framework/core/src/Discussion/Event/Saving.php index 40b63644e..d9319ee02 100644 --- a/framework/core/src/Discussion/Event/Saving.php +++ b/framework/core/src/Discussion/Event/Saving.php @@ -14,36 +14,10 @@ use Flarum\User\User; class Saving { - /** - * The discussion that will be saved. - * - * @var \Flarum\Discussion\Discussion - */ - public $discussion; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * Any user input associated with the command. - * - * @var array - */ - public $data; - - /** - * @param \Flarum\Discussion\Discussion $discussion - * @param User $actor - * @param array $data - */ - public function __construct(Discussion $discussion, User $actor, array $data = []) - { - $this->discussion = $discussion; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Discussion $discussion, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/Discussion/Event/Started.php b/framework/core/src/Discussion/Event/Started.php index 7fd7e7eff..7d8b0f1b4 100644 --- a/framework/core/src/Discussion/Event/Started.php +++ b/framework/core/src/Discussion/Event/Started.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Started { - /** - * @var \Flarum\Discussion\Discussion - */ - public $discussion; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Discussion\Discussion $discussion - * @param User $actor - */ - public function __construct(Discussion $discussion, User $actor = null) - { - $this->discussion = $discussion; - $this->actor = $actor; + public function __construct( + public Discussion $discussion, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Discussion/Event/UserDataSaving.php b/framework/core/src/Discussion/Event/UserDataSaving.php index be2c88987..8996e1432 100644 --- a/framework/core/src/Discussion/Event/UserDataSaving.php +++ b/framework/core/src/Discussion/Event/UserDataSaving.php @@ -13,16 +13,8 @@ use Flarum\Discussion\UserState; class UserDataSaving { - /** - * @var \Flarum\Discussion\UserState - */ - public $state; - - /** - * @param \Flarum\Discussion\UserState $state - */ - public function __construct(UserState $state) - { - $this->state = $state; + public function __construct( + public UserState $state + ) { } } diff --git a/framework/core/src/Discussion/Event/UserRead.php b/framework/core/src/Discussion/Event/UserRead.php index b631977e7..90e94ec18 100644 --- a/framework/core/src/Discussion/Event/UserRead.php +++ b/framework/core/src/Discussion/Event/UserRead.php @@ -10,25 +10,11 @@ namespace Flarum\Discussion\Event; use Flarum\Discussion\UserState; -use Flarum\User\User; class UserRead { - /** - * @var UserState - */ - public $state; - - /** - * @var User - */ - public $actor; - - /** - * @param UserState $state - */ - public function __construct(UserState $state) - { - $this->state = $state; + public function __construct( + public UserState $state + ) { } } diff --git a/framework/core/src/Discussion/Filter/DiscussionFilterer.php b/framework/core/src/Discussion/Filter/DiscussionFilterer.php index 8ada10502..ec4be9aeb 100644 --- a/framework/core/src/Discussion/Filter/DiscussionFilterer.php +++ b/framework/core/src/Discussion/Filter/DiscussionFilterer.php @@ -16,21 +16,9 @@ use Illuminate\Database\Eloquent\Builder; class DiscussionFilterer extends AbstractFilterer { - /** - * @var DiscussionRepository - */ - protected $discussions; - - /** - * @param DiscussionRepository $discussions - * @param array $filters - * @param array $filterMutators - */ - public function __construct(DiscussionRepository $discussions, array $filters, array $filterMutators) + public function __construct(protected DiscussionRepository $discussions, array $filters, array $filterMutators) { parent::__construct($filters, $filterMutators); - - $this->discussions = $discussions; } protected function getQuery(User $actor): Builder diff --git a/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php b/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php index 2f55220f7..550cbaf4b 100644 --- a/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php +++ b/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php @@ -18,14 +18,9 @@ use Flarum\User\User; */ class IdWithTransliteratedSlugDriver implements SlugDriverInterface { - /** - * @var DiscussionRepository - */ - protected $discussions; - - public function __construct(DiscussionRepository $discussions) - { - $this->discussions = $discussions; + public function __construct( + protected DiscussionRepository $discussions + ) { } /** diff --git a/framework/core/src/Discussion/Query/AuthorFilterGambit.php b/framework/core/src/Discussion/Query/AuthorFilterGambit.php index d1008604f..7d804be75 100644 --- a/framework/core/src/Discussion/Query/AuthorFilterGambit.php +++ b/framework/core/src/Discussion/Query/AuthorFilterGambit.php @@ -21,31 +21,17 @@ class AuthorFilterGambit extends AbstractRegexGambit implements FilterInterface { use ValidateFilterTrait; - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @param \Flarum\User\UserRepository $users - */ - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'author:(.+)'; } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $matches[1], $negate); } @@ -55,12 +41,12 @@ class AuthorFilterGambit extends AbstractRegexGambit implements FilterInterface return 'author'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $filterValue, $negate); } - protected function constrain(Builder $query, $rawUsernames, $negate) + protected function constrain(Builder $query, string|array $rawUsernames, $negate) { $usernames = $this->asStringArray($rawUsernames); diff --git a/framework/core/src/Discussion/Query/CreatedFilterGambit.php b/framework/core/src/Discussion/Query/CreatedFilterGambit.php index ed2198be3..ad4d36d3a 100644 --- a/framework/core/src/Discussion/Query/CreatedFilterGambit.php +++ b/framework/core/src/Discussion/Query/CreatedFilterGambit.php @@ -21,18 +21,12 @@ class CreatedFilterGambit extends AbstractRegexGambit implements FilterInterface { use ValidateFilterTrait; - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'created:(\d{4}\-\d\d\-\d\d)(\.\.(\d{4}\-\d\d\-\d\d))?'; } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), Arr::get($matches, 1), Arr::get($matches, 3), $negate); } @@ -42,7 +36,7 @@ class CreatedFilterGambit extends AbstractRegexGambit implements FilterInterface return 'created'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $filterValue = $this->asString($filterValue); diff --git a/framework/core/src/Discussion/Query/HiddenFilterGambit.php b/framework/core/src/Discussion/Query/HiddenFilterGambit.php index b56af3298..a5e88ebb7 100644 --- a/framework/core/src/Discussion/Query/HiddenFilterGambit.php +++ b/framework/core/src/Discussion/Query/HiddenFilterGambit.php @@ -17,18 +17,12 @@ use Illuminate\Database\Query\Builder; class HiddenFilterGambit extends AbstractRegexGambit implements FilterInterface { - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'is:hidden'; } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $negate); } @@ -38,7 +32,7 @@ class HiddenFilterGambit extends AbstractRegexGambit implements FilterInterface return 'hidden'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $negate); } diff --git a/framework/core/src/Discussion/Query/UnreadFilterGambit.php b/framework/core/src/Discussion/Query/UnreadFilterGambit.php index 0423bda58..2a25a0ea5 100644 --- a/framework/core/src/Discussion/Query/UnreadFilterGambit.php +++ b/framework/core/src/Discussion/Query/UnreadFilterGambit.php @@ -32,18 +32,12 @@ class UnreadFilterGambit extends AbstractRegexGambit implements FilterInterface $this->discussions = $discussions; } - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'is:unread'; } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $search->getActor(), $negate); } @@ -53,7 +47,7 @@ class UnreadFilterGambit extends AbstractRegexGambit implements FilterInterface return 'unread'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $filterState->getActor(), $negate); } diff --git a/framework/core/src/Discussion/Search/DiscussionSearcher.php b/framework/core/src/Discussion/Search/DiscussionSearcher.php index afdd40724..e5c953e2b 100644 --- a/framework/core/src/Discussion/Search/DiscussionSearcher.php +++ b/framework/core/src/Discussion/Search/DiscussionSearcher.php @@ -18,28 +18,13 @@ use Illuminate\Database\Eloquent\Builder; class DiscussionSearcher extends AbstractSearcher { - /** - * @var DiscussionRepository - */ - protected $discussions; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param DiscussionRepository $discussions - * @param Dispatcher $events - * @param GambitManager $gambits - * @param array $searchMutators - */ - public function __construct(DiscussionRepository $discussions, Dispatcher $events, GambitManager $gambits, array $searchMutators) - { + public function __construct( + protected DiscussionRepository $discussions, + protected Dispatcher $events, + GambitManager $gambits, + array $searchMutators + ) { parent::__construct($gambits, $searchMutators); - - $this->discussions = $discussions; - $this->events = $events; } protected function getQuery(User $actor): Builder diff --git a/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php b/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php index 20cd7227e..5e72febfe 100644 --- a/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php +++ b/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php @@ -17,10 +17,7 @@ use Illuminate\Database\Query\Expression; class FulltextGambit implements GambitInterface { - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $bit) + public function apply(SearchState $search, string $bit): bool { // Replace all non-word characters with spaces. // We do this to prevent MySQL fulltext search boolean mode from taking diff --git a/framework/core/src/Discussion/UserState.php b/framework/core/src/Discussion/UserState.php index 1fb7dd943..1dd7c52c9 100644 --- a/framework/core/src/Discussion/UserState.php +++ b/framework/core/src/Discussion/UserState.php @@ -15,6 +15,7 @@ use Flarum\Discussion\Event\UserRead; use Flarum\Foundation\EventGeneratorTrait; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * Models a discussion-user state record in the database. @@ -25,18 +26,15 @@ use Illuminate\Database\Eloquent\Builder; * * @property int $user_id * @property int $discussion_id - * @property \Carbon\Carbon|null $last_read_at + * @property Carbon|null $last_read_at * @property int|null $last_read_post_number * @property Discussion $discussion - * @property \Flarum\User\User $user + * @property User $user */ class UserState extends AbstractModel { use EventGeneratorTrait; - /** - * {@inheritdoc} - */ protected $table = 'discussion_user'; /** @@ -56,11 +54,8 @@ class UserState extends AbstractModel /** * Mark the discussion as being read up to a certain point. Raises the * DiscussionWasRead event. - * - * @param int $number - * @return $this */ - public function read($number) + public function read(int $number): static { if ($number > $this->last_read_post_number) { $this->last_read_post_number = $number; @@ -72,22 +67,12 @@ class UserState extends AbstractModel return $this; } - /** - * Define the relationship with the discussion that this state is for. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function discussion() + public function discussion(): BelongsTo { return $this->belongsTo(Discussion::class); } - /** - * Define the relationship with the user that this state is for. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } @@ -100,8 +85,9 @@ class UserState extends AbstractModel */ protected function setKeysForSaveQuery($query) { - $query->where('discussion_id', $this->discussion_id) - ->where('user_id', $this->user_id); + $query + ->where('discussion_id', $this->discussion_id) + ->where('user_id', $this->user_id); return $query; } diff --git a/framework/core/src/Discussion/UserStateUpdater.php b/framework/core/src/Discussion/UserStateUpdater.php index 3c90d735d..9f47130e0 100644 --- a/framework/core/src/Discussion/UserStateUpdater.php +++ b/framework/core/src/Discussion/UserStateUpdater.php @@ -14,9 +14,9 @@ use Illuminate\Contracts\Events\Dispatcher; class UserStateUpdater { - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Deleted::class, [$this, 'whenPostWasDeleted']); + $events->listen(Deleted::class, $this->whenPostWasDeleted(...)); } /** @@ -24,7 +24,7 @@ class UserStateUpdater * If user A read a discussion all the way to post number N, and X last posts were deleted, * then we need to update user A's read status to the new N-X post number so that they get notified by new posts. */ - public function whenPostWasDeleted(Deleted $event) + public function whenPostWasDeleted(Deleted $event): void { /* * We check if it's greater because at this point the DiscussionMetadataUpdater should have updated the last post. diff --git a/framework/core/src/Discussion/Utf8SlugDriver.php b/framework/core/src/Discussion/Utf8SlugDriver.php index d0467df49..00b3f4f86 100644 --- a/framework/core/src/Discussion/Utf8SlugDriver.php +++ b/framework/core/src/Discussion/Utf8SlugDriver.php @@ -18,19 +18,13 @@ use Flarum\User\User; */ class Utf8SlugDriver implements SlugDriverInterface { - /** - * @var DiscussionRepository - */ - protected $discussions; - - public function __construct(DiscussionRepository $discussions) - { - $this->discussions = $discussions; + public function __construct( + protected DiscussionRepository $discussions + ) { } /** * @param Discussion $instance - * @return string */ public function toSlug(AbstractModel $instance): string { @@ -42,8 +36,6 @@ class Utf8SlugDriver implements SlugDriverInterface } /** - * @param string $slug - * @param User $actor * @return Discussion */ public function fromSlug(string $slug, User $actor): AbstractModel diff --git a/framework/core/src/Extend/ApiController.php b/framework/core/src/Extend/ApiController.php index b87b84602..8ee6f58c9 100644 --- a/framework/core/src/Extend/ApiController.php +++ b/framework/core/src/Extend/ApiController.php @@ -10,46 +10,51 @@ namespace Flarum\Extend; use Flarum\Api\Controller\AbstractSerializeController; +use Flarum\Api\Serializer\AbstractSerializer; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; +use Psr\Http\Message\ServerRequestInterface; +use Tobscure\JsonApi\Document; class ApiController implements ExtenderInterface { - private $controllerClass; - private $beforeDataCallbacks = []; - private $beforeSerializationCallbacks = []; - private $serializer; - private $addIncludes = []; - private $removeIncludes = []; - private $addOptionalIncludes = []; - private $removeOptionalIncludes = []; - private $limit; - private $maxLimit; - private $addSortFields = []; - private $removeSortFields = []; - private $sort; - private $load = []; - private $loadCallables = []; + private array $beforeDataCallbacks = []; + private array $beforeSerializationCallbacks = []; + private array $serializer; + private array $addIncludes = []; + private array $removeIncludes = []; + private array $addOptionalIncludes = []; + private array $removeOptionalIncludes = []; + private array $limit; + private array $maxLimit; + private array $addSortFields = []; + private array $removeSortFields = []; + private array $sort; + private array $load = []; + private array $loadCallables = []; /** - * @param string $controllerClass: The ::class attribute of the controller you are modifying. + * @param class-string $controllerClass: The ::class attribute of the controller you are modifying. * This controller should extend from \Flarum\Api\Controller\AbstractSerializeController. */ - public function __construct(string $controllerClass) - { - $this->controllerClass = $controllerClass; + public function __construct( + private readonly string $controllerClass + ) { } /** - * @param callable|string $callback + * @template S of AbstractSerializeController + * @param (callable(S $controller): void)|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. * * @return self */ - public function prepareDataQuery($callback): self + public function prepareDataQuery(callable|string $callback): self { $this->beforeDataCallbacks[] = $callback; @@ -57,7 +62,8 @@ class ApiController implements ExtenderInterface } /** - * @param callable|string $callback + * @template S of AbstractSerializeController + * @param (callable(S $controller, mixed $data, ServerRequestInterface $request, Document $document): array)|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -71,7 +77,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function prepareDataForSerialization($callback): self + public function prepareDataForSerialization(callable|string $callback): self { $this->beforeSerializationCallbacks[] = $callback; @@ -81,8 +87,9 @@ class ApiController implements ExtenderInterface /** * Set the serializer that will serialize data for the endpoint. * - * @param string $serializerClass: The ::class attribute of the serializer. - * @param callable|string|null $callback + * @template S of AbstractSerializeController + * @param class-string $serializerClass: The ::class attribute of the serializer. + * @param (callable(S $controller): bool)|string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -92,7 +99,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function setSerializer(string $serializerClass, $callback = null): self + public function setSerializer(string $serializerClass, callable|string $callback = null): self { $this->serializer = [$serializerClass, $callback]; @@ -102,8 +109,9 @@ class ApiController implements ExtenderInterface /** * Include the given relationship by default. * - * @param string|array $name: The name of the relation. - * @param callable|string|null $callback + * @template S of AbstractSerializeController + * @param array|string $name: The name of the relation. + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -113,7 +121,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function addInclude($name, $callback = null): self + public function addInclude(array|string $name, callable|string $callback = null): self { $this->addIncludes[] = [$name, $callback]; @@ -123,8 +131,9 @@ class ApiController implements ExtenderInterface /** * Don't include the given relationship by default. * - * @param string|array $name: The name of the relation. - * @param callable|string|null $callback + * @param array|string $name: The name of the relation. + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -134,7 +143,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function removeInclude($name, $callback = null): self + public function removeInclude(array|string $name, callable|string $callback = null): self { $this->removeIncludes[] = [$name, $callback]; @@ -144,8 +153,9 @@ class ApiController implements ExtenderInterface /** * Make the given relationship available for inclusion. * - * @param string|array $name: The name of the relation. - * @param callable|string|null $callback + * @param array|string $name: The name of the relation. + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -155,7 +165,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function addOptionalInclude($name, $callback = null): self + public function addOptionalInclude(array|string $name, callable|string $callback = null): self { $this->addOptionalIncludes[] = [$name, $callback]; @@ -165,8 +175,9 @@ class ApiController implements ExtenderInterface /** * Don't allow the given relationship to be included. * - * @param string|array $name: The name of the relation. - * @param callable|string|null $callback + * @param array|string $name: The name of the relation. + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -176,7 +187,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function removeOptionalInclude($name, $callback = null): self + public function removeOptionalInclude(array|string $name, callable|string $callback = null): self { $this->removeOptionalIncludes[] = [$name, $callback]; @@ -187,7 +198,8 @@ class ApiController implements ExtenderInterface * Set the default number of results. * * @param int $limit - * @param callable|string|null $callback + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -197,7 +209,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function setLimit(int $limit, $callback = null): self + public function setLimit(int $limit, callable|string $callback = null): self { $this->limit = [$limit, $callback]; @@ -208,7 +220,8 @@ class ApiController implements ExtenderInterface * Set the maximum number of results. * * @param int $max - * @param callable|string|null $callback + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -218,7 +231,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function setMaxLimit(int $max, $callback = null): self + public function setMaxLimit(int $max, callable|string $callback = null): self { $this->maxLimit = [$max, $callback]; @@ -228,8 +241,9 @@ class ApiController implements ExtenderInterface /** * Allow sorting results by the given field. * - * @param string|array $field - * @param callable|string|null $callback + * @param array|string $field + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -239,7 +253,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function addSortField($field, $callback = null): self + public function addSortField(array|string $field, callable|string $callback = null): self { $this->addSortFields[] = [$field, $callback]; @@ -249,8 +263,9 @@ class ApiController implements ExtenderInterface /** * Disallow sorting results by the given field. * - * @param string|array $field - * @param callable|string|null $callback + * @param array|string $field + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -260,7 +275,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function removeSortField($field, $callback = null): self + public function removeSortField(array|string $field, callable|string $callback = null): self { $this->removeSortFields[] = [$field, $callback]; @@ -271,7 +286,8 @@ class ApiController implements ExtenderInterface * Set the default sort order for the results. * * @param array $sort - * @param callable|string|null $callback + * @template S of AbstractSerializeController + * @param (callable(S $controller): bool)|class-string|null $callback * * The optional callback can be a closure or an invokable class, and should accept: * - $controller: An instance of this controller. @@ -281,7 +297,7 @@ class ApiController implements ExtenderInterface * * @return self */ - public function setSort(array $sort, $callback = null): self + public function setSort(array $sort, callable|string $callback = null): self { $this->sort = [$sort, $callback]; @@ -292,7 +308,7 @@ class ApiController implements ExtenderInterface * Eager loads relationships needed for serializer logic. * * First level relationships will be loaded regardless of whether they are included in the response. - * Sublevel relationships will only be loaded if the upper level was included or manually loaded. + * Sub-level relationships will only be loaded if the upper level was included or manually loaded. * * @example If a relationship such as: 'relation.subRelation' is specified, * it will only be loaded if 'relation' is or has been loaded. @@ -302,7 +318,7 @@ class ApiController implements ExtenderInterface * @param string|string[] $relations * @return self */ - public function load($relations): self + public function load(array|string $relations): self { $this->load = array_merge($this->load, array_map('strval', (array) $relations)); @@ -313,23 +329,24 @@ class ApiController implements ExtenderInterface * Allows loading a relationship with additional query modification. * * @param string $relation: Relationship name, see load method description. - * @param array|(callable(\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Relations\Relation, \Psr\Http\Message\ServerRequestInterface|null, array): void) $callback + * @template R of Relation + * @param (callable(Builder|R, \Psr\Http\Message\ServerRequestInterface|null, array): void) $callback * * The callback to modify the query, should accept: - * - \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query: A query object. + * - \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query: A query object. * - \Psr\Http\Message\ServerRequestInterface|null $request: An instance of the request. * - array $relations: An array of relations that are to be loaded. * * @return self */ - public function loadWhere(string $relation, callable $callback): self // @phpstan-ignore-line + public function loadWhere(string $relation, callable $callback): self { $this->loadCallables = array_merge($this->loadCallables, [$relation => $callback]); return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $this->beforeDataCallbacks[] = function (AbstractSerializeController $controller) use ($container) { if (isset($this->serializer) && $this->isApplicable($this->serializer[1], $controller, $container)) { @@ -399,13 +416,7 @@ class ApiController implements ExtenderInterface AbstractSerializeController::setLoadRelationCallables($this->controllerClass, $this->loadCallables); } - /** - * @param callable|string|null $callback - * @param AbstractSerializeController $controller - * @param Container $container - * @return bool - */ - private function isApplicable($callback, AbstractSerializeController $controller, Container $container) + private function isApplicable(callable|string|null $callback, AbstractSerializeController $controller, Container $container): bool { if (! isset($callback)) { return true; diff --git a/framework/core/src/Extend/ApiSerializer.php b/framework/core/src/Extend/ApiSerializer.php index a72e91df7..8448320a1 100644 --- a/framework/core/src/Extend/ApiSerializer.php +++ b/framework/core/src/Extend/ApiSerializer.php @@ -10,31 +10,34 @@ namespace Flarum\Extend; use Flarum\Api\Serializer\AbstractSerializer; +use Flarum\Database\AbstractModel; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; +use Tobscure\JsonApi\Relationship; class ApiSerializer implements ExtenderInterface { - private $serializerClass; - private $attribute = []; - private $attributes = []; - private $relationships = []; + private array $attribute = []; + private array $attributes = []; + private array $relationships = []; /** - * @param string $serializerClass The ::class attribute of the serializer you are modifying. + * @param class-string $serializerClass The ::class attribute of the serializer you are modifying. * This serializer should extend from \Flarum\Api\Serializer\AbstractSerializer. */ - public function __construct(string $serializerClass) - { - $this->serializerClass = $serializerClass; + public function __construct( + private readonly string $serializerClass + ) { } /** * Add a single attribute to this serializer. * + * @template T of AbstractModel + * @template S of AbstractSerializer * @param string $name: The name of the attribute. - * @param callable|string $callback + * @param (callable(S $serializer, T $model, array $attributes): mixed)|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - $serializer: An instance of this serializer. @@ -46,7 +49,7 @@ class ApiSerializer implements ExtenderInterface * * @return self */ - public function attribute(string $name, $callback): self + public function attribute(string $name, callable|string $callback): self { $this->attribute[$name] = $callback; @@ -56,7 +59,7 @@ class ApiSerializer implements ExtenderInterface /** * Add to or modify the attributes array of this serializer. * - * @param callable|string $callback + * @param (callable(AbstractSerializer $serializer, AbstractModel $model, array $attributes): array)|string $callback * * The callback can be a closure or an invokable class, and should accept: * - $serializer: An instance of this serializer. @@ -69,7 +72,7 @@ class ApiSerializer implements ExtenderInterface * * @return self */ - public function attributes($callback): self + public function attributes(callable|string $callback): self { $this->attributes[] = $callback; @@ -115,7 +118,9 @@ class ApiSerializer implements ExtenderInterface * * @param string $name: The name of the relation. Has to be unique from other relation names. * The relation has to exist in the model handled by this serializer. - * @param callable|string $callback + * @template T of AbstractModel + * @template S of AbstractSerializer + * @param (callable(S $serializer, T $model): Relationship)|class-string $callback * * The callable can be a closure or an invokable class, and should accept: * - $serializer: An instance of this serializer. @@ -126,14 +131,14 @@ class ApiSerializer implements ExtenderInterface * * @return self */ - public function relationship(string $name, $callback): self + public function relationship(string $name, callable|string $callback): self { $this->relationships[$this->serializerClass][$name] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (! empty($this->attribute)) { $this->attributes[] = function ($serializer, $model, $attributes) use ($container) { diff --git a/framework/core/src/Extend/Auth.php b/framework/core/src/Extend/Auth.php index 66f5e764c..7013e1a1f 100644 --- a/framework/core/src/Extend/Auth.php +++ b/framework/core/src/Extend/Auth.php @@ -15,8 +15,8 @@ use Illuminate\Contracts\Container\Container; class Auth implements ExtenderInterface { - private $addPasswordCheckers = []; - private $removePasswordCheckers = []; + private array $addPasswordCheckers = []; + private array $removePasswordCheckers = []; /** * Add a new password checker. @@ -38,7 +38,7 @@ class Auth implements ExtenderInterface * * @return self */ - public function addPasswordChecker(string $identifier, $callback): self + public function addPasswordChecker(string $identifier, callable|string $callback): self { $this->addPasswordCheckers[$identifier] = $callback; @@ -58,7 +58,7 @@ class Auth implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.user.password_checkers', function ($passwordCheckers) use ($container) { foreach ($this->removePasswordCheckers as $identifier) { diff --git a/framework/core/src/Extend/Conditional.php b/framework/core/src/Extend/Conditional.php index b9bbc764a..3630063ec 100644 --- a/framework/core/src/Extend/Conditional.php +++ b/framework/core/src/Extend/Conditional.php @@ -18,7 +18,7 @@ class Conditional implements ExtenderInterface /** * @var array */ - protected $conditions = []; + protected array $conditions = []; /** * @param ExtenderInterface[] $extenders @@ -30,11 +30,7 @@ class Conditional implements ExtenderInterface }, $extenders); } - /** - * @param bool|callable $condition - * @param ExtenderInterface[] $extenders - */ - public function when($condition, array $extenders): self + public function when(callable|bool $condition, array $extenders): self { $this->conditions[] = [ 'condition' => $condition, @@ -44,7 +40,7 @@ class Conditional implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { foreach ($this->conditions as $condition) { if (is_callable($condition['condition'])) { diff --git a/framework/core/src/Extend/Console.php b/framework/core/src/Extend/Console.php index dfa1945a2..40492c2cc 100644 --- a/framework/core/src/Extend/Console.php +++ b/framework/core/src/Extend/Console.php @@ -9,18 +9,19 @@ namespace Flarum\Extend; +use Flarum\Console\AbstractCommand; use Flarum\Extension\Extension; use Illuminate\Contracts\Container\Container; class Console implements ExtenderInterface { - protected $addCommands = []; - protected $scheduled = []; + protected array $addCommands = []; + protected array $scheduled = []; /** * Add a command to the console. * - * @param string $command: ::class attribute of command class, which must extend Flarum\Console\AbstractCommand. + * @param class-string $command: ::class attribute of command class, which must extend \Flarum\Console\AbstractCommand. * @return self */ public function command(string $command): self @@ -33,8 +34,8 @@ class Console implements ExtenderInterface /** * Schedule a command to run on an interval. * - * @param string $command: ::class attribute of command class, which must extend Flarum\Console\AbstractCommand. - * @param callable|string $callback + * @param class-string $command: ::class attribute of command class, which must extend Flarum\Console\AbstractCommand. + * @param (callable(\Illuminate\Console\Scheduling\Event $event): void)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \Illuminate\Console\Scheduling\Event $event @@ -48,14 +49,14 @@ class Console implements ExtenderInterface * @param array $args An array of args to call the command with. * @return self */ - public function schedule(string $command, $callback, $args = []): self + public function schedule(string $command, callable|string $callback, array $args = []): self { $this->scheduled[] = compact('args', 'callback', 'command'); return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.console.commands', function ($existingCommands) { return array_merge($existingCommands, $this->addCommands); diff --git a/framework/core/src/Extend/Csrf.php b/framework/core/src/Extend/Csrf.php index d4d6d2e0f..a60033af4 100644 --- a/framework/core/src/Extend/Csrf.php +++ b/framework/core/src/Extend/Csrf.php @@ -14,7 +14,7 @@ use Illuminate\Contracts\Container\Container; class Csrf implements ExtenderInterface { - protected $csrfExemptRoutes = []; + protected array $csrfExemptRoutes = []; /** * Exempt a named route from CSRF checks. @@ -29,7 +29,7 @@ class Csrf implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.http.csrfExemptPaths', function ($existingExemptPaths) { return array_merge($existingExemptPaths, $this->csrfExemptRoutes); diff --git a/framework/core/src/Extend/ErrorHandling.php b/framework/core/src/Extend/ErrorHandling.php index 135c795e5..15b1d1f42 100644 --- a/framework/core/src/Extend/ErrorHandling.php +++ b/framework/core/src/Extend/ErrorHandling.php @@ -15,10 +15,10 @@ use Illuminate\Contracts\Container\Container; class ErrorHandling implements ExtenderInterface { - private $statuses = []; - private $types = []; - private $handlers = []; - private $reporters = []; + private array $statuses = []; + private array $types = []; + private array $handlers = []; + private array $reporters = []; /** * Define the corresponding HTTP status code for a well-known error type. @@ -67,7 +67,7 @@ class ErrorHandling implements ExtenderInterface * When Flarum's default error handling is not enough for you, and the other * methods of this extender don't help, this is the place where you can go * wild! Using this method, you can define a handler class (second - * parameter) that will be responsible for exceptions of a certain type + * parameter) that will be responsible for exceptions to a certain type * (first parameter). * * The handler class must implement a handle() method (surprise!), which @@ -96,9 +96,9 @@ class ErrorHandling implements ExtenderInterface * administrators are notified about the error. * * When passing in a reporter class, make sure that it implements the - * {@see \Flarum\Foundation\ErrorHandling\Reporter} interface. + * {@see Reporter} interface. * - * @param string $reporterClass: The ::class attribute of the reporter class. + * @param class-string $reporterClass: The ::class attribute of the reporter class. * @return self */ public function reporter(string $reporterClass): self @@ -108,7 +108,7 @@ class ErrorHandling implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (count($this->statuses)) { $container->extend('flarum.error.statuses', function ($statuses) { diff --git a/framework/core/src/Extend/Event.php b/framework/core/src/Extend/Event.php index 98cc091e8..07b8b6eac 100644 --- a/framework/core/src/Extend/Event.php +++ b/framework/core/src/Extend/Event.php @@ -15,8 +15,8 @@ use Illuminate\Contracts\Events\Dispatcher; class Event implements ExtenderInterface { - private $listeners = []; - private $subscribers = []; + private array $listeners = []; + private array $subscribers = []; /** * Add a listener to a domain event dispatched by flarum or a flarum extension. @@ -32,7 +32,7 @@ class Event implements ExtenderInterface * * @return self */ - public function listen(string $event, $listener): self + public function listen(string $event, callable|string $listener): self { $this->listeners[] = [$event, $listener]; @@ -56,7 +56,7 @@ class Event implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $events = $container->make(Dispatcher::class); diff --git a/framework/core/src/Extend/ExtenderInterface.php b/framework/core/src/Extend/ExtenderInterface.php index f43e5afe2..f6ecf9155 100644 --- a/framework/core/src/Extend/ExtenderInterface.php +++ b/framework/core/src/Extend/ExtenderInterface.php @@ -14,5 +14,5 @@ use Illuminate\Contracts\Container\Container; interface ExtenderInterface { - public function extend(Container $container, Extension $extension = null); + public function extend(Container $container, Extension $extension = null): void; } diff --git a/framework/core/src/Extend/Filesystem.php b/framework/core/src/Extend/Filesystem.php index 4e2f2ec59..fa49162e5 100644 --- a/framework/core/src/Extend/Filesystem.php +++ b/framework/core/src/Extend/Filesystem.php @@ -11,12 +11,14 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; +use Flarum\Foundation\Paths; +use Flarum\Http\UrlGenerator; use Illuminate\Contracts\Container\Container; class Filesystem implements ExtenderInterface { - private $disks = []; - private $drivers = []; + private array $disks = []; + private array $drivers = []; /** * Declare a new filesystem disk. @@ -29,7 +31,7 @@ class Filesystem implements ExtenderInterface * To declare a new disk, you must provide default configuration a "local" driver. * * @param string $name: The name of the disk. - * @param string|callable $callback + * @param (callable(Paths $paths, UrlGenerator $url): array)|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - \Flarum\Foundation\Paths $paths @@ -53,7 +55,7 @@ class Filesystem implements ExtenderInterface * * @return self */ - public function disk(string $name, $callback): self + public function disk(string $name, callable|string $callback): self { $this->disks[$name] = $callback; @@ -75,7 +77,7 @@ class Filesystem implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.filesystem.disks', function ($existingDisks) use ($container) { foreach ($this->disks as $name => $disk) { diff --git a/framework/core/src/Extend/Filter.php b/framework/core/src/Extend/Filter.php index 3fa0d1d50..cfc54c476 100644 --- a/framework/core/src/Extend/Filter.php +++ b/framework/core/src/Extend/Filter.php @@ -10,20 +10,22 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\Filter\AbstractFilterer; +use Flarum\Filter\FilterState; +use Flarum\Query\QueryCriteria; use Illuminate\Contracts\Container\Container; class Filter implements ExtenderInterface { - private $filtererClass; - private $filters = []; - private $filterMutators = []; + private array $filters = []; + private array $filterMutators = []; /** - * @param string $filtererClass: The ::class attribute of the filterer to extend. + * @param class-string $filtererClass: The ::class attribute of the filterer to extend. */ - public function __construct($filtererClass) - { - $this->filtererClass = $filtererClass; + public function __construct( + private readonly string $filtererClass + ) { } /** @@ -42,7 +44,7 @@ class Filter implements ExtenderInterface /** * Add a callback through which to run all filter queries after filters have been applied. * - * @param callable|string $callback + * @param (callable(FilterState $filter, QueryCriteria $criteria): void)|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - Flarum\Filter\FilterState $filter @@ -52,14 +54,14 @@ class Filter implements ExtenderInterface * * @return self */ - public function addFilterMutator($callback): self + public function addFilterMutator(callable|string $callback): self { $this->filterMutators[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.filter.filters', function ($originalFilters) { foreach ($this->filters as $filter) { @@ -68,6 +70,7 @@ class Filter implements ExtenderInterface return $originalFilters; }); + $container->extend('flarum.filter.filter_mutators', function ($originalMutators) { foreach ($this->filterMutators as $mutator) { $originalMutators[$this->filtererClass][] = $mutator; diff --git a/framework/core/src/Extend/Formatter.php b/framework/core/src/Extend/Formatter.php index 1d8a3b5f4..4e3f24964 100644 --- a/framework/core/src/Extend/Formatter.php +++ b/framework/core/src/Extend/Formatter.php @@ -13,20 +13,24 @@ use Flarum\Extension\Extension; use Flarum\Formatter\Formatter as ActualFormatter; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; +use Psr\Http\Message\ServerRequestInterface; +use s9e\TextFormatter\Configurator; +use s9e\TextFormatter\Parser; +use s9e\TextFormatter\Renderer; class Formatter implements ExtenderInterface, LifecycleInterface { - private $configurationCallbacks = []; - private $parsingCallbacks = []; - private $unparsingCallbacks = []; - private $renderingCallbacks = []; + private array $configurationCallbacks = []; + private array $parsingCallbacks = []; + private array $unparsingCallbacks = []; + private array $renderingCallbacks = []; /** * Configure the formatter. This can be used to add support for custom markdown/bbcode/etc tags, * or otherwise change the formatter. Please see documentation for the s9e text formatter library for more * information on how to use this. * - * @param callable|string $callback + * @param (callable(Configurator $configurator): void)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \s9e\TextFormatter\Configurator $configurator @@ -35,7 +39,7 @@ class Formatter implements ExtenderInterface, LifecycleInterface * * @return self */ - public function configure($callback): self + public function configure(callable|string $callback): self { $this->configurationCallbacks[] = $callback; @@ -46,7 +50,7 @@ class Formatter implements ExtenderInterface, LifecycleInterface * Prepare the system for parsing. This can be used to modify the text that will be parsed, or to modify the parser. * Please note that the text to be parsed must be returned, regardless of whether it's changed. * - * @param callable|string $callback + * @param (callable(Parser $parser, mixed $context, string $text, ?\Flarum\User\User $actor): string)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \s9e\TextFormatter\Parser $parser @@ -59,7 +63,7 @@ class Formatter implements ExtenderInterface, LifecycleInterface * * @return self */ - public function parse($callback): self + public function parse(callable|string $callback): self { $this->parsingCallbacks[] = $callback; @@ -70,7 +74,7 @@ class Formatter implements ExtenderInterface, LifecycleInterface * Prepare the system for unparsing. This can be used to modify the text that was parsed. * Please note that the parsed text must be returned, regardless of whether it's changed. * - * @param callable|string $callback + * @param (callable(mixed $context, string $xml): string)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - mixed $context @@ -81,7 +85,7 @@ class Formatter implements ExtenderInterface, LifecycleInterface * * @return self */ - public function unparse($callback): self + public function unparse(callable|string $callback): self { $this->unparsingCallbacks[] = $callback; @@ -92,7 +96,7 @@ class Formatter implements ExtenderInterface, LifecycleInterface * Prepare the system for rendering. This can be used to modify the xml that will be rendered, or to modify the renderer. * Please note that the xml to be rendered must be returned, regardless of whether it's changed. * - * @param callable|string $callback + * @param (callable(Renderer $renderer, mixed $context, string $xml, ServerRequestInterface $request): string)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \s9e\TextFormatter\Renderer $renderer @@ -105,14 +109,14 @@ class Formatter implements ExtenderInterface, LifecycleInterface * * @return self */ - public function render($callback): self + public function render(callable|string $callback): self { $this->renderingCallbacks[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.formatter', function ($formatter, $container) { foreach ($this->configurationCallbacks as $callback) { @@ -135,13 +139,13 @@ class Formatter implements ExtenderInterface, LifecycleInterface }); } - public function onEnable(Container $container, Extension $extension) + public function onEnable(Container $container, Extension $extension): void { // FLush the formatter cache when this extension is enabled $container->make(ActualFormatter::class)->flush(); } - public function onDisable(Container $container, Extension $extension) + public function onDisable(Container $container, Extension $extension): void { // FLush the formatter cache when this extension is disabled $container->make(ActualFormatter::class)->flush(); diff --git a/framework/core/src/Extend/Frontend.php b/framework/core/src/Extend/Frontend.php index 1bab3522d..82abbb389 100644 --- a/framework/core/src/Extend/Frontend.php +++ b/framework/core/src/Extend/Frontend.php @@ -17,6 +17,7 @@ use Flarum\Foundation\Event\ClearingCache; use Flarum\Frontend\Assets; use Flarum\Frontend\Compiler\Source\SourceCollector; use Flarum\Frontend\Document; +use Flarum\Frontend\Driver\TitleDriverInterface; use Flarum\Frontend\Frontend as ActualFrontend; use Flarum\Frontend\RecompileFrontendAssets; use Flarum\Http\RouteCollection; @@ -24,25 +25,24 @@ use Flarum\Http\RouteHandlerFactory; use Flarum\Locale\LocaleManager; use Flarum\Settings\Event\Saved; use Illuminate\Contracts\Container\Container; +use Psr\Http\Message\ServerRequestInterface; class Frontend implements ExtenderInterface { - private $frontend; - - private $css = []; - private $js; - private $routes = []; - private $removedRoutes = []; - private $content = []; - private $preloadArrs = []; - private $titleDriver; + private array $css = []; + private ?string $js = null; + private array $routes = []; + private array $removedRoutes = []; + private array $content = []; + private array $preloadArrs = []; + private ?string $titleDriver = null; /** * @param string $frontend: The name of the frontend. */ - public function __construct(string $frontend) - { - $this->frontend = $frontend; + public function __construct( + private readonly string $frontend + ) { } /** @@ -76,7 +76,7 @@ class Frontend implements ExtenderInterface * * @param string $path: The path of the route. * @param string $name: The name of the route, must be unique. - * @param callable|string|null $content + * @param (callable(Document $document, ServerRequestInterface $request): void)|class-string|null $content * * The content can be a closure or an invokable class, and should accept: * - \Flarum\Frontend\Document $document @@ -86,7 +86,7 @@ class Frontend implements ExtenderInterface * * @return self */ - public function route(string $path, string $name, $content = null): self + public function route(string $path, string $name, callable|string $content = null): self { $this->routes[] = compact('path', 'name', 'content'); @@ -110,7 +110,7 @@ class Frontend implements ExtenderInterface /** * Modify the content of the frontend. * - * @param callable|string|null $callback + * @param (callable(Document $document, ServerRequestInterface $request): void)|class-string|null $callback * * The content can be a closure or an invokable class, and should accept: * - \Flarum\Frontend\Document $document @@ -120,7 +120,7 @@ class Frontend implements ExtenderInterface * * @return self */ - public function content($callback): self + public function content(callable|string|null $callback): self { $this->content[] = $callback; @@ -153,7 +153,7 @@ class Frontend implements ExtenderInterface * @param callable|array $preloads * @return self */ - public function preloads($preloads): self + public function preloads(callable|array $preloads): self { $this->preloadArrs[] = $preloads; @@ -162,6 +162,8 @@ class Frontend implements ExtenderInterface /** * Register a new title driver to change the title of frontend documents. + * + * @param class-string $driverClass */ public function title(string $driverClass): self { @@ -170,7 +172,7 @@ class Frontend implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $this->registerAssets($container, $this->getModuleName($extension)); $this->registerRoutes($container); diff --git a/framework/core/src/Extend/LanguagePack.php b/framework/core/src/Extend/LanguagePack.php index 96cc87503..eeafd126a 100644 --- a/framework/core/src/Extend/LanguagePack.php +++ b/framework/core/src/Extend/LanguagePack.php @@ -26,19 +26,17 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface 'validation', ]; - private $path; - /** * LanguagePack constructor. * * @param string $path: Path to yaml language files. */ - public function __construct(string $path = '/locale') - { - $this->path = $path; + public function __construct( + private readonly string $path = '/locale' + ) { } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (is_null($extension)) { throw new InvalidArgumentException( @@ -63,7 +61,7 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface ); } - private function registerLocale(Container $container, LocaleManager $locales, Extension $extension, $locale, $title) + private function registerLocale(Container $container, LocaleManager $locales, Extension $extension, $locale, $title): void { $locales->addLocale($locale, $title); @@ -90,7 +88,7 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface } } - private function shouldLoad(SplFileInfo $file, Container $container) + private function shouldLoad(SplFileInfo $file, Container $container): bool { if (! $file->isFile()) { return false; @@ -122,12 +120,12 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface return $extensions->isEnabled($slug); } - public function onEnable(Container $container, Extension $extension) + public function onEnable(Container $container, Extension $extension): void { $container->make('flarum.locales')->clearCache(); } - public function onDisable(Container $container, Extension $extension) + public function onDisable(Container $container, Extension $extension): void { $container->make('flarum.locales')->clearCache(); } diff --git a/framework/core/src/Extend/LifecycleInterface.php b/framework/core/src/Extend/LifecycleInterface.php index cde5a9dc9..c025227f7 100644 --- a/framework/core/src/Extend/LifecycleInterface.php +++ b/framework/core/src/Extend/LifecycleInterface.php @@ -14,7 +14,7 @@ use Illuminate\Contracts\Container\Container; interface LifecycleInterface { - public function onEnable(Container $container, Extension $extension); + public function onEnable(Container $container, Extension $extension): void; - public function onDisable(Container $container, Extension $extension); + public function onDisable(Container $container, Extension $extension): void; } diff --git a/framework/core/src/Extend/Link.php b/framework/core/src/Extend/Link.php index e3669876a..6163c9a86 100644 --- a/framework/core/src/Extend/Link.php +++ b/framework/core/src/Extend/Link.php @@ -9,6 +9,7 @@ namespace Flarum\Extend; +use Closure; use Flarum\Extension\Extension; use Flarum\Foundation\Config; use Illuminate\Contracts\Container\Container; @@ -18,24 +19,24 @@ use s9e\TextFormatter\Utils; class Link implements ExtenderInterface { - protected $setRel = null; - protected $setTarget = null; + protected Closure|null $setRel = null; + protected Closure|null $setTarget = null; - public function setRel(callable $callable) + public function setRel(Closure $callable): self { $this->setRel = $callable; return $this; } - public function setTarget(callable $callable) + public function setTarget(Closure $callable): self { $this->setTarget = $callable; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $siteUrl = $container->make(Config::class)->url(); diff --git a/framework/core/src/Extend/Locales.php b/framework/core/src/Extend/Locales.php index 9ad953420..3fe491032 100644 --- a/framework/core/src/Extend/Locales.php +++ b/framework/core/src/Extend/Locales.php @@ -17,17 +17,15 @@ use Symfony\Component\Translation\MessageCatalogueInterface; class Locales implements ExtenderInterface, LifecycleInterface { - private $directory; - /** * @param string $directory: Directory of the locale files. */ - public function __construct(string $directory) - { - $this->directory = $directory; + public function __construct( + private readonly string $directory + ) { } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->resolving( LocaleManager::class, @@ -56,12 +54,12 @@ class Locales implements ExtenderInterface, LifecycleInterface ); } - public function onEnable(Container $container, Extension $extension) + public function onEnable(Container $container, Extension $extension): void { $container->make(LocaleManager::class)->clearCache(); } - public function onDisable(Container $container, Extension $extension) + public function onDisable(Container $container, Extension $extension): void { $container->make(LocaleManager::class)->clearCache(); } diff --git a/framework/core/src/Extend/Mail.php b/framework/core/src/Extend/Mail.php index 217c5da77..3a9cbd100 100644 --- a/framework/core/src/Extend/Mail.php +++ b/framework/core/src/Extend/Mail.php @@ -10,17 +10,18 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\Mail\DriverInterface; use Illuminate\Contracts\Container\Container; class Mail implements ExtenderInterface { - private $drivers = []; + private array $drivers = []; /** * Add a mail driver. * * @param string $identifier: Identifier for mail driver. E.g. 'smtp' for SmtpDriver. - * @param string $driver: ::class attribute of driver class, which must implement Flarum\Mail\DriverInterface. + * @param class-string $driver: ::class attribute of driver class, which must implement \Flarum\Mail\DriverInterface. * @return self */ public function driver(string $identifier, string $driver): self @@ -30,7 +31,7 @@ class Mail implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('mail.supported_drivers', function ($existingDrivers) { return array_merge($existingDrivers, $this->drivers); diff --git a/framework/core/src/Extend/Middleware.php b/framework/core/src/Extend/Middleware.php index e22f3e458..021b504b9 100644 --- a/framework/core/src/Extend/Middleware.php +++ b/framework/core/src/Extend/Middleware.php @@ -11,28 +11,28 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; use Illuminate\Contracts\Container\Container; +use Psr\Http\Server\MiddlewareInterface; class Middleware implements ExtenderInterface { - private $addMiddlewares = []; - private $removeMiddlewares = []; - private $replaceMiddlewares = []; - private $insertBeforeMiddlewares = []; - private $insertAfterMiddlewares = []; - private $frontend; + private array $addMiddlewares = []; + private array $removeMiddlewares = []; + private array $replaceMiddlewares = []; + private array $insertBeforeMiddlewares = []; + private array $insertAfterMiddlewares = []; /** * @param string $frontend: The name of the frontend. */ - public function __construct(string $frontend) - { - $this->frontend = $frontend; + public function __construct( + private readonly string $frontend + ) { } /** * Adds a new middleware to the frontend. * - * @param string $middleware: ::class attribute of the middleware class. + * @param class-string $middleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ @@ -46,9 +46,9 @@ class Middleware implements ExtenderInterface /** * Replaces an existing middleware of the frontend. * - * @param string $originalMiddleware: ::class attribute of the original middleware class. + * @param class-string $originalMiddleware: ::class attribute of the original middleware class. * Or container binding name. - * @param string $newMiddleware: ::class attribute of the middleware class. + * @param class-string $newMiddleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ @@ -62,7 +62,7 @@ class Middleware implements ExtenderInterface /** * Removes a middleware from the frontend. * - * @param string $middleware: ::class attribute of the middleware class. + * @param class-string $middleware: ::class attribute of the middleware class. * @return self */ public function remove(string $middleware): self @@ -75,9 +75,9 @@ class Middleware implements ExtenderInterface /** * Inserts a middleware before an existing middleware. * - * @param string $originalMiddleware: ::class attribute of the original middleware class. + * @param class-string $originalMiddleware: ::class attribute of the original middleware class. * Or container binding name. - * @param string $newMiddleware: ::class attribute of the middleware class. + * @param class-string $newMiddleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ @@ -91,9 +91,9 @@ class Middleware implements ExtenderInterface /** * Inserts a middleware after an existing middleware. * - * @param string $originalMiddleware: ::class attribute of the original middleware class. + * @param class-string $originalMiddleware: ::class attribute of the original middleware class. * Or container binding name. - * @param string $newMiddleware: ::class attribute of the middleware class. + * @param class-string $newMiddleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ @@ -104,9 +104,9 @@ class Middleware implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { - $container->extend("flarum.{$this->frontend}.middleware", function ($existingMiddleware) { + $container->extend("flarum.$this->frontend.middleware", function ($existingMiddleware) { foreach ($this->addMiddlewares as $addMiddleware) { $existingMiddleware[] = $addMiddleware; } @@ -139,9 +139,7 @@ class Middleware implements ExtenderInterface ); } - $existingMiddleware = array_diff($existingMiddleware, $this->removeMiddlewares); - - return $existingMiddleware; + return array_diff($existingMiddleware, $this->removeMiddlewares); }); } } diff --git a/framework/core/src/Extend/Model.php b/framework/core/src/Extend/Model.php index 3b26fe729..e1f4229f0 100644 --- a/framework/core/src/Extend/Model.php +++ b/framework/core/src/Extend/Model.php @@ -13,21 +13,21 @@ use Flarum\Database\AbstractModel; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Arr; class Model implements ExtenderInterface { - private $modelClass; - private $customRelations = []; - private $casts = []; + private array $customRelations = []; + private array $casts = []; /** - * @param string $modelClass: The ::class attribute of the model you are modifying. + * @param class-string $modelClass: The ::class attribute of the model you are modifying. * This model should extend from \Flarum\Database\AbstractModel. */ - public function __construct(string $modelClass) - { - $this->modelClass = $modelClass; + public function __construct( + private readonly string $modelClass + ) { } /** @@ -67,7 +67,7 @@ class Model implements ExtenderInterface * @param mixed $value * @return self */ - public function default(string $attribute, $value): self + public function default(string $attribute, mixed $value): self { Arr::set(AbstractModel::$defaults, "$this->modelClass.$attribute", $value); @@ -83,11 +83,11 @@ class Model implements ExtenderInterface * but has to be unique from other relation names for this model, and should * work as the name of a method. * @param string $related: The ::class attribute of the model, which should extend \Flarum\Database\AbstractModel. - * @param string $foreignKey: The foreign key attribute of the parent model. - * @param string $ownerKey: The primary key attribute of the parent model. + * @param string|null $foreignKey: The foreign key attribute of the parent model. + * @param string|null $ownerKey: The primary key attribute of the parent model. * @return self */ - public function belongsTo(string $name, string $related, string $foreignKey = null, string $ownerKey = null): self + public function belongsTo(string $name, string $related, ?string $foreignKey = null, ?string $ownerKey = null): self { return $this->relationship($name, function (AbstractModel $model) use ($related, $foreignKey, $ownerKey, $name) { return $model->belongsTo($related, $foreignKey, $ownerKey, $name); @@ -103,21 +103,21 @@ class Model implements ExtenderInterface * but has to be unique from other relation names for this model, and should * work as the name of a method. * @param string $related: The ::class attribute of the model, which should extend \Flarum\Database\AbstractModel. - * @param string $table: The intermediate table for this relation - * @param string $foreignPivotKey: The foreign key attribute of the parent model. - * @param string $relatedPivotKey: The associated key attribute of the relation. - * @param string $parentKey: The key name of the parent model. - * @param string $relatedKey: The key name of the related model. + * @param string|null $table: The intermediate table for this relation + * @param string|null $foreignPivotKey: The foreign key attribute of the parent model. + * @param string|null $relatedPivotKey: The associated key attribute of the relation. + * @param string|null $parentKey: The key name of the parent model. + * @param string|null $relatedKey: The key name of the related model. * @return self */ public function belongsToMany( string $name, string $related, - string $table = null, - string $foreignPivotKey = null, - string $relatedPivotKey = null, - string $parentKey = null, - string $relatedKey = null + ?string $table = null, + ?string $foreignPivotKey = null, + ?string $relatedPivotKey = null, + ?string $parentKey = null, + ?string $relatedKey = null ): self { return $this->relationship($name, function (AbstractModel $model) use ($related, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey, $name) { return $model->belongsToMany($related, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey, $name); @@ -133,11 +133,11 @@ class Model implements ExtenderInterface * but has to be unique from other relation names for this model, and should * work as the name of a method. * @param string $related: The ::class attribute of the model, which should extend \Flarum\Database\AbstractModel. - * @param string $foreignKey: The foreign key attribute of the parent model. - * @param string $localKey: The primary key attribute of the parent model. + * @param string|null $foreignKey: The foreign key attribute of the parent model. + * @param string|null $localKey: The primary key attribute of the parent model. * @return self */ - public function hasOne(string $name, string $related, string $foreignKey = null, string $localKey = null): self + public function hasOne(string $name, string $related, ?string $foreignKey = null, ?string $localKey = null): self { return $this->relationship($name, function (AbstractModel $model) use ($related, $foreignKey, $localKey) { return $model->hasOne($related, $foreignKey, $localKey); @@ -153,11 +153,11 @@ class Model implements ExtenderInterface * but has to be unique from other relation names for this model, and should * work as the name of a method. * @param string $related: The ::class attribute of the model, which should extend \Flarum\Database\AbstractModel. - * @param string $foreignKey: The foreign key attribute of the parent model. - * @param string $localKey: The primary key attribute of the parent model. + * @param string|null $foreignKey: The foreign key attribute of the parent model. + * @param string|null $localKey: The primary key attribute of the parent model. * @return self */ - public function hasMany(string $name, string $related, string $foreignKey = null, string $localKey = null): self + public function hasMany(string $name, string $related, ?string $foreignKey = null, ?string $localKey = null): self { return $this->relationship($name, function (AbstractModel $model) use ($related, $foreignKey, $localKey) { return $model->hasMany($related, $foreignKey, $localKey); @@ -170,7 +170,9 @@ class Model implements ExtenderInterface * @param string $name: The name of the relation. This doesn't have to be anything in particular, * but has to be unique from other relation names for this model, and should * work as the name of a method. - * @param callable|string $callback + * @template T of AbstractModel + * @template R of Relation + * @param (callable(T $instance): R)|class-string $callback * * The callable can be a closure or invokable class, and should accept: * - $instance: An instance of this model. @@ -181,14 +183,14 @@ class Model implements ExtenderInterface * * @return self */ - public function relationship(string $name, $callback): self + public function relationship(string $name, callable|string $callback): self { $this->customRelations[$name] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { foreach ($this->customRelations as $name => $callback) { Arr::set(AbstractModel::$customRelations, "$this->modelClass.$name", ContainerUtil::wrapCallback($callback, $container)); diff --git a/framework/core/src/Extend/ModelPrivate.php b/framework/core/src/Extend/ModelPrivate.php index 9b64c5c37..3eb378e20 100644 --- a/framework/core/src/Extend/ModelPrivate.php +++ b/framework/core/src/Extend/ModelPrivate.php @@ -9,6 +9,7 @@ namespace Flarum\Extend; +use Flarum\Database\AbstractModel; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; @@ -33,22 +34,22 @@ use Illuminate\Contracts\Container\Container; */ class ModelPrivate implements ExtenderInterface { - private $modelClass; private $checkers = []; /** - * @param string $modelClass: The ::class attribute of the model you are applying private checkers to. + * @param class-string $modelClass: The ::class attribute of the model you are applying private checkers to. * This model must have a `is_private` field. */ - public function __construct(string $modelClass) - { - $this->modelClass = $modelClass; + public function __construct( + private readonly string $modelClass + ) { } /** * Add a model privacy checker. * - * @param callable|string $callback + * @template T of AbstractModel + * @param (callable(T $instance): ?bool)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \Flarum\Database\AbstractModel $instance: An instance of the model. @@ -57,14 +58,14 @@ class ModelPrivate implements ExtenderInterface * * @return self */ - public function checker($callback): self + public function checker(callable|string $callback): self { $this->checkers[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (! class_exists($this->modelClass)) { return; diff --git a/framework/core/src/Extend/ModelUrl.php b/framework/core/src/Extend/ModelUrl.php index c03b3516d..80ef5f824 100644 --- a/framework/core/src/Extend/ModelUrl.php +++ b/framework/core/src/Extend/ModelUrl.php @@ -9,22 +9,22 @@ namespace Flarum\Extend; +use Flarum\Database\AbstractModel; use Flarum\Extension\Extension; use Illuminate\Contracts\Container\Container; use Illuminate\Support\Arr; class ModelUrl implements ExtenderInterface { - private $modelClass; - private $slugDrivers = []; + private array $slugDrivers = []; /** - * @param string $modelClass: The ::class attribute of the model you are modifying. + * @param class-string $modelClass: The ::class attribute of the model you are modifying. * This model should extend from \Flarum\Database\AbstractModel. */ - public function __construct(string $modelClass) - { - $this->modelClass = $modelClass; + public function __construct( + private readonly string $modelClass + ) { } /** @@ -41,7 +41,7 @@ class ModelUrl implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if ($this->slugDrivers) { $container->extend('flarum.http.slugDrivers', function ($existingDrivers) { diff --git a/framework/core/src/Extend/ModelVisibility.php b/framework/core/src/Extend/ModelVisibility.php index 6110d89c8..8cf885640 100644 --- a/framework/core/src/Extend/ModelVisibility.php +++ b/framework/core/src/Extend/ModelVisibility.php @@ -10,9 +10,12 @@ namespace Flarum\Extend; use Exception; +use Flarum\Database\AbstractModel; +use Flarum\Database\ScopeVisibilityTrait; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; +use Illuminate\Database\Eloquent\Builder; /** * Model visibility scoping allows us to scope queries based on the current user. @@ -31,28 +34,26 @@ use Illuminate\Contracts\Container\Container; */ class ModelVisibility implements ExtenderInterface { - private $modelClass; - private $scopers = []; - private $allScopers = []; + private array $scopers = []; + private array $allScopers = []; /** - * @param string $modelClass: The ::class attribute of the model you are applying scopers to. + * @param class-string $modelClass: The ::class attribute of the model you are applying scopers to. * This model must extend from \Flarum\Database\AbstractModel, * and use \Flarum\Database\ScopeVisibilityTrait. */ - public function __construct(string $modelClass) - { - $this->modelClass = $modelClass; - - if (class_exists($this->modelClass) && ! is_callable([$modelClass, 'registerVisibilityScoper'])) { - throw new Exception("Model $modelClass cannot be visibility scoped as it does not use Flarum\Database\ScopeVisibilityTrait."); + public function __construct( + private readonly string $modelClass + ) { + if (class_exists($modelClass) && ! is_callable([$modelClass, 'registerVisibilityScoper'])) { + throw new Exception("Model $modelClass cannot be visibility scoped as it does not use ".ScopeVisibilityTrait::class.'.'); } } /** * Add a scoper for a given ability. * - * @param callable|string $callback + * @param (callable(\Flarum\User\User $actor, Builder $query): void)|class-string $callback * @param string $ability: Defaults to 'view'. * * The callback can be a closure or invokable class, and should accept: @@ -63,7 +64,7 @@ class ModelVisibility implements ExtenderInterface * * @return self */ - public function scope($callback, string $ability = 'view'): self + public function scope(callable|string $callback, string $ability = 'view'): self { $this->scopers[$ability][] = $callback; @@ -71,9 +72,9 @@ class ModelVisibility implements ExtenderInterface } /** - * Add a scoper scoper that will always run for this model, regardless of requested ability. + * Add a scoper that will always run for this model, regardless of requested ability. * - * @param callable|string $callback + * @param (callable(\Flarum\User\User $actor, Builder $query, string $ability): void)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \Flarum\User\User $actor @@ -84,14 +85,14 @@ class ModelVisibility implements ExtenderInterface * * @return self */ - public function scopeAll($callback): self + public function scopeAll(callable|string $callback): self { $this->allScopers[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (! class_exists($this->modelClass)) { return; @@ -99,11 +100,14 @@ class ModelVisibility implements ExtenderInterface foreach ($this->scopers as $ability => $scopers) { foreach ($scopers as $scoper) { + // @todo: we can't define class-string, introduce interfaces for scopers. + // @phpstan-ignore-next-line $this->modelClass::registerVisibilityScoper(ContainerUtil::wrapCallback($scoper, $container), $ability); } } foreach ($this->allScopers as $scoper) { + // @phpstan-ignore-next-line $this->modelClass::registerVisibilityScoper(ContainerUtil::wrapCallback($scoper, $container)); } } diff --git a/framework/core/src/Extend/Notification.php b/framework/core/src/Extend/Notification.php index 72abf1f8d..a3d8a7f93 100644 --- a/framework/core/src/Extend/Notification.php +++ b/framework/core/src/Extend/Notification.php @@ -9,23 +9,26 @@ namespace Flarum\Extend; +use Flarum\Api\Serializer\AbstractSerializer; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; +use Flarum\Notification\Blueprint\BlueprintInterface; +use Flarum\Notification\Driver\NotificationDriverInterface; use Flarum\Notification\NotificationSyncer; use Illuminate\Contracts\Container\Container; class Notification implements ExtenderInterface { - private $blueprints = []; - private $serializers = []; - private $drivers = []; - private $typesEnabledByDefault = []; - private $beforeSendingCallbacks = []; + private array $blueprints = []; + private array $serializers = []; + private array $drivers = []; + private array $typesEnabledByDefault = []; + private array $beforeSendingCallbacks = []; /** - * @param string $blueprint: The ::class attribute of the blueprint class. + * @param class-string $blueprint: The ::class attribute of the blueprint class. * This blueprint should implement \Flarum\Notification\Blueprint\BlueprintInterface. - * @param string $serializer: The ::class attribute of the serializer class. + * @param class-string $serializer: The ::class attribute of the serializer class. * This serializer should extend from \Flarum\Api\Serializer\AbstractSerializer. * @param string[] $driversEnabledByDefault: The names of the drivers enabled by default for this notification type. * (example: alert, email). @@ -41,7 +44,7 @@ class Notification implements ExtenderInterface /** * @param string $driverName: The name of the notification driver. - * @param string $driver: The ::class attribute of the driver class. + * @param class-string $driver: The ::class attribute of the driver class. * This driver should implement \Flarum\Notification\Driver\NotificationDriverInterface. * @param string[] $typesEnabledByDefault: The names of blueprint classes of types enabled by default for this driver. * @return self @@ -55,7 +58,7 @@ class Notification implements ExtenderInterface } /** - * @param callable|string $callback + * @param (callable(BlueprintInterface $blueprint, \Flarum\User\User[] $newRecipients): \Flarum\User\User[])|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - \Flarum\Notification\Blueprint\BlueprintInterface $blueprint @@ -66,14 +69,14 @@ class Notification implements ExtenderInterface * * @return self */ - public function beforeSending($callback): self + public function beforeSending(callable|string $callback): self { $this->beforeSendingCallbacks[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.notification.blueprints', function ($existingBlueprints) { $existingBlueprints = array_merge($existingBlueprints, $this->blueprints); diff --git a/framework/core/src/Extend/Policy.php b/framework/core/src/Extend/Policy.php index f44f6f793..a134784e1 100644 --- a/framework/core/src/Extend/Policy.php +++ b/framework/core/src/Extend/Policy.php @@ -15,13 +15,13 @@ use Illuminate\Contracts\Container\Container; class Policy implements ExtenderInterface { - private $globalPolicies = []; - private $modelPolicies = []; + private array $globalPolicies = []; + private array $modelPolicies = []; /** * Add a custom policy for when an ability check is ran without a model instance. * - * @param string $policy: ::class attribute of policy class, which must extend Flarum\User\Access\AbstractPolicy + * @param class-string $policy: ::class attribute of policy class, which must extend \Flarum\User\Access\AbstractPolicy * @return self */ public function globalPolicy(string $policy): self @@ -50,7 +50,7 @@ class Policy implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.policies', function ($existingPolicies) { foreach ($this->modelPolicies as $modelClass => $addPolicies) { diff --git a/framework/core/src/Extend/Post.php b/framework/core/src/Extend/Post.php index 3e10dba5f..78e515c21 100644 --- a/framework/core/src/Extend/Post.php +++ b/framework/core/src/Extend/Post.php @@ -15,7 +15,7 @@ use Illuminate\Contracts\Container\Container; class Post implements ExtenderInterface { - private $postTypes = []; + private array $postTypes = []; /** * Register a new post type. This is generally done for custom 'event posts', @@ -31,7 +31,7 @@ class Post implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { foreach ($this->postTypes as $postType) { PostModel::setModel($postType::$type, $postType); diff --git a/framework/core/src/Extend/Routes.php b/framework/core/src/Extend/Routes.php index bb92e3518..a5b12449b 100644 --- a/framework/core/src/Extend/Routes.php +++ b/framework/core/src/Extend/Routes.php @@ -13,20 +13,19 @@ use Flarum\Extension\Extension; use Flarum\Http\RouteCollection; use Flarum\Http\RouteHandlerFactory; use Illuminate\Contracts\Container\Container; +use Psr\Http\Server\RequestHandlerInterface; class Routes implements ExtenderInterface { - private $appName; - - private $routes = []; - private $removedRoutes = []; + private array $routes = []; + private array $removedRoutes = []; /** * @param string $appName: Name of the app (api, forum, admin). */ - public function __construct(string $appName) - { - $this->appName = $appName; + public function __construct( + private readonly string $appName + ) { } /** @@ -34,7 +33,7 @@ class Routes implements ExtenderInterface * * @param string $path: The path of the route * @param string $name: The name of the route, must be unique. - * @param callable|string $handler: ::class attribute of the controller class, or a closure. + * @param callable|class-string $handler: ::class attribute of the controller class, or a closure. * * If the handler is a controller class, it should implement \Psr\Http\Server\RequestHandlerInterface, * or extend one of the Flarum Api controllers within \Flarum\Api\Controller. @@ -48,7 +47,7 @@ class Routes implements ExtenderInterface * * @return self */ - public function get(string $path, string $name, $handler): self + public function get(string $path, string $name, callable|string $handler): self { return $this->route('GET', $path, $name, $handler); } @@ -58,7 +57,7 @@ class Routes implements ExtenderInterface * * @param string $path: The path of the route * @param string $name: The name of the route, must be unique. - * @param callable|string $handler: ::class attribute of the controller class, or a closure. + * @param callable|class-string $handler: ::class attribute of the controller class, or a closure. * * If the handler is a controller class, it should implement \Psr\Http\Server\RequestHandlerInterface, * or extend one of the Flarum Api controllers within \Flarum\Api\Controller. @@ -72,7 +71,7 @@ class Routes implements ExtenderInterface * * @return self */ - public function post(string $path, string $name, $handler): self + public function post(string $path, string $name, callable|string $handler): self { return $this->route('POST', $path, $name, $handler); } @@ -82,7 +81,7 @@ class Routes implements ExtenderInterface * * @param string $path: The path of the route * @param string $name: The name of the route, must be unique. - * @param callable|string $handler: ::class attribute of the controller class, or a closure. + * @param callable|class-string $handler: ::class attribute of the controller class, or a closure. * * If the handler is a controller class, it should implement \Psr\Http\Server\RequestHandlerInterface, * or extend one of the Flarum Api controllers within \Flarum\Api\Controller. @@ -96,7 +95,7 @@ class Routes implements ExtenderInterface * * @return self */ - public function put(string $path, string $name, $handler): self + public function put(string $path, string $name, callable|string $handler): self { return $this->route('PUT', $path, $name, $handler); } @@ -106,7 +105,7 @@ class Routes implements ExtenderInterface * * @param string $path: The path of the route * @param string $name: The name of the route, must be unique. - * @param callable|string $handler: ::class attribute of the controller class, or a closure. + * @param callable|class-string $handler: ::class attribute of the controller class, or a closure. * * If the handler is a controller class, it should implement \Psr\Http\Server\RequestHandlerInterface, * or extend one of the Flarum Api controllers within \Flarum\Api\Controller. @@ -120,7 +119,7 @@ class Routes implements ExtenderInterface * * @return self */ - public function patch(string $path, string $name, $handler): self + public function patch(string $path, string $name, callable|string $handler): self { return $this->route('PATCH', $path, $name, $handler); } @@ -130,7 +129,7 @@ class Routes implements ExtenderInterface * * @param string $path: The path of the route * @param string $name: The name of the route, must be unique. - * @param callable|string $handler: ::class attribute of the controller class, or a closure. + * @param callable|class-string $handler: ::class attribute of the controller class, or a closure. * * If the handler is a controller class, it should implement \Psr\Http\Server\RequestHandlerInterface, * or extend one of the Flarum Api controllers within \Flarum\Api\Controller. @@ -144,7 +143,7 @@ class Routes implements ExtenderInterface * * @return self */ - public function delete(string $path, string $name, $handler): self + public function delete(string $path, string $name, callable|string $handler): self { return $this->route('DELETE', $path, $name, $handler); } @@ -175,7 +174,7 @@ class Routes implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (empty($this->routes) && empty($this->removedRoutes)) { return; diff --git a/framework/core/src/Extend/ServiceProvider.php b/framework/core/src/Extend/ServiceProvider.php index a7216d625..d42416a87 100644 --- a/framework/core/src/Extend/ServiceProvider.php +++ b/framework/core/src/Extend/ServiceProvider.php @@ -10,11 +10,12 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\Foundation\AbstractServiceProvider; use Illuminate\Contracts\Container\Container; class ServiceProvider implements ExtenderInterface { - private $providers = []; + private array $providers = []; /** * Register a service provider. @@ -23,7 +24,7 @@ class ServiceProvider implements ExtenderInterface * Please read our documentation about service providers for recommendations. * @see https://docs.flarum.org/extend/service-provider/ * - * @param string $serviceProviderClass The ::class attribute of the service provider class. + * @param class-string $serviceProviderClass The ::class attribute of the service provider class. * @return self */ public function register(string $serviceProviderClass): self @@ -33,7 +34,7 @@ class ServiceProvider implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $app = $container->make('flarum'); diff --git a/framework/core/src/Extend/Session.php b/framework/core/src/Extend/Session.php index 83d4af8a1..c7ed580bb 100644 --- a/framework/core/src/Extend/Session.php +++ b/framework/core/src/Extend/Session.php @@ -10,11 +10,12 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\User\SessionDriverInterface; use Illuminate\Contracts\Container\Container; class Session implements ExtenderInterface { - private $drivers = []; + private array $drivers = []; /** * Register a new session driver. @@ -22,7 +23,7 @@ class Session implements ExtenderInterface * A driver can currently be selected by setting `session.driver` in `config.php`. * * @param string $name: The name of the driver. - * @param string $driverClass: The ::class attribute of the driver. + * @param class-string $driverClass: The ::class attribute of the driver. * Driver must implement `\Flarum\User\SessionDriverInterface`. * @return self */ @@ -33,7 +34,7 @@ class Session implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.session.drivers', function ($drivers) { return array_merge($drivers, $this->drivers); diff --git a/framework/core/src/Extend/Settings.php b/framework/core/src/Extend/Settings.php index a685addbc..18c83306d 100644 --- a/framework/core/src/Extend/Settings.php +++ b/framework/core/src/Extend/Settings.php @@ -19,16 +19,16 @@ use Illuminate\Support\Collection; class Settings implements ExtenderInterface { - private $settings = []; - private $defaults = []; - private $lessConfigs = []; + private array $settings = []; + private array $defaults = []; + private array $lessConfigs = []; /** * Serialize a setting value to the ForumSerializer attributes. * * @param string $attributeName: The attribute name to be used in the ForumSerializer attributes array. * @param string $key: The key of the setting. - * @param string|callable|null $callback: Optional callback to modify the value before serialization. + * @param (callable(mixed $value): mixed)|class-string|null $callback: Optional callback to modify the value before serialization. * * The callback can be a closure or an invokable class, and should accept: * - mixed $value: The value of the setting. @@ -40,7 +40,7 @@ class Settings implements ExtenderInterface * @param mixed $default: Deprecated optional default serialized value. Will be run through the optional callback. * @return self */ - public function serializeToForum(string $attributeName, string $key, $callback = null, $default = null): self + public function serializeToForum(string $attributeName, string $key, callable|string $callback = null, mixed $default = null): self { $this->settings[$key] = compact('attributeName', 'callback', 'default'); @@ -55,7 +55,7 @@ class Settings implements ExtenderInterface * @param mixed $value: The setting value. * @return self */ - public function default(string $key, $value): self + public function default(string $key, mixed $value): self { $this->defaults[$key] = $value; @@ -67,7 +67,7 @@ class Settings implements ExtenderInterface * * @param string $configName: The name of the configuration variable, in hyphen case. * @param string $key: The key of the setting. - * @param string|callable|null $callback: Optional callback to modify the value. + * @param (callable(mixed $value): mixed)|class-string|null $callback: Optional callback to modify the value. * * The callback can be a closure or an invokable class, and should accept: * - mixed $value: The value of the setting. @@ -77,14 +77,14 @@ class Settings implements ExtenderInterface * * @return self */ - public function registerLessConfigVar(string $configName, string $key, $callback = null): self + public function registerLessConfigVar(string $configName, string $key, callable|string $callback = null): self { $this->lessConfigs[$configName] = compact('key', 'callback'); return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (! empty($this->defaults)) { $container->extend('flarum.settings.default', function (Collection $defaults) { diff --git a/framework/core/src/Extend/SimpleFlarumSearch.php b/framework/core/src/Extend/SimpleFlarumSearch.php index 9249ae9cb..0e1924c37 100644 --- a/framework/core/src/Extend/SimpleFlarumSearch.php +++ b/framework/core/src/Extend/SimpleFlarumSearch.php @@ -10,28 +10,32 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\Query\QueryCriteria; +use Flarum\Search\AbstractRegexGambit; +use Flarum\Search\AbstractSearcher; +use Flarum\Search\GambitInterface; +use Flarum\Search\SearchState; use Illuminate\Contracts\Container\Container; class SimpleFlarumSearch implements ExtenderInterface { - private $fullTextGambit; - private $gambits = []; - private $searcher; - private $searchMutators = []; + private ?string $fullTextGambit = null; + private array $gambits = []; + private array $searchMutators = []; /** - * @param string $searcherClass: The ::class attribute of the Searcher you are modifying. + * @param class-string $searcher: The ::class attribute of the Searcher you are modifying. * This searcher must extend \Flarum\Search\AbstractSearcher. */ - public function __construct(string $searcherClass) - { - $this->searcher = $searcherClass; + public function __construct( + private readonly string $searcher + ) { } /** * Add a gambit to this searcher. Gambits are used to filter search queries. * - * @param string $gambitClass: The ::class attribute of the gambit you are adding. + * @param class-string $gambitClass: The ::class attribute of the gambit you are adding. * This gambit must extend \Flarum\Search\AbstractRegexGambit * @return self */ @@ -45,7 +49,7 @@ class SimpleFlarumSearch implements ExtenderInterface /** * Set the full text gambit for this searcher. The full text gambit actually executes the search. * - * @param string $gambitClass: The ::class attribute of the full test gambit you are adding. + * @param class-string $gambitClass: The ::class attribute of the full test gambit you are adding. * This gambit must implement \Flarum\Search\GambitInterface * @return self */ @@ -59,7 +63,7 @@ class SimpleFlarumSearch implements ExtenderInterface /** * Add a callback through which to run all search queries after gambits have been applied. * - * @param callable|string $callback + * @param (callable(SearchState $search, QueryCriteria $criteria): void)|class-string $callback * * The callback can be a closure or an invokable class, and should accept: * - \Flarum\Search\SearchState $search @@ -69,14 +73,14 @@ class SimpleFlarumSearch implements ExtenderInterface * * @return self */ - public function addSearchMutator($callback): self + public function addSearchMutator(callable|string $callback): self { $this->searchMutators[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (! is_null($this->fullTextGambit)) { $container->extend('flarum.simple_search.fulltext_gambits', function ($oldFulltextGambits) { diff --git a/framework/core/src/Extend/Theme.php b/framework/core/src/Extend/Theme.php index 0d332b862..3dda047c8 100644 --- a/framework/core/src/Extend/Theme.php +++ b/framework/core/src/Extend/Theme.php @@ -16,13 +16,13 @@ use RuntimeException; class Theme implements ExtenderInterface { - private $lessImportOverrides = []; - private $fileSourceOverrides = []; - private $customFunctions = []; - private $lessVariables = []; + private array $lessImportOverrides = []; + private array $fileSourceOverrides = []; + private array $customFunctions = []; + private array $lessVariables = []; /** - * This can be used to override LESS files that are imported within the code. + * This can be used to override `LESS` files that are imported within the code. * For example, core's `forum.less` file imports a `forum/DiscussionListItem.less` file. * The contents of this file can be overriden with this method. * @@ -31,7 +31,7 @@ class Theme implements ExtenderInterface * @param string|null $extensionId : If overriding an extension file, specify its ID, for example: `flarum-tags`. * @return self */ - public function overrideLessImport(string $file, string $newFilePath, string $extensionId = null): self + public function overrideLessImport(string $file, string $newFilePath, ?string $extensionId = null): self { $this->lessImportOverrides[] = compact('file', 'newFilePath', 'extensionId'); @@ -136,7 +136,7 @@ class Theme implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.frontend.custom_less_functions', function (array $customFunctions) { return array_merge($customFunctions, $this->customFunctions); diff --git a/framework/core/src/Extend/ThrottleApi.php b/framework/core/src/Extend/ThrottleApi.php index 747f0deea..ce05332c1 100644 --- a/framework/core/src/Extend/ThrottleApi.php +++ b/framework/core/src/Extend/ThrottleApi.php @@ -12,17 +12,18 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; +use Psr\Http\Message\ServerRequestInterface; class ThrottleApi implements ExtenderInterface { - private $setThrottlers = []; - private $removeThrottlers = []; + private array $setThrottlers = []; + private array $removeThrottlers = []; /** * Add a new throttler (or override one with the same name). * * @param string $name: The name of the throttler. - * @param string|callable $callback + * @param (callable(ServerRequestInterface $request): bool)|class-string $callback * * The callable can be a closure or invokable class, and should accept: * - $request: The current `\Psr\Http\Message\ServerRequestInterface` request object. @@ -38,7 +39,7 @@ class ThrottleApi implements ExtenderInterface * * @return self */ - public function set(string $name, $callback): self + public function set(string $name, callable|string $callback): self { $this->setThrottlers[$name] = $callback; @@ -58,7 +59,7 @@ class ThrottleApi implements ExtenderInterface return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.api.throttlers', function ($throttlers) use ($container) { $throttlers = array_diff_key($throttlers, array_flip($this->removeThrottlers)); diff --git a/framework/core/src/Extend/User.php b/framework/core/src/Extend/User.php index 3357474e1..f429258f4 100644 --- a/framework/core/src/Extend/User.php +++ b/framework/core/src/Extend/User.php @@ -10,20 +10,21 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\User\DisplayName\DriverInterface; use Flarum\User\User as FlarumUser; use Illuminate\Contracts\Container\Container; class User implements ExtenderInterface { - private $displayNameDrivers = []; - private $groupProcessors = []; - private $preferences = []; + private array $displayNameDrivers = []; + private array $groupProcessors = []; + private array $preferences = []; /** * Add a display name driver. * * @param string $identifier: Identifier for display name driver. E.g. 'username' for UserNameDriver - * @param string $driver: ::class attribute of driver class, which must implement Flarum\User\DisplayName\DriverInterface + * @param class-string $driver: ::class attribute of driver class, which must implement Flarum\User\DisplayName\DriverInterface * @return self */ public function displayNameDriver(string $identifier, string $driver): self @@ -38,7 +39,7 @@ class User implements ExtenderInterface * This can be used to give a user permissions for groups they aren't actually in, based on context. * It will not change the group badges displayed for the user. * - * @param callable|string $callback + * @param (callable(\Flarum\User\User $user, int[] $groupIds): int[])|class-string $callback * * The callable can be a closure or invokable class, and should accept: * - \Flarum\User\User $user: the user in question. @@ -49,7 +50,7 @@ class User implements ExtenderInterface * * @return self */ - public function permissionGroups($callback): self + public function permissionGroups(callable|string $callback): self { $this->groupProcessors[] = $callback; @@ -60,18 +61,18 @@ class User implements ExtenderInterface * Register a new user preference. * * @param string $key - * @param callable $transformer + * @param callable|null $transformer * @param mixed|null $default * @return self */ - public function registerPreference(string $key, callable $transformer = null, $default = null): self + public function registerPreference(string $key, ?callable $transformer = null, mixed $default = null): self { $this->preferences[$key] = compact('transformer', 'default'); return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->extend('flarum.user.display_name.supported_drivers', function ($existingDrivers) { return array_merge($existingDrivers, $this->displayNameDrivers); diff --git a/framework/core/src/Extend/Validator.php b/framework/core/src/Extend/Validator.php index 0420b0e2b..282736e9c 100644 --- a/framework/core/src/Extend/Validator.php +++ b/framework/core/src/Extend/Validator.php @@ -10,28 +10,28 @@ namespace Flarum\Extend; use Flarum\Extension\Extension; +use Flarum\Foundation\AbstractValidator; use Flarum\Foundation\ContainerUtil; use Illuminate\Contracts\Container\Container; class Validator implements ExtenderInterface { - private $configurationCallbacks = []; - private $validator; + private array $configurationCallbacks = []; /** - * @param string $validatorClass: The ::class attribute of the validator you are modifying. + * @param class-string $validatorClass: The ::class attribute of the validator you are modifying. * The validator should inherit from \Flarum\Foundation\AbstractValidator. */ - public function __construct(string $validatorClass) - { - $this->validator = $validatorClass; + public function __construct( + private readonly string $validatorClass + ) { } /** * Configure the validator. This is often used to adjust validation rules, but can be * used to make other changes to the validator as well. * - * @param callable|class-string $callback + * @param (callable(AbstractValidator $flarumValidator, \Illuminate\Validation\Validator $validator): void)|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \Flarum\Foundation\AbstractValidator $flarumValidator: The Flarum validator wrapper @@ -41,16 +41,16 @@ class Validator implements ExtenderInterface * * @return self */ - public function configure($callback): self + public function configure(callable|string $callback): self { $this->configurationCallbacks[] = $callback; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { - $container->resolving($this->validator, function ($validator, $container) { + $container->resolving($this->validatorClass, function ($validator, $container) { foreach ($this->configurationCallbacks as $callback) { $validator->addConfiguration(ContainerUtil::wrapCallback($callback, $container)); } diff --git a/framework/core/src/Extend/View.php b/framework/core/src/Extend/View.php index 1c0d39c8e..a71420736 100644 --- a/framework/core/src/Extend/View.php +++ b/framework/core/src/Extend/View.php @@ -22,8 +22,8 @@ use Illuminate\View\Factory as FactoryImplementation; */ class View implements ExtenderInterface, LifecycleInterface { - private $namespaces = []; - private $prependNamespaces = []; + private array $namespaces = []; + private array $prependNamespaces = []; /** * Register a new namespace of Laravel views. @@ -39,7 +39,7 @@ class View implements ExtenderInterface, LifecycleInterface * where view files are stored, relative to the extend.php file. * @return self */ - public function namespace(string $namespace, $hints): self + public function namespace(string $namespace, array|string $hints): self { $this->namespaces[$namespace] = $hints; @@ -54,17 +54,17 @@ class View implements ExtenderInterface, LifecycleInterface * * @param string $namespace: The name of the namespace. * @param string|string[] $hints: This is a path (or an array of paths) to the folder(s) - * where view files are stored, relative to the extend.php file. + * where view files are stored, relative to the `extend.php` file. * @return self */ - public function extendNamespace(string $namespace, $hints): self + public function extendNamespace(string $namespace, array|string $hints): self { $this->prependNamespaces[$namespace] = $hints; return $this; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->resolving(Factory::class, function (FactoryImplementation $view) { foreach ($this->namespaces as $namespace => $hints) { @@ -81,7 +81,7 @@ class View implements ExtenderInterface, LifecycleInterface * @param Extension $extension * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function onEnable(Container $container, Extension $extension) + public function onEnable(Container $container, Extension $extension): void { $storagePath = $container->make(Paths::class)->storage; array_map('unlink', glob($storagePath.'/views/*')); @@ -92,7 +92,7 @@ class View implements ExtenderInterface, LifecycleInterface * @param Extension $extension * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function onDisable(Container $container, Extension $extension) + public function onDisable(Container $container, Extension $extension): void { $storagePath = $container->make(Paths::class)->storage; array_map('unlink', glob($storagePath.'/views/*')); diff --git a/framework/core/src/Extension/Command/ToggleExtension.php b/framework/core/src/Extension/Command/ToggleExtension.php index 69d3060a4..a25b39498 100644 --- a/framework/core/src/Extension/Command/ToggleExtension.php +++ b/framework/core/src/Extension/Command/ToggleExtension.php @@ -13,25 +13,10 @@ use Flarum\User\User; class ToggleExtension { - /** - * @var User - */ - public $actor; - - /** - * @var string - */ - public $name; - - /** - * @var bool - */ - public $enabled; - - public function __construct(User $actor, string $name, bool $enabled) - { - $this->actor = $actor; - $this->name = $name; - $this->enabled = $enabled; + public function __construct( + public User $actor, + public string $name, + public bool $enabled + ) { } } diff --git a/framework/core/src/Extension/Command/ToggleExtensionHandler.php b/framework/core/src/Extension/Command/ToggleExtensionHandler.php index 564d543df..2b3fa11fe 100644 --- a/framework/core/src/Extension/Command/ToggleExtensionHandler.php +++ b/framework/core/src/Extension/Command/ToggleExtensionHandler.php @@ -13,22 +13,12 @@ use Flarum\Extension\ExtensionManager; class ToggleExtensionHandler { - /** - * @var ExtensionManager - */ - protected $extensions; - - public function __construct(ExtensionManager $extensions) - { - $this->extensions = $extensions; + public function __construct( + protected ExtensionManager $extensions + ) { } - /** - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws \Flarum\Extension\Exception\MissingDependenciesException - * @throws \Flarum\Extension\Exception\DependentExtensionsException - */ - public function handle(ToggleExtension $command) + public function handle(ToggleExtension $command): void { $command->actor->assertAdmin(); diff --git a/framework/core/src/Extension/Console/ToggleExtensionCommand.php b/framework/core/src/Extension/Console/ToggleExtensionCommand.php index ff272d362..e64c7e37d 100644 --- a/framework/core/src/Extension/Console/ToggleExtensionCommand.php +++ b/framework/core/src/Extension/Console/ToggleExtensionCommand.php @@ -11,25 +11,17 @@ namespace Flarum\Extension\Console; use Flarum\Console\AbstractCommand; use Flarum\Extension\ExtensionManager; +use Symfony\Component\Console\Command\Command; class ToggleExtensionCommand extends AbstractCommand { - /** - * @var ExtensionManager - */ - protected $extensionManager; - - public function __construct(ExtensionManager $extensionManager) - { - $this->extensionManager = $extensionManager; - + public function __construct( + protected ExtensionManager $extensionManager + ) { parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('extension:enable') @@ -38,10 +30,7 @@ class ToggleExtensionCommand extends AbstractCommand ->addArgument('extension-id', null, 'The ID of the extension to enable or disable.'); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $name = $this->input->getArgument('extension-id'); $enabling = $this->input->getFirstArgument() === 'extension:enable'; @@ -49,30 +38,29 @@ class ToggleExtensionCommand extends AbstractCommand if ($this->extensionManager->getExtension($name) === null) { $this->error("There are no extensions by the ID of '$name'."); - return; + return Command::INVALID; } - switch ($enabling) { - case true: - if ($this->extensionManager->isEnabled($name)) { - $this->info("The '$name' extension is already enabled."); + if ($enabling) { + if ($this->extensionManager->isEnabled($name)) { + $this->info("The '$name' extension is already enabled."); - return; - } else { - $this->info("Enabling '$name' extension..."); - $this->extensionManager->enable($name); - } - break; - case false: - if (! $this->extensionManager->isEnabled($name)) { - $this->info("The '$name' extension is already disabled."); + return Command::FAILURE; + } else { + $this->info("Enabling '$name' extension..."); + $this->extensionManager->enable($name); + } + } else { + if (! $this->extensionManager->isEnabled($name)) { + $this->info("The '$name' extension is already disabled."); - return; - } else { - $this->info("Disabling '$name' extension..."); - $this->extensionManager->disable($name); - } - break; + return Command::FAILURE; + } else { + $this->info("Disabling '$name' extension..."); + $this->extensionManager->disable($name); + } } + + return Command::SUCCESS; } } diff --git a/framework/core/src/Extension/DefaultLanguagePackGuard.php b/framework/core/src/Extension/DefaultLanguagePackGuard.php index ee1dc6d12..747b60b3f 100644 --- a/framework/core/src/Extension/DefaultLanguagePackGuard.php +++ b/framework/core/src/Extension/DefaultLanguagePackGuard.php @@ -16,17 +16,12 @@ use Illuminate\Support\Arr; class DefaultLanguagePackGuard { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - public function handle(Disabling $event) + public function handle(Disabling $event): void { if (! in_array('flarum-locale', $event->extension->extra)) { return; diff --git a/framework/core/src/Extension/Event/Disabled.php b/framework/core/src/Extension/Event/Disabled.php index 74d96c4ad..b28ae5fa7 100644 --- a/framework/core/src/Extension/Event/Disabled.php +++ b/framework/core/src/Extension/Event/Disabled.php @@ -13,16 +13,8 @@ use Flarum\Extension\Extension; class Disabled { - /** - * @var Extension - */ - public $extension; - - /** - * @param Extension $extension - */ - public function __construct(Extension $extension) - { - $this->extension = $extension; + public function __construct( + public Extension $extension + ) { } } diff --git a/framework/core/src/Extension/Event/Disabling.php b/framework/core/src/Extension/Event/Disabling.php index 87f0ee6b8..9adfec08d 100644 --- a/framework/core/src/Extension/Event/Disabling.php +++ b/framework/core/src/Extension/Event/Disabling.php @@ -13,16 +13,8 @@ use Flarum\Extension\Extension; class Disabling { - /** - * @var Extension - */ - public $extension; - - /** - * @param Extension $extension - */ - public function __construct(Extension $extension) - { - $this->extension = $extension; + public function __construct( + public Extension $extension + ) { } } diff --git a/framework/core/src/Extension/Event/Enabled.php b/framework/core/src/Extension/Event/Enabled.php index b2764c859..db08a363b 100644 --- a/framework/core/src/Extension/Event/Enabled.php +++ b/framework/core/src/Extension/Event/Enabled.php @@ -13,16 +13,8 @@ use Flarum\Extension\Extension; class Enabled { - /** - * @var Extension - */ - public $extension; - - /** - * @param Extension $extension - */ - public function __construct(Extension $extension) - { - $this->extension = $extension; + public function __construct( + public Extension $extension + ) { } } diff --git a/framework/core/src/Extension/Event/Enabling.php b/framework/core/src/Extension/Event/Enabling.php index fe9c39319..1e17eef3a 100644 --- a/framework/core/src/Extension/Event/Enabling.php +++ b/framework/core/src/Extension/Event/Enabling.php @@ -13,16 +13,8 @@ use Flarum\Extension\Extension; class Enabling { - /** - * @var Extension - */ - public $extension; - - /** - * @param Extension $extension - */ - public function __construct(Extension $extension) - { - $this->extension = $extension; + public function __construct( + public Extension $extension + ) { } } diff --git a/framework/core/src/Extension/Event/Uninstalled.php b/framework/core/src/Extension/Event/Uninstalled.php index cb1819d29..7f2ef3050 100644 --- a/framework/core/src/Extension/Event/Uninstalled.php +++ b/framework/core/src/Extension/Event/Uninstalled.php @@ -13,16 +13,8 @@ use Flarum\Extension\Extension; class Uninstalled { - /** - * @var Extension - */ - public $extension; - - /** - * @param Extension $extension - */ - public function __construct(Extension $extension) - { - $this->extension = $extension; + public function __construct( + public Extension $extension + ) { } } diff --git a/framework/core/src/Extension/Exception/CircularDependenciesException.php b/framework/core/src/Extension/Exception/CircularDependenciesException.php index c2c052839..c19a8665c 100644 --- a/framework/core/src/Extension/Exception/CircularDependenciesException.php +++ b/framework/core/src/Extension/Exception/CircularDependenciesException.php @@ -14,12 +14,9 @@ use Flarum\Extension\ExtensionManager; class CircularDependenciesException extends Exception { - public $circular_dependencies; - - public function __construct(array $circularDependencies) - { - $this->circular_dependencies = $circularDependencies; - - parent::__construct('Circular dependencies detected: '.implode(', ', ExtensionManager::pluckTitles($circularDependencies)).' - aborting. Please fix this by disabling the extensions that are causing the circular dependencies.'); + public function __construct( + public array $circular_dependencies + ) { + parent::__construct('Circular dependencies detected: '.implode(', ', ExtensionManager::pluckTitles($this->circular_dependencies)).' - aborting. Please fix this by disabling the extensions that are causing the circular dependencies.'); } } diff --git a/framework/core/src/Extension/Exception/DependentExtensionsException.php b/framework/core/src/Extension/Exception/DependentExtensionsException.php index 3966cbaf9..b5c416cc9 100644 --- a/framework/core/src/Extension/Exception/DependentExtensionsException.php +++ b/framework/core/src/Extension/Exception/DependentExtensionsException.php @@ -19,18 +19,14 @@ use Flarum\Extension\ExtensionManager; */ class DependentExtensionsException extends Exception { - public $extension; - public $dependent_extensions; - /** * @param $extension: The extension we are attempting to disable. * @param $dependent_extensions: Enabled Flarum extensions that depend on this extension. */ - public function __construct(Extension $extension, array $dependent_extensions) - { - $this->extension = $extension; - $this->dependent_extensions = $dependent_extensions; - + public function __construct( + public Extension $extension, + public array $dependent_extensions + ) { parent::__construct($extension->getTitle().' could not be disabled, because it is a dependency of: '.implode(', ', ExtensionManager::pluckTitles($dependent_extensions))); } } diff --git a/framework/core/src/Extension/Exception/ExtensionBootError.php b/framework/core/src/Extension/Exception/ExtensionBootError.php index e015bf34b..c5c126d55 100644 --- a/framework/core/src/Extension/Exception/ExtensionBootError.php +++ b/framework/core/src/Extension/Exception/ExtensionBootError.php @@ -15,14 +15,11 @@ use Throwable; class ExtensionBootError extends Exception { - public $extension; - public $extender; - - public function __construct(Extension $extension, $extender, Throwable $previous = null) - { - $this->extension = $extension; - $this->extender = $extender; - + public function __construct( + public Extension $extension, + public $extender, + Throwable $previous = null + ) { $extenderClass = get_class($extender); parent::__construct("Experienced an error while booting extension: {$extension->getTitle()}.\n\nError occurred while applying an extender of type: $extenderClass.", 0, $previous); diff --git a/framework/core/src/Extension/Exception/MissingDependenciesException.php b/framework/core/src/Extension/Exception/MissingDependenciesException.php index cd2407261..289101af0 100644 --- a/framework/core/src/Extension/Exception/MissingDependenciesException.php +++ b/framework/core/src/Extension/Exception/MissingDependenciesException.php @@ -19,18 +19,14 @@ use Flarum\Extension\ExtensionManager; */ class MissingDependenciesException extends Exception { - public $extension; - public $missing_dependencies; - /** * @param $extension: The extension we are attempting to enable. * @param $missing_dependencies: Extensions that this extension depends on, and are not enabled. */ - public function __construct(Extension $extension, array $missing_dependencies = null) - { - $this->extension = $extension; - $this->missing_dependencies = $missing_dependencies; - + public function __construct( + public Extension $extension, + public ?array $missing_dependencies = null + ) { parent::__construct($extension->getTitle().' could not be enabled, because it depends on: '.implode(', ', ExtensionManager::pluckTitles($missing_dependencies))); } } diff --git a/framework/core/src/Extension/Extension.php b/framework/core/src/Extension/Extension.php index 6971ecb18..e3e7dc464 100644 --- a/framework/core/src/Extension/Extension.php +++ b/framework/core/src/Extension/Extension.php @@ -52,35 +52,19 @@ class Extension implements Arrayable ]; /** - * Unique Id of the extension. + * Unique ID of the extension. + * Constructed from vendor/packageName to vendor-packageName. * - * @info Identical to the directory in the extensions directory. * @example flarum-suspend - * - * @var string */ - protected $id; - - /** - * The directory of this extension. - * - * @var string - */ - protected $path; - - /** - * Composer json of the package. - * - * @var array - */ - protected $composerJson; + protected string $id; /** * The IDs of all Flarum extensions that this extension depends on. * * @var string[] */ - protected $extensionDependencyIds; + protected array $extensionDependencyIds; /** * The IDs of all Flarum extensions that this extension should be booted after @@ -88,34 +72,19 @@ class Extension implements Arrayable * * @var string[] */ - protected $optionalDependencyIds; + protected array $optionalDependencyIds; - /** - * Whether the extension is installed. - * - * @var bool - */ - protected $installed = true; + protected bool $installed = true; + protected string $version; - /** - * The installed version of the extension. - * - * @var string - */ - protected $version; - - /** - * @param $path - * @param array $composerJson - */ - public function __construct($path, $composerJson) - { - $this->path = $path; - $this->composerJson = $composerJson; + public function __construct( + protected string $path, + protected array $composerJson + ) { $this->assignId(); } - protected static function nameToId($name) + protected static function nameToId($name): string { [$vendor, $package] = explode('/', $name); $package = str_replace(['flarum-ext-', 'flarum-'], '', $package); @@ -126,7 +95,7 @@ class Extension implements Arrayable /** * Assigns the id for the extension used globally. */ - protected function assignId() + protected function assignId(): void { $this->id = static::nameToId($this->name); } @@ -134,7 +103,7 @@ class Extension implements Arrayable /** * @internal */ - public function extend(Container $container) + public function extend(Container $container): void { foreach ($this->getExtenders() as $extender) { try { @@ -145,17 +114,11 @@ class Extension implements Arrayable } } - /** - * {@inheritdoc} - */ public function __get($name) { return $this->composerJsonAttribute(Str::snake($name, '-')); } - /** - * {@inheritdoc} - */ public function __isset($name) { return isset($this->{$name}) || $this->composerJsonAttribute(Str::snake($name, '-')); @@ -169,18 +132,15 @@ class Extension implements Arrayable * @param $name * @return mixed */ - public function composerJsonAttribute($name) + public function composerJsonAttribute($name): mixed { return Arr::get($this->composerJson, $name); } /** - * @param bool $installed - * @return Extension - * * @internal */ - public function setInstalled($installed) + public function setInstalled(bool $installed): static { $this->installed = $installed; @@ -190,18 +150,15 @@ class Extension implements Arrayable /** * @return bool */ - public function isInstalled() + public function isInstalled(): bool { return $this->installed; } /** - * @param string $version - * @return Extension - * * @internal */ - public function setVersion($version) + public function setVersion(string $version): static { $this->version = $version; @@ -216,7 +173,7 @@ class Extension implements Arrayable * are flarum extensions. * @internal */ - public function calculateDependencies($extensionSet) + public function calculateDependencies(array $extensionSet): void { $this->extensionDependencyIds = (new Collection(Arr::get($this->composerJson, 'require', []))) ->keys() @@ -235,20 +192,12 @@ class Extension implements Arrayable ->toArray(); } - /** - * @return string|null - */ - public function getVersion() + public function getVersion(): ?string { return $this->version; } - /** - * Loads the icon information from the composer.json. - * - * @return array|null - */ - public function getIcon() + public function getIcon(): ?array { $icon = $this->composerJsonAttribute('extra.flarum-extension.icon'); $file = Arr::get($icon, 'image'); @@ -298,7 +247,7 @@ class Extension implements Arrayable /** * @internal */ - public function enable(Container $container) + public function enable(Container $container): void { foreach ($this->getLifecycleExtenders() as $extender) { $extender->onEnable($container, $this); @@ -308,7 +257,7 @@ class Extension implements Arrayable /** * @internal */ - public function disable(Container $container) + public function disable(Container $container): void { foreach ($this->getLifecycleExtenders() as $extender) { $extender->onDisable($container, $this); @@ -320,7 +269,7 @@ class Extension implements Arrayable * * @return string */ - public function getId() + public function getId(): string { return $this->id; } @@ -328,7 +277,7 @@ class Extension implements Arrayable /** * @return string */ - public function getTitle() + public function getTitle(): string { return $this->composerJsonAttribute('extra.flarum-extension.title'); } @@ -336,7 +285,7 @@ class Extension implements Arrayable /** * @return string */ - public function getPath() + public function getPath(): string { return $this->path; } @@ -394,7 +343,7 @@ class Extension implements Arrayable private function getExtenderFile(): ?string { - $filename = "{$this->path}/extend.php"; + $filename = "$this->path/extend.php"; if (file_exists($filename)) { return $filename; @@ -406,7 +355,7 @@ class Extension implements Arrayable /** * Compile a list of links for this extension. */ - public function getLinks() + public function getLinks(): array { $links = []; @@ -448,10 +397,8 @@ class Extension implements Arrayable /** * Tests whether the extension has assets. - * - * @return bool */ - public function hasAssets() + public function hasAssets(): bool { return realpath($this->path.'/assets/') !== false; } @@ -459,7 +406,7 @@ class Extension implements Arrayable /** * @internal */ - public function copyAssetsTo(FilesystemInterface $target) + public function copyAssetsTo(FilesystemInterface $target): void { if (! $this->hasAssets()) { return; @@ -477,22 +424,19 @@ class Extension implements Arrayable /** * Tests whether the extension has migrations. - * - * @return bool */ - public function hasMigrations() + public function hasMigrations(): bool { return realpath($this->path.'/migrations/') !== false; } /** - * @return int|void * @internal */ - public function migrate(Migrator $migrator, $direction = 'up') + public function migrate(Migrator $migrator, $direction = 'up'): ?int { if (! $this->hasMigrations()) { - return; + return null; } if ($direction == 'up') { @@ -500,6 +444,8 @@ class Extension implements Arrayable } else { return $migrator->reset($this->getPath().'/migrations', $this); } + + return null; } /** @@ -507,7 +453,7 @@ class Extension implements Arrayable * * @return array */ - public function toArray() + public function toArray(): array { return (array) array_merge([ 'id' => $this->getId(), diff --git a/framework/core/src/Extension/ExtensionManager.php b/framework/core/src/Extension/ExtensionManager.php index 08d0be0ef..a8d9fb4d2 100644 --- a/framework/core/src/Extension/ExtensionManager.php +++ b/framework/core/src/Extension/ExtensionManager.php @@ -29,52 +29,19 @@ use Illuminate\Support\Collection; class ExtensionManager { - protected $config; - - /** - * @var Paths - */ - protected $paths; - - protected $container; - - protected $migrator; - - /** - * @var Dispatcher - */ - protected $dispatcher; - - /** - * @var Filesystem - */ - protected $filesystem; - - /** - * @var Collection|null - */ - protected $extensions; + protected ?Collection $extensions = null; public function __construct( - SettingsRepositoryInterface $config, - Paths $paths, - Container $container, - Migrator $migrator, - Dispatcher $dispatcher, - Filesystem $filesystem + protected SettingsRepositoryInterface $config, + protected Paths $paths, + protected Container $container, + protected Migrator $migrator, + protected Dispatcher $dispatcher, + protected Filesystem $filesystem ) { - $this->config = $config; - $this->paths = $paths; - $this->container = $container; - $this->migrator = $migrator; - $this->dispatcher = $dispatcher; - $this->filesystem = $filesystem; } - /** - * @return Collection - */ - public function getExtensions() + public function getExtensions(): Collection { if (is_null($this->extensions) && $this->filesystem->exists($this->paths->vendor.'/composer/installed.json')) { $extensions = new Collection(); @@ -165,25 +132,15 @@ class ExtensionManager }); } - /** - * Loads an Extension with all information. - * - * @param string $name - * @return Extension|null - */ - public function getExtension($name) + public function getExtension(string $name): ?Extension { return $this->getExtensions()->get($name); } /** - * Enables the extension. - * - * @param string $name - * * @internal */ - public function enable($name) + public function enable(string $name): void { if ($this->isEnabled($name)) { return; @@ -219,13 +176,9 @@ class ExtensionManager } /** - * Disables an extension. - * - * @param string $name - * * @internal */ - public function disable($name) + public function disable(string $name): void { $extension = $this->getExtension($name); $enabledExtensions = $this->getEnabledExtensions(); @@ -257,12 +210,9 @@ class ExtensionManager } /** - * Uninstalls an extension. - * - * @param string $name * @internal */ - public function uninstall($name) + public function uninstall(string $name): void { $extension = $this->getExtension($name); @@ -279,38 +229,30 @@ class ExtensionManager /** * Copy the assets from an extension's assets directory into public view. - * - * @param Extension $extension */ - protected function publishAssets(Extension $extension) + protected function publishAssets(Extension $extension): void { $extension->copyAssetsTo($this->getAssetsFilesystem()); } /** * Delete an extension's assets from public view. - * - * @param Extension $extension */ - protected function unpublishAssets(Extension $extension) + protected function unpublishAssets(Extension $extension): void { $this->getAssetsFilesystem()->deleteDirectory('extensions/'.$extension->getId()); } /** * Get the path to an extension's published asset. - * - * @param Extension $extension - * @param string $path - * @return string */ - public function getAsset(Extension $extension, $path) + public function getAsset(Extension $extension, string $path): string { return $this->getAssetsFilesystem()->url($extension->getId()."/$path"); } /** - * Get an instance of the assets filesystem. + * Get an instance of the `assets` filesystem. * This is resolved dynamically because Flarum's filesystem configuration * might not be booted yet when the ExtensionManager singleton initializes. */ @@ -322,13 +264,9 @@ class ExtensionManager /** * Runs the database migrations for the extension. * - * @param Extension $extension - * @param string $direction - * @return int - * * @internal */ - public function migrate(Extension $extension, $direction = 'up') + public function migrate(Extension $extension, string $direction = 'up'): ?int { $this->container->bind(Builder::class, function ($container) { return $container->make(ConnectionInterface::class)->getSchemaBuilder(); @@ -340,32 +278,25 @@ class ExtensionManager /** * Runs the database migrations to reset the database to its old state. * - * @param Extension $extension - * @return void - * * @internal */ - public function migrateDown(Extension $extension) + public function migrateDown(Extension $extension): void { $this->migrate($extension, 'down'); } /** * The database migrator. - * - * @return Migrator */ - public function getMigrator() + public function getMigrator(): Migrator { return $this->migrator; } /** - * Get only enabled extensions. - * - * @return array|Extension[] + * @return Extension[] */ - public function getEnabledExtensions() + public function getEnabledExtensions(): array { $enabled = []; $extensions = $this->getExtensions(); @@ -381,10 +312,8 @@ class ExtensionManager /** * Call on all enabled extensions to extend the Flarum application. - * - * @param Container $container */ - public function extend(Container $container) + public function extend(Container $container): void { foreach ($this->getEnabledExtensions() as $extension) { $extension->extend($container); @@ -394,9 +323,9 @@ class ExtensionManager /** * The id's of the enabled extensions. * - * @return array + * @return string[] */ - public function getEnabled() + public function getEnabled(): array { return json_decode($this->config->get('extensions_enabled'), true) ?? []; } @@ -404,10 +333,10 @@ class ExtensionManager /** * Persist the currently enabled extensions. * - * @param array $enabledExtensions + * @param Extension[] $enabledExtensions * @throws CircularDependenciesException */ - protected function setEnabledExtensions(array $enabledExtensions) + protected function setEnabledExtensions(array $enabledExtensions): void { $resolved = static::resolveExtensionOrder($enabledExtensions); @@ -426,13 +355,7 @@ class ExtensionManager $this->config->set('extensions_enabled', json_encode($sortedEnabledIds)); } - /** - * Whether the extension is enabled. - * - * @param $extension - * @return bool - */ - public function isEnabled($extension) + public function isEnabled(string $extension): bool { $enabled = $this->getEnabledExtensions(); @@ -442,14 +365,14 @@ class ExtensionManager /** * Returns the titles of the extensions passed. * - * @param array $exts + * @param Extension[] $extensions * @return string[] */ - public static function pluckTitles(array $exts) + public static function pluckTitles(array $extensions): array { return array_map(function (Extension $extension) { return $extension->getTitle(); - }, $exts); + }, $extensions); } /** @@ -467,7 +390,7 @@ class ExtensionManager * * @internal */ - public static function resolveExtensionOrder($extensionList) + public static function resolveExtensionOrder(array $extensionList): array { $extensionIdMapping = []; // Used for caching so we don't rerun ->getExtensions every time. diff --git a/framework/core/src/Extension/ExtensionServiceProvider.php b/framework/core/src/Extension/ExtensionServiceProvider.php index 648b0285e..861ca3133 100644 --- a/framework/core/src/Extension/ExtensionServiceProvider.php +++ b/framework/core/src/Extension/ExtensionServiceProvider.php @@ -15,10 +15,7 @@ use Illuminate\Contracts\Events\Dispatcher; class ExtensionServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton(ExtensionManager::class); $this->container->alias(ExtensionManager::class, 'flarum.extensions'); @@ -32,10 +29,7 @@ class ExtensionServiceProvider extends AbstractServiceProvider }); } - /** - * {@inheritdoc} - */ - public function boot(Dispatcher $events) + public function boot(Dispatcher $events): void { $events->listen( Disabling::class, diff --git a/framework/core/src/Filesystem/FilesystemManager.php b/framework/core/src/Filesystem/FilesystemManager.php index 95e3c057f..4188fd4f2 100644 --- a/framework/core/src/Filesystem/FilesystemManager.php +++ b/framework/core/src/Filesystem/FilesystemManager.php @@ -21,20 +21,14 @@ use InvalidArgumentException; class FilesystemManager extends LaravelFilesystemManager { - protected $diskLocalConfig = []; - protected $drivers = []; - - public function __construct(Container $app, array $diskLocalConfig, array $drivers) - { + public function __construct( + Container $app, + protected array $diskLocalConfig, + protected array $drivers + ) { parent::__construct($app); - - $this->diskLocalConfig = $diskLocalConfig; - $this->drivers = $drivers; } - /** - * @inheritDoc - */ protected function resolve($name, $config = null): Filesystem { $localConfig = $config ?? $this->getLocalConfig($name); @@ -55,10 +49,7 @@ class FilesystemManager extends LaravelFilesystemManager return $driver->build($name, $settings, $config, $localConfig); } - /** - * @return string|DriverInterface - */ - protected function getDriver(string $name) + protected function getDriver(string $name): string|DriverInterface { $config = $this->app->make(Config::class); $settings = $this->app->make(SettingsRepositoryInterface::class); diff --git a/framework/core/src/Filesystem/FilesystemServiceProvider.php b/framework/core/src/Filesystem/FilesystemServiceProvider.php index 0c3d2cb5b..cbba4fb66 100644 --- a/framework/core/src/Filesystem/FilesystemServiceProvider.php +++ b/framework/core/src/Filesystem/FilesystemServiceProvider.php @@ -23,10 +23,7 @@ class FilesystemServiceProvider extends AbstractServiceProvider { protected const INTERVENTION_DRIVERS = ['gd' => 'gd', 'imagick' => 'imagick']; - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('files', function () { return new Filesystem; diff --git a/framework/core/src/Filter/AbstractFilterer.php b/framework/core/src/Filter/AbstractFilterer.php index db18b21ec..7db2e197c 100644 --- a/framework/core/src/Filter/AbstractFilterer.php +++ b/framework/core/src/Filter/AbstractFilterer.php @@ -14,35 +14,22 @@ use Flarum\Query\QueryCriteria; use Flarum\Query\QueryResults; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Arr; use InvalidArgumentException; abstract class AbstractFilterer { use ApplyQueryParametersTrait; - protected $filters; - - protected $filterMutators; - - /** - * @param array $filters - * @param array $filterMutators - */ - public function __construct(array $filters, array $filterMutators) - { - $this->filters = $filters; - $this->filterMutators = $filterMutators; + public function __construct( + /** @var array */ + protected array $filters, + protected array $filterMutators + ) { } abstract protected function getQuery(User $actor): Builder; /** - * @param QueryCriteria $criteria - * @param int|null $limit - * @param int $offset - * - * @return QueryResults * @throws InvalidArgumentException */ public function filter(QueryCriteria $criteria, int $limit = null, int $offset = 0): QueryResults @@ -55,11 +42,13 @@ abstract class AbstractFilterer foreach ($criteria->query as $filterKey => $filterValue) { $negate = false; - if (substr($filterKey, 0, 1) == '-') { + + if (str_starts_with($filterKey, '-')) { $negate = true; $filterKey = substr($filterKey, 1); } - foreach (Arr::get($this->filters, $filterKey, []) as $filter) { + + foreach (($this->filters[$filterKey] ?? []) as $filter) { $filterState->addActiveFilter($filter); $filter->filter($filterState, $filterValue, $negate); } diff --git a/framework/core/src/Filter/FilterInterface.php b/framework/core/src/Filter/FilterInterface.php index 4411826cc..481978a1e 100644 --- a/framework/core/src/Filter/FilterInterface.php +++ b/framework/core/src/Filter/FilterInterface.php @@ -18,8 +18,6 @@ interface FilterInterface /** * Filters a query. - * - * @todo: 2.0 change the $filterValue type to mixed, as it can be an array. */ - public function filter(FilterState $filterState, string $filterValue, bool $negate); + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void; } diff --git a/framework/core/src/Filter/FilterServiceProvider.php b/framework/core/src/Filter/FilterServiceProvider.php index 46cffadbf..0698d5ad7 100644 --- a/framework/core/src/Filter/FilterServiceProvider.php +++ b/framework/core/src/Filter/FilterServiceProvider.php @@ -26,12 +26,7 @@ use Illuminate\Support\Arr; class FilterServiceProvider extends AbstractServiceProvider { - /** - * Register the service provider. - * - * @return void - */ - public function register() + public function register(): void { $this->container->singleton('flarum.filter.filters', function () { return [ @@ -66,7 +61,7 @@ class FilterServiceProvider extends AbstractServiceProvider }); } - public function boot(Container $container) + public function boot(Container $container): void { // We can resolve the filter mutators in the when->needs->give callback, // but we need to resolve at least one regardless so we know which diff --git a/framework/core/src/Filter/FilterState.php b/framework/core/src/Filter/FilterState.php index 5597964da..9b8b19ed9 100644 --- a/framework/core/src/Filter/FilterState.php +++ b/framework/core/src/Filter/FilterState.php @@ -16,14 +16,14 @@ class FilterState extends AbstractQueryState /** * @var FilterInterface[] */ - protected $activeFilters = []; + protected array $activeFilters = []; /** * Get a list of the filters that are active. * * @return FilterInterface[] */ - public function getActiveFilters() + public function getActiveFilters(): array { return $this->activeFilters; } @@ -34,7 +34,7 @@ class FilterState extends AbstractQueryState * @param FilterInterface $filter * @return void */ - public function addActiveFilter(FilterInterface $filter) + public function addActiveFilter(FilterInterface $filter): void { $this->activeFilters[] = $filter; } diff --git a/framework/core/src/Formatter/Formatter.php b/framework/core/src/Formatter/Formatter.php index f47daae69..af2ed15b4 100644 --- a/framework/core/src/Formatter/Formatter.php +++ b/framework/core/src/Formatter/Formatter.php @@ -13,44 +13,28 @@ use Flarum\User\User; use Illuminate\Contracts\Cache\Repository; use Psr\Http\Message\ServerRequestInterface; use s9e\TextFormatter\Configurator; +use s9e\TextFormatter\Parser; use s9e\TextFormatter\Renderer; use s9e\TextFormatter\Unparser; use s9e\TextFormatter\Utils; class Formatter { - protected $configurationCallbacks = []; + protected array $configurationCallbacks = []; + protected array $parsingCallbacks = []; + protected array $unparsingCallbacks = []; + protected array $renderingCallbacks = []; - protected $parsingCallbacks = []; - - protected $unparsingCallbacks = []; - - protected $renderingCallbacks = []; - - /** - * @var Repository - */ - protected $cache; - - /** - * @var string - */ - protected $cacheDir; - - /** - * @param Repository $cache - * @param string $cacheDir - */ - public function __construct(Repository $cache, $cacheDir) - { - $this->cache = $cache; - $this->cacheDir = $cacheDir; + public function __construct( + protected Repository $cache, + protected string $cacheDir + ) { } /** * @internal */ - public function addConfigurationCallback($callback) + public function addConfigurationCallback(callable $callback): void { $this->configurationCallbacks[] = $callback; } @@ -58,7 +42,7 @@ class Formatter /** * @internal */ - public function addParsingCallback($callback) + public function addParsingCallback(callable $callback): void { $this->parsingCallbacks[] = $callback; } @@ -66,7 +50,7 @@ class Formatter /** * @internal */ - public function addUnparsingCallback($callback) + public function addUnparsingCallback(callable $callback): void { $this->unparsingCallbacks[] = $callback; } @@ -74,20 +58,12 @@ class Formatter /** * @internal */ - public function addRenderingCallback($callback) + public function addRenderingCallback(callable $callback): void { $this->renderingCallbacks[] = $callback; } - /** - * Parse text. - * - * @param string $text - * @param mixed $context - * @param User|null $user - * @return string the parsed XML - */ - public function parse($text, $context = null, User $user = null) + public function parse(string $text, mixed $context = null, User $user = null): string { $parser = $this->getParser($context); @@ -105,15 +81,7 @@ class Formatter return $parser->parse($text); } - /** - * Render parsed XML. - * - * @param string $xml - * @param mixed|null $context - * @param ServerRequestInterface|null $request - * @return string - */ - public function render($xml, $context = null, ServerRequestInterface $request = null) + public function render(string $xml, mixed $context = null, ServerRequestInterface $request = null): string { $renderer = $this->getRenderer(); @@ -121,19 +89,12 @@ class Formatter $xml = $callback($renderer, $context, $xml, $request); } - $xml = $this->configureDefaultsOnLinks($renderer, $xml, $context, $request); + $xml = $this->configureDefaultsOnLinks($xml); return $renderer->render($xml); } - /** - * Unparse XML. - * - * @param string $xml - * @param mixed $context - * @return string - */ - public function unparse($xml, $context = null) + public function unparse(string $xml, $context = null): string { foreach ($this->unparsingCallbacks as $callback) { $xml = $callback($context, $xml); @@ -145,15 +106,12 @@ class Formatter /** * Flush the cache so that the formatter components are regenerated. */ - public function flush() + public function flush(): void { $this->cache->forget('flarum.formatter'); } - /** - * @return Configurator - */ - protected function getConfigurator() + protected function getConfigurator(): Configurator { $configurator = new Configurator; @@ -182,10 +140,7 @@ class Formatter return $configurator; } - /** - * @param Configurator $configurator - */ - protected function configureExternalLinks(Configurator $configurator) + protected function configureExternalLinks(Configurator $configurator): void { /** * @var Configurator\Items\TemplateDocument $dom @@ -202,12 +157,9 @@ class Formatter } /** - * Get a TextFormatter component. - * - * @param string $name "renderer" or "parser" or "js" - * @return mixed + * Get a TextFormatter component ("renderer" or "parser" or "js"). */ - protected function getComponent($name) + protected function getComponent(string $name): mixed { $formatter = $this->cache->rememberForever('flarum.formatter', function () { return $this->getConfigurator()->finalize(); @@ -216,13 +168,7 @@ class Formatter return $formatter[$name]; } - /** - * Get the parser. - * - * @param mixed $context - * @return \s9e\TextFormatter\Parser - */ - protected function getParser($context = null) + protected function getParser(mixed $context = null): Parser { $parser = $this->getComponent('parser'); @@ -231,12 +177,7 @@ class Formatter return $parser; } - /** - * Get the renderer. - * - * @return Renderer - */ - protected function getRenderer() + protected function getRenderer(): Renderer { spl_autoload_register(function ($class) { if (file_exists($file = $this->cacheDir.'/'.$class.'.php')) { @@ -249,20 +190,14 @@ class Formatter /** * Get the formatter JavaScript. - * - * @return string */ - public function getJs() + public function getJs(): string { return $this->getComponent('js'); } - protected function configureDefaultsOnLinks( - Renderer $renderer, - string $xml, - $context = null, - ServerRequestInterface $request = null - ): string { + protected function configureDefaultsOnLinks(string $xml): string + { return Utils::replaceAttributes($xml, 'URL', function ($attributes) { $attributes['rel'] = $attributes['rel'] ?? 'ugc nofollow'; diff --git a/framework/core/src/Formatter/FormatterServiceProvider.php b/framework/core/src/Formatter/FormatterServiceProvider.php index 811f3cf1e..43008bc33 100644 --- a/framework/core/src/Formatter/FormatterServiceProvider.php +++ b/framework/core/src/Formatter/FormatterServiceProvider.php @@ -16,10 +16,7 @@ use Illuminate\Contracts\Container\Container; class FormatterServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.formatter', function (Container $container) { return new Formatter( diff --git a/framework/core/src/Forum/Auth/Registration.php b/framework/core/src/Forum/Auth/Registration.php index 3eedf3d41..2d24d3aa7 100644 --- a/framework/core/src/Forum/Auth/Registration.php +++ b/framework/core/src/Forum/Auth/Registration.php @@ -11,91 +11,49 @@ namespace Flarum\Forum\Auth; class Registration { - /** - * @var array - */ - protected $provided = []; + protected array $provided = []; + protected array $suggested = []; + protected mixed $payload; - /** - * @var array - */ - protected $suggested = []; - - /** - * @var mixed - */ - protected $payload; - - /** - * @return array - */ public function getProvided(): array { return $this->provided; } - /** - * @return array - */ public function getSuggested(): array { return $this->suggested; } - /** - * @return mixed - */ - public function getPayload() + public function getPayload(): mixed { return $this->payload; } - /** - * @param string $key - * @param mixed $value - * @return $this - */ - public function provide(string $key, $value): self + public function provide(string $key, mixed $value): self { $this->provided[$key] = $value; return $this; } - /** - * @param string $email - * @return $this - */ public function provideTrustedEmail(string $email): self { return $this->provide('email', $email); } - /** - * @param string $url - * @return $this - */ public function provideAvatar(string $url): self { return $this->provide('avatar_url', $url); } - /** - * @param string $key - * @param mixed $value - * @return $this - */ - public function suggest(string $key, $value): self + public function suggest(string $key, mixed $value): self { $this->suggested[$key] = $value; return $this; } - /** - * @param string $username - * @return $this - */ public function suggestUsername(string $username): self { $username = preg_replace('/[^a-z0-9-_]/i', '', $username); @@ -103,19 +61,11 @@ class Registration return $this->suggest('username', $username); } - /** - * @param string $email - * @return $this - */ public function suggestEmail(string $email): self { return $this->suggest('email', $email); } - /** - * @param mixed $payload - * @return $this - */ public function setPayload($payload): self { $this->payload = $payload; diff --git a/framework/core/src/Forum/Auth/ResponseFactory.php b/framework/core/src/Forum/Auth/ResponseFactory.php index ba1839440..a100aa25d 100644 --- a/framework/core/src/Forum/Auth/ResponseFactory.php +++ b/framework/core/src/Forum/Auth/ResponseFactory.php @@ -20,17 +20,9 @@ use Psr\Http\Message\ResponseInterface; class ResponseFactory { - /** - * @var Rememberer - */ - protected $rememberer; - - /** - * @param Rememberer $rememberer - */ - public function __construct(Rememberer $rememberer) - { - $this->rememberer = $rememberer; + public function __construct( + protected Rememberer $rememberer + ) { } public function make(string $provider, string $identifier, callable $configureRegistration): ResponseInterface @@ -72,7 +64,7 @@ class ResponseFactory return new HtmlResponse($content); } - private function makeLoggedInResponse(User $user) + private function makeLoggedInResponse(User $user): ResponseInterface { $response = $this->makeResponse(['loggedIn' => true]); diff --git a/framework/core/src/Forum/Content/AssertRegistered.php b/framework/core/src/Forum/Content/AssertRegistered.php index e17240e59..4c819454c 100644 --- a/framework/core/src/Forum/Content/AssertRegistered.php +++ b/framework/core/src/Forum/Content/AssertRegistered.php @@ -15,7 +15,7 @@ use Psr\Http\Message\ServerRequestInterface as Request; class AssertRegistered { - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): void { RequestUtil::getActor($request)->assertRegistered(); } diff --git a/framework/core/src/Forum/Content/Discussion.php b/framework/core/src/Forum/Content/Discussion.php index 9add89c2c..40533edec 100644 --- a/framework/core/src/Forum/Content/Discussion.php +++ b/framework/core/src/Forum/Content/Discussion.php @@ -19,34 +19,14 @@ use Psr\Http\Message\ServerRequestInterface as Request; class Discussion { - /** - * @var Client - */ - protected $api; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var Factory - */ - protected $view; - - /** - * @param Client $api - * @param UrlGenerator $url - * @param Factory $view - */ - public function __construct(Client $api, UrlGenerator $url, Factory $view) - { - $this->api = $api; - $this->url = $url; - $this->view = $view; + public function __construct( + protected Client $api, + protected UrlGenerator $url, + protected Factory $view + ) { } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): Document { $queryParams = $request->getQueryParams(); $id = Arr::get($queryParams, 'id'); diff --git a/framework/core/src/Forum/Content/Index.php b/framework/core/src/Forum/Content/Index.php index 3f02af7bb..a8af226e6 100644 --- a/framework/core/src/Forum/Content/Index.php +++ b/framework/core/src/Forum/Content/Index.php @@ -12,56 +12,24 @@ namespace Flarum\Forum\Content; use Flarum\Api\Client; use Flarum\Frontend\Document; use Flarum\Http\UrlGenerator; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface as Request; -use Symfony\Contracts\Translation\TranslatorInterface; class Index { - /** - * @var Client - */ - protected $api; - - /** - * @var Factory - */ - protected $view; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @param Client $api - * @param Factory $view - * @param SettingsRepositoryInterface $settings - * @param UrlGenerator $url - * @param TranslatorInterface $translator - */ - public function __construct(Client $api, Factory $view, SettingsRepositoryInterface $settings, UrlGenerator $url, TranslatorInterface $translator) - { - $this->api = $api; - $this->view = $view; - $this->settings = $settings; - $this->url = $url; - $this->translator = $translator; + public function __construct( + protected Client $api, + protected Factory $view, + protected SettingsRepositoryInterface $settings, + protected UrlGenerator $url, + protected TranslatorInterface $translator + ) { } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): Document { $queryParams = $request->getQueryParams(); @@ -98,12 +66,8 @@ class Index /** * Get the result of an API request to list discussions. - * - * @param Request $request - * @param array $params - * @return object */ - 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()); } diff --git a/framework/core/src/Forum/Content/User.php b/framework/core/src/Forum/Content/User.php index 50a67f761..08ebffde7 100644 --- a/framework/core/src/Forum/Content/User.php +++ b/framework/core/src/Forum/Content/User.php @@ -18,27 +18,13 @@ use Psr\Http\Message\ServerRequestInterface as Request; class User { - /** - * @var Client - */ - protected $api; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param Client $api - * @param UrlGenerator $url - */ - public function __construct(Client $api, UrlGenerator $url) - { - $this->api = $api; - $this->url = $url; + public function __construct( + protected Client $api, + protected UrlGenerator $url + ) { } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): Document { $queryParams = $request->getQueryParams(); $username = Arr::get($queryParams, 'username'); diff --git a/framework/core/src/Forum/Controller/ConfirmEmailController.php b/framework/core/src/Forum/Controller/ConfirmEmailController.php index f57572ae2..2b1be5a18 100644 --- a/framework/core/src/Forum/Controller/ConfirmEmailController.php +++ b/framework/core/src/Forum/Controller/ConfirmEmailController.php @@ -22,37 +22,13 @@ use Psr\Http\Server\RequestHandlerInterface; class ConfirmEmailController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $bus; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @param Dispatcher $bus - * @param UrlGenerator $url - * @param SessionAuthenticator $authenticator - */ - public function __construct(Dispatcher $bus, UrlGenerator $url, SessionAuthenticator $authenticator) - { - $this->bus = $bus; - $this->url = $url; - $this->authenticator = $authenticator; + public function __construct( + protected Dispatcher $bus, + protected UrlGenerator $url, + protected SessionAuthenticator $authenticator + ) { } - /** - * @param Request $request - * @return ResponseInterface - */ public function handle(Request $request): ResponseInterface { $token = Arr::get($request->getQueryParams(), 'token'); diff --git a/framework/core/src/Forum/Controller/ConfirmEmailViewController.php b/framework/core/src/Forum/Controller/ConfirmEmailViewController.php index 865d1fa22..df73c270d 100644 --- a/framework/core/src/Forum/Controller/ConfirmEmailViewController.php +++ b/framework/core/src/Forum/Controller/ConfirmEmailViewController.php @@ -12,35 +12,25 @@ namespace Flarum\Forum\Controller; use Flarum\Http\Controller\AbstractHtmlController; use Flarum\User\EmailToken; use Illuminate\Contracts\View\Factory; +use Illuminate\Contracts\View\View; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface as Request; class ConfirmEmailViewController extends AbstractHtmlController { - /** - * @var Factory - */ - protected $view; - - /** - * @param Factory $view - */ - public function __construct(Factory $view) - { - $this->view = $view; + public function __construct( + protected Factory $view + ) { } - /** - * @param Request $request - * @return \Illuminate\Contracts\View\View - */ - public function render(Request $request) + public function render(Request $request): View { $token = Arr::get($request->getQueryParams(), 'token'); - $token = EmailToken::validOrFail($token); + EmailToken::validOrFail($token); - return $this->view->make('flarum.forum::confirm-email') + return $this->view + ->make('flarum.forum::confirm-email') ->with('csrfToken', $request->getAttribute('session')->token()); } } diff --git a/framework/core/src/Forum/Controller/GlobalLogOutController.php b/framework/core/src/Forum/Controller/GlobalLogOutController.php index 0a9b3ed97..609ef2f17 100644 --- a/framework/core/src/Forum/Controller/GlobalLogOutController.php +++ b/framework/core/src/Forum/Controller/GlobalLogOutController.php @@ -22,36 +22,12 @@ use Psr\Http\Server\RequestHandlerInterface; class GlobalLogOutController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @var Rememberer - */ - protected $rememberer; - - /** - * @var UrlGenerator - */ - protected $url; - public function __construct( - Dispatcher $events, - SessionAuthenticator $authenticator, - Rememberer $rememberer, - UrlGenerator $url + protected Dispatcher $events, + protected SessionAuthenticator $authenticator, + protected Rememberer $rememberer, + protected UrlGenerator $url ) { - $this->events = $events; - $this->authenticator = $authenticator; - $this->rememberer = $rememberer; - $this->url = $url; } public function handle(Request $request): ResponseInterface diff --git a/framework/core/src/Forum/Controller/LogInController.php b/framework/core/src/Forum/Controller/LogInController.php index 86de9ceeb..e30b10846 100644 --- a/framework/core/src/Forum/Controller/LogInController.php +++ b/framework/core/src/Forum/Controller/LogInController.php @@ -25,56 +25,16 @@ use Psr\Http\Server\RequestHandlerInterface; class LogInController implements RequestHandlerInterface { - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @var Client - */ - protected $apiClient; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var Rememberer - */ - protected $rememberer; - - /** - * @var LogInValidator - */ - protected $validator; - - /** - * @param \Flarum\User\UserRepository $users - * @param Client $apiClient - * @param SessionAuthenticator $authenticator - * @param Rememberer $rememberer - * @param LogInValidator $validator - */ - public function __construct(UserRepository $users, Client $apiClient, SessionAuthenticator $authenticator, Dispatcher $events, Rememberer $rememberer, LogInValidator $validator) - { - $this->users = $users; - $this->apiClient = $apiClient; - $this->authenticator = $authenticator; - $this->events = $events; - $this->rememberer = $rememberer; - $this->validator = $validator; + public function __construct( + protected UserRepository $users, + protected Client $apiClient, + protected SessionAuthenticator $authenticator, + protected Dispatcher $events, + protected Rememberer $rememberer, + protected LogInValidator $validator + ) { } - /** - * {@inheritdoc} - */ public function handle(Request $request): ResponseInterface { $body = $request->getParsedBody(); diff --git a/framework/core/src/Forum/Controller/LogOutController.php b/framework/core/src/Forum/Controller/LogOutController.php index f5eb88d30..5744946f4 100644 --- a/framework/core/src/Forum/Controller/LogOutController.php +++ b/framework/core/src/Forum/Controller/LogOutController.php @@ -9,7 +9,6 @@ namespace Flarum\Forum\Controller; -use Flarum\Http\Exception\TokenMismatchException; use Flarum\Http\Rememberer; use Flarum\Http\RequestUtil; use Flarum\Http\SessionAuthenticator; @@ -26,57 +25,15 @@ use Psr\Http\Server\RequestHandlerInterface; class LogOutController implements RequestHandlerInterface { - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @var Rememberer - */ - protected $rememberer; - - /** - * @var Factory - */ - protected $view; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @param Dispatcher $events - * @param SessionAuthenticator $authenticator - * @param Rememberer $rememberer - * @param Factory $view - * @param UrlGenerator $url - */ public function __construct( - Dispatcher $events, - SessionAuthenticator $authenticator, - Rememberer $rememberer, - Factory $view, - UrlGenerator $url + protected Dispatcher $events, + protected SessionAuthenticator $authenticator, + protected Rememberer $rememberer, + protected Factory $view, + protected UrlGenerator $url ) { - $this->events = $events; - $this->authenticator = $authenticator; - $this->rememberer = $rememberer; - $this->view = $view; - $this->url = $url; } - /** - * @param Request $request - * @return ResponseInterface - * @throws TokenMismatchException - */ public function handle(Request $request): ResponseInterface { $session = $request->getAttribute('session'); diff --git a/framework/core/src/Forum/Controller/RegisterController.php b/framework/core/src/Forum/Controller/RegisterController.php index e732101e9..8ea02956b 100644 --- a/framework/core/src/Forum/Controller/RegisterController.php +++ b/framework/core/src/Forum/Controller/RegisterController.php @@ -19,36 +19,13 @@ use Psr\Http\Server\RequestHandlerInterface; class RegisterController implements RequestHandlerInterface { - /** - * @var Client - */ - protected $api; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @var Rememberer - */ - protected $rememberer; - - /** - * @param Client $api - * @param SessionAuthenticator $authenticator - * @param Rememberer $rememberer - */ - public function __construct(Client $api, SessionAuthenticator $authenticator, Rememberer $rememberer) - { - $this->api = $api; - $this->authenticator = $authenticator; - $this->rememberer = $rememberer; + public function __construct( + protected Client $api, + protected SessionAuthenticator $authenticator, + protected Rememberer $rememberer + ) { } - /** - * {@inheritdoc} - */ public function handle(Request $request): ResponseInterface { $params = ['data' => ['attributes' => $request->getParsedBody()]]; diff --git a/framework/core/src/Forum/Controller/ResetPasswordController.php b/framework/core/src/Forum/Controller/ResetPasswordController.php index c698efb66..482487ec1 100644 --- a/framework/core/src/Forum/Controller/ResetPasswordController.php +++ b/framework/core/src/Forum/Controller/ResetPasswordController.php @@ -14,30 +14,18 @@ use Flarum\Http\Controller\AbstractHtmlController; use Flarum\User\Exception\InvalidConfirmationTokenException; use Flarum\User\PasswordToken; use Illuminate\Contracts\View\Factory; +use Illuminate\Contracts\View\View; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface as Request; class ResetPasswordController extends AbstractHtmlController { - /** - * @var Factory - */ - protected $view; - - /** - * @param Factory $view - */ - public function __construct(Factory $view) - { - $this->view = $view; + public function __construct( + protected Factory $view + ) { } - /** - * @param Request $request - * @return \Illuminate\Contracts\View\View - * @throws \Flarum\User\Exception\InvalidConfirmationTokenException - */ - public function render(Request $request) + public function render(Request $request): View { $token = Arr::get($request->getQueryParams(), 'token'); @@ -47,7 +35,8 @@ class ResetPasswordController extends AbstractHtmlController throw new InvalidConfirmationTokenException; } - return $this->view->make('flarum.forum::reset-password') + return $this->view + ->make('flarum.forum::reset-password') ->with('passwordToken', $token->token) ->with('csrfToken', $request->getAttribute('session')->token()); } diff --git a/framework/core/src/Forum/Controller/SavePasswordController.php b/framework/core/src/Forum/Controller/SavePasswordController.php index 6543db20c..81d7b105b 100644 --- a/framework/core/src/Forum/Controller/SavePasswordController.php +++ b/framework/core/src/Forum/Controller/SavePasswordController.php @@ -29,45 +29,15 @@ class SavePasswordController implements RequestHandlerInterface { use DispatchEventsTrait; - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var \Flarum\User\UserValidator - */ - protected $validator; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @var Factory - */ - protected $validatorFactory; - - /** - * @param UrlGenerator $url - * @param SessionAuthenticator $authenticator - * @param UserValidator $validator - * @param Factory $validatorFactory - */ - public function __construct(UrlGenerator $url, SessionAuthenticator $authenticator, UserValidator $validator, Factory $validatorFactory, Dispatcher $events) - { - $this->url = $url; - $this->authenticator = $authenticator; - $this->validator = $validator; - $this->validatorFactory = $validatorFactory; - $this->events = $events; + public function __construct( + protected UrlGenerator $url, + protected SessionAuthenticator $authenticator, + protected UserValidator $validator, + protected Factory $validatorFactory, + protected Dispatcher $events + ) { } - /** - * @param Request $request - * @return ResponseInterface - */ public function handle(Request $request): ResponseInterface { $input = $request->getParsedBody(); diff --git a/framework/core/src/Forum/ForumServiceProvider.php b/framework/core/src/Forum/ForumServiceProvider.php index 57579e410..875fe27ca 100644 --- a/framework/core/src/Forum/ForumServiceProvider.php +++ b/framework/core/src/Forum/ForumServiceProvider.php @@ -39,10 +39,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class ForumServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->extend(UrlGenerator::class, function (UrlGenerator $url, Container $container) { return $url->addCollection('forum', $container->make('flarum.forum.routes')); @@ -140,7 +137,7 @@ class ForumServiceProvider extends AbstractServiceProvider }); } - public function boot(Container $container, Dispatcher $events, Factory $view) + public function boot(Container $container, Dispatcher $events, Factory $view): void { $this->loadViewsFrom(__DIR__.'/../../views', 'flarum.forum'); @@ -193,13 +190,7 @@ class ForumServiceProvider extends AbstractServiceProvider ); } - /** - * Populate the forum client routes. - * - * @param RouteCollection $routes - * @param Container $container - */ - protected function populateRoutes(RouteCollection $routes, Container $container) + protected function populateRoutes(RouteCollection $routes, Container $container): void { $factory = $container->make(RouteHandlerFactory::class); @@ -207,13 +198,7 @@ class ForumServiceProvider extends AbstractServiceProvider $callback($routes, $factory); } - /** - * Determine the default route. - * - * @param RouteCollection $routes - * @param Container $container - */ - protected function setDefaultRoute(RouteCollection $routes, Container $container) + protected function setDefaultRoute(RouteCollection $routes, Container $container): void { $factory = $container->make(RouteHandlerFactory::class); $defaultRoute = $container->make('flarum.settings')->get('default_route'); diff --git a/framework/core/src/Forum/LogInValidator.php b/framework/core/src/Forum/LogInValidator.php index 33035ae6a..bdf21b3ee 100644 --- a/framework/core/src/Forum/LogInValidator.php +++ b/framework/core/src/Forum/LogInValidator.php @@ -13,8 +13,5 @@ use Flarum\Foundation\AbstractValidator; class LogInValidator extends AbstractValidator { - /** - * {@inheritdoc} - */ - protected $rules = []; + protected array $rules = []; } diff --git a/framework/core/src/Forum/ValidateCustomLess.php b/framework/core/src/Forum/ValidateCustomLess.php index 808a812f5..266440b45 100644 --- a/framework/core/src/Forum/ValidateCustomLess.php +++ b/framework/core/src/Forum/ValidateCustomLess.php @@ -28,35 +28,15 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class ValidateCustomLess { - /** - * @var Assets - */ - protected $assets; - - /** - * @var LocaleManager - */ - protected $locales; - - /** - * @var Container - */ - protected $container; - - /** - * @var array - */ - protected $customLessSettings; - - public function __construct(Assets $assets, LocaleManager $locales, Container $container, array $customLessSettings = []) - { - $this->assets = $assets; - $this->locales = $locales; - $this->container = $container; - $this->customLessSettings = $customLessSettings; + public function __construct( + protected Assets $assets, + protected LocaleManager $locales, + protected Container $container, + protected array $customLessSettings = [] + ) { } - public function whenSettingsSaving(Saving $event) + public function whenSettingsSaving(Saving $event): void { if (! isset($event->settings['custom_less']) && ! $this->hasDirtyCustomLessSettings($event)) { return; @@ -104,7 +84,7 @@ class ValidateCustomLess $this->container->instance(SettingsRepositoryInterface::class, $settings); } - public function whenSettingsSaved(Saved $event) + public function whenSettingsSaved(Saved $event): void { if (! isset($event->settings['custom_less']) && ! $this->hasDirtyCustomLessSettings($event)) { return; @@ -117,11 +97,7 @@ class ValidateCustomLess } } - /** - * @param Saved|Saving $event - * @return bool - */ - protected function hasDirtyCustomLessSettings($event): bool + protected function hasDirtyCustomLessSettings(Saved|Saving $event): bool { if (empty($this->customLessSettings)) { return false; diff --git a/framework/core/src/Foundation/AbstractServiceProvider.php b/framework/core/src/Foundation/AbstractServiceProvider.php index 22e32ca67..97f699da9 100644 --- a/framework/core/src/Foundation/AbstractServiceProvider.php +++ b/framework/core/src/Foundation/AbstractServiceProvider.php @@ -20,23 +20,12 @@ abstract class AbstractServiceProvider extends ServiceProvider */ protected $app; - /** - * @var Container - */ - protected $container; - - /** - * @param Container $container - */ - public function __construct(Container $container) - { - $this->app = $container; - $this->container = $container; + public function __construct( + protected Container $container + ) { + parent::__construct($container); } - /** - * {@inheritdoc} - */ public function register() { } diff --git a/framework/core/src/Foundation/AbstractValidator.php b/framework/core/src/Foundation/AbstractValidator.php index 5629213aa..fc04a263c 100644 --- a/framework/core/src/Foundation/AbstractValidator.php +++ b/framework/core/src/Foundation/AbstractValidator.php @@ -9,54 +9,39 @@ namespace Flarum\Foundation; +use Flarum\Locale\TranslatorInterface; use Illuminate\Support\Arr; use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationException; -use Symfony\Contracts\Translation\TranslatorInterface; +use Illuminate\Validation\Validator; abstract class AbstractValidator { + /** + * @var callable[] + */ + protected array $configuration = []; + /** * @var array */ - protected $configuration = []; + protected array $rules = []; - public function addConfiguration($callable) + public function __construct( + protected Factory $validator, + protected TranslatorInterface $translator + ) { + } + + public function addConfiguration($callable): void { $this->configuration[] = $callable; } - /** - * @var array - */ - protected $rules = []; - - /** - * @var Factory - */ - protected $validator; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @param Factory $validator - * @param TranslatorInterface $translator - */ - public function __construct(Factory $validator, TranslatorInterface $translator) - { - $this->validator = $validator; - $this->translator = $translator; - } - /** * Throw an exception if a model is not valid. - * - * @param array $attributes */ - public function assertValid(array $attributes) + public function assertValid(array $attributes): void { $validator = $this->makeValidator($attributes); @@ -65,29 +50,17 @@ abstract class AbstractValidator } } - /** - * @return array - */ - protected function getRules() + protected function getRules(): array { return $this->rules; } - /** - * @return array - */ - protected function getMessages() + protected function getMessages(): array { return []; } - /** - * Make a new validator instance for this model. - * - * @param array $attributes - * @return \Illuminate\Validation\Validator - */ - protected function makeValidator(array $attributes) + protected function makeValidator(array $attributes): Validator { $rules = Arr::only($this->getRules(), array_keys($attributes)); diff --git a/framework/core/src/Foundation/AppInterface.php b/framework/core/src/Foundation/AppInterface.php index 34181814b..4ffb48317 100644 --- a/framework/core/src/Foundation/AppInterface.php +++ b/framework/core/src/Foundation/AppInterface.php @@ -9,15 +9,15 @@ namespace Flarum\Foundation; +use Psr\Http\Server\RequestHandlerInterface; +use Symfony\Component\Console\Command\Command; + interface AppInterface { - /** - * @return \Psr\Http\Server\RequestHandlerInterface - */ - public function getRequestHandler(); + public function getRequestHandler(): RequestHandlerInterface; /** - * @return \Symfony\Component\Console\Command\Command[] + * @return Command[] */ - public function getConsoleCommands(); + public function getConsoleCommands(): array; } diff --git a/framework/core/src/Foundation/Application.php b/framework/core/src/Foundation/Application.php index aa1530886..4ed1dcdfe 100644 --- a/framework/core/src/Foundation/Application.php +++ b/framework/core/src/Foundation/Application.php @@ -23,100 +23,38 @@ class Application */ const VERSION = '2.0-dev'; - /** - * The IoC container for the Flarum application. - * - * @var Container - */ - private $container; + protected bool $booted = false; - /** - * The paths for the Flarum installation. - * - * @var Paths - */ - protected $paths; + protected array $bootingCallbacks = []; - /** - * Indicates if the application has "booted". - * - * @var bool - */ - protected $booted = false; + protected array $bootedCallbacks = []; - /** - * The array of booting callbacks. - * - * @var array - */ - protected $bootingCallbacks = []; + protected array $serviceProviders = []; - /** - * The array of booted callbacks. - * - * @var array - */ - protected $bootedCallbacks = []; - - /** - * All of the registered service providers. - * - * @var array - */ - protected $serviceProviders = []; - - /** - * The names of the loaded service providers. - * - * @var array - */ - protected $loadedProviders = []; - - /** - * Create a new Flarum application instance. - * - * @param Container $container - * @param Paths $paths - */ - public function __construct(Container $container, Paths $paths) - { - $this->container = $container; - $this->paths = $paths; + protected array $loadedProviders = []; + public function __construct( + private readonly Container $container, + protected Paths $paths + ) { $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); } - /** - * @param string $key - * @param mixed $default - * @return mixed - */ - public function config($key, $default = null) + public function config(string $key, mixed $default = null): mixed { $config = $this->container->make('flarum.config'); return $config[$key] ?? $default; } - /** - * Check if Flarum is in debug mode. - * - * @return bool - */ - public function inDebugMode() + public function inDebugMode(): bool { return $this->config('debug', true); } - /** - * Get the URL to the Flarum installation. - * - * @param string $path - * @return string - */ - public function url($path = null) + public function url(string $path = null): string { $config = $this->container->make('flarum.config'); $url = (string) $config->url(); @@ -128,10 +66,7 @@ class Application return $url; } - /** - * Register the basic bindings into the container. - */ - protected function registerBaseBindings() + protected function registerBaseBindings(): void { \Illuminate\Container\Container::setInstance($this->container); @@ -152,23 +87,12 @@ class Application $this->container->alias('flarum.paths', Paths::class); } - /** - * Register all of the base service providers. - */ - protected function registerBaseServiceProviders() + protected function registerBaseServiceProviders(): void { $this->register(new EventServiceProvider($this->container)); } - /** - * Register a service provider with the application. - * - * @param ServiceProvider|string $provider - * @param array $options - * @param bool $force - * @return ServiceProvider - */ - public function register($provider, $options = [], $force = false) + public function register(string|ServiceProvider $provider, array $options = [], bool $force = false): ServiceProvider { if (($registered = $this->getProvider($provider)) && ! $force) { return $registered; @@ -202,13 +126,7 @@ class Application return $provider; } - /** - * Get the registered service provider instance if it exists. - * - * @param ServiceProvider|string $provider - * @return ServiceProvider|null - */ - public function getProvider($provider) + public function getProvider(string|ServiceProvider $provider): ?ServiceProvider { $name = is_string($provider) ? $provider : get_class($provider); @@ -220,21 +138,14 @@ class Application /** * Resolve a service provider instance from the class name. * - * @param string $provider - * @return ServiceProvider + * @param class-string $provider */ - public function resolveProviderClass($provider) + public function resolveProviderClass(string $provider): ServiceProvider { return new $provider($this->container); } - /** - * Mark the given provider as registered. - * - * @param ServiceProvider $provider - * @return void - */ - protected function markAsRegistered($provider) + protected function markAsRegistered(ServiceProvider $provider): void { $this->container['events']->dispatch($class = get_class($provider), [$provider]); @@ -243,22 +154,12 @@ class Application $this->loadedProviders[$class] = true; } - /** - * Determine if the application has booted. - * - * @return bool - */ - public function isBooted() + public function isBooted(): bool { return $this->booted; } - /** - * Boot the application's service providers. - * - * @return void - */ - public function boot() + public function boot(): void { if ($this->booted) { return; @@ -278,37 +179,21 @@ class Application $this->fireAppCallbacks($this->bootedCallbacks); } - /** - * Boot the given service provider. - * - * @param ServiceProvider $provider - * @return mixed - */ - protected function bootProvider(ServiceProvider $provider) + protected function bootProvider(ServiceProvider $provider): mixed { if (method_exists($provider, 'boot')) { return $this->container->call([$provider, 'boot']); } + + return null; } - /** - * Register a new boot listener. - * - * @param mixed $callback - * @return void - */ - public function booting($callback) + public function booting(mixed $callback): void { $this->bootingCallbacks[] = $callback; } - /** - * Register a new "booted" listener. - * - * @param mixed $callback - * @return void - */ - public function booted($callback) + public function booted(mixed $callback): void { $this->bootedCallbacks[] = $callback; @@ -317,23 +202,14 @@ class Application } } - /** - * Call the booting callbacks for the application. - * - * @param array $callbacks - * @return void - */ - protected function fireAppCallbacks(array $callbacks) + protected function fireAppCallbacks(array $callbacks): void { foreach ($callbacks as $callback) { call_user_func($callback, $this); } } - /** - * Register the core class aliases in the container. - */ - public function registerCoreContainerAliases() + public function registerCoreContainerAliases(): void { $aliases = [ 'app' => [\Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class], @@ -354,8 +230,8 @@ class Application 'view' => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class], ]; - foreach ($aliases as $key => $aliases) { - foreach ((array) $aliases as $alias) { + foreach ($aliases as $key => $aliasGroup) { + foreach ($aliasGroup as $alias) { $this->container->alias($key, $alias); } } diff --git a/framework/core/src/Foundation/ApplicationInfoProvider.php b/framework/core/src/Foundation/ApplicationInfoProvider.php index c15c6de0e..523c27195 100644 --- a/framework/core/src/Foundation/ApplicationInfoProvider.php +++ b/framework/core/src/Foundation/ApplicationInfoProvider.php @@ -23,91 +23,23 @@ use SessionHandlerInterface; class ApplicationInfoProvider { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Translator - */ - protected $translator; - - /** - * @var Schedule - */ - protected $schedule; - - /** - * @var ConnectionInterface - */ - protected $db; - - /** - * @var Config - */ - protected $config; - - /** - * @var SessionManager - */ - protected $session; - - /** - * @var SessionHandlerInterface - */ - protected $sessionHandler; - - /** - * @var Queue - */ - protected $queue; - - /** - * @param SettingsRepositoryInterface $settings - * @param Translator $translator - * @param Schedule $schedule - * @param ConnectionInterface $db - * @param Config $config - * @param SessionManager $session - * @param SessionHandlerInterface $sessionHandler - * @param Queue $queue - */ public function __construct( - SettingsRepositoryInterface $settings, - Translator $translator, - Schedule $schedule, - ConnectionInterface $db, - Config $config, - SessionManager $session, - SessionHandlerInterface $sessionHandler, - Queue $queue + protected SettingsRepositoryInterface $settings, + protected Translator $translator, + protected Schedule $schedule, + protected ConnectionInterface $db, + protected Config $config, + protected SessionManager $session, + protected SessionHandlerInterface $sessionHandler, + protected Queue $queue ) { - $this->settings = $settings; - $this->translator = $translator; - $this->schedule = $schedule; - $this->db = $db; - $this->config = $config; - $this->session = $session; - $this->sessionHandler = $sessionHandler; - $this->queue = $queue; } - /** - * Identify if any tasks are registered with the scheduler. - * - * @return bool - */ public function scheduledTasksRegistered(): bool { return count($this->schedule->events()) > 0; } - /** - * Gets the current status of the scheduler. - * - * @return string - */ public function getSchedulerStatus(): string { $status = $this->settings->get('schedule.last_run'); @@ -122,11 +54,6 @@ class ApplicationInfoProvider : $this->translator->trans('core.admin.dashboard.status.scheduler.inactive'); } - /** - * Identify the queue driver in use. - * - * @return string - */ public function identifyQueueDriver(): string { // Get class name @@ -141,11 +68,6 @@ class ApplicationInfoProvider return $queue; } - /** - * Identify the version of the database we are connected to. - * - * @return string - */ public function identifyDatabaseVersion(): string { return $this->db->selectOne('select version() as version')->version; @@ -200,11 +122,6 @@ class ApplicationInfoProvider return $driver; } - /** - * Identifiy the current PHP version. - * - * @return string - */ public function identifyPHPVersion(): string { return PHP_VERSION; diff --git a/framework/core/src/Foundation/Config.php b/framework/core/src/Foundation/Config.php index 5163c97c6..ec20e4cfd 100644 --- a/framework/core/src/Foundation/Config.php +++ b/framework/core/src/Foundation/Config.php @@ -18,12 +18,9 @@ use RuntimeException; class Config implements ArrayAccess { - private $data; - - public function __construct(array $data) - { - $this->data = $data; - + public function __construct( + private readonly array $data + ) { $this->requireKeys('url'); } @@ -42,7 +39,7 @@ class Config implements ArrayAccess return $this->data['offline'] ?? false; } - private function requireKeys(...$keys) + private function requireKeys(...$keys): void { foreach ($keys as $key) { if (! array_key_exists($key, $this->data)) { @@ -53,8 +50,7 @@ class Config implements ArrayAccess } } - #[\ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet($offset): mixed { return Arr::get($this->data, $offset); } diff --git a/framework/core/src/Foundation/Console/AssetsPublishCommand.php b/framework/core/src/Foundation/Console/AssetsPublishCommand.php index 917667e65..635b0e113 100644 --- a/framework/core/src/Foundation/Console/AssetsPublishCommand.php +++ b/framework/core/src/Foundation/Console/AssetsPublishCommand.php @@ -14,45 +14,25 @@ use Flarum\Extension\ExtensionManager; use Flarum\Foundation\Paths; use Illuminate\Contracts\Container\Container; use Illuminate\Filesystem\Filesystem; +use Symfony\Component\Console\Command\Command; class AssetsPublishCommand extends AbstractCommand { - /** - * @var Container - */ - protected $container; - - /** - * @var Paths - */ - protected $paths; - - /** - * @param Container $container - * @param Paths $paths - */ - public function __construct(Container $container, Paths $paths) - { - $this->container = $container; - $this->paths = $paths; - + public function __construct( + protected Container $container, + protected Paths $paths + ) { parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('assets:publish') ->setDescription('Publish core and extension assets.'); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $this->info('Publishing core assets...'); @@ -78,5 +58,7 @@ class AssetsPublishCommand extends AbstractCommand $extension->copyAssetsTo($target); } } + + return Command::SUCCESS; } } diff --git a/framework/core/src/Foundation/Console/CacheClearCommand.php b/framework/core/src/Foundation/Console/CacheClearCommand.php index ae7c3d710..13761bb77 100644 --- a/framework/core/src/Foundation/Console/CacheClearCommand.php +++ b/framework/core/src/Foundation/Console/CacheClearCommand.php @@ -14,51 +14,26 @@ use Flarum\Foundation\Event\ClearingCache; use Flarum\Foundation\Paths; use Illuminate\Contracts\Cache\Store; use Illuminate\Contracts\Events\Dispatcher; +use Symfony\Component\Console\Command\Command; class CacheClearCommand extends AbstractCommand { - /** - * @var Store - */ - protected $cache; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var Paths - */ - protected $paths; - - /** - * @param Store $cache - * @param Paths $paths - */ - public function __construct(Store $cache, Dispatcher $events, Paths $paths) - { - $this->cache = $cache; - $this->events = $events; - $this->paths = $paths; - + public function __construct( + protected Store $cache, + protected Dispatcher $events, + protected Paths $paths + ) { parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('cache:clear') ->setDescription('Remove all temporary and generated files'); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $this->info('Clearing the cache...'); @@ -67,7 +42,7 @@ class CacheClearCommand extends AbstractCommand if (! $succeeded) { $this->error('Could not clear contents of `storage/cache`. Please adjust file permissions and try again. This can frequently be fixed by clearing cache via the `Tools` dropdown on the Administration Dashboard page.'); - return 1; + return Command::FAILURE; } $storagePath = $this->paths->storage; @@ -76,5 +51,7 @@ class CacheClearCommand extends AbstractCommand array_map('unlink', glob($storagePath.'/views/*')); $this->events->dispatch(new ClearingCache); + + return Command::SUCCESS; } } diff --git a/framework/core/src/Foundation/Console/InfoCommand.php b/framework/core/src/Foundation/Console/InfoCommand.php index 34001b2e7..4256b79fe 100644 --- a/framework/core/src/Foundation/Console/InfoCommand.php +++ b/framework/core/src/Foundation/Console/InfoCommand.php @@ -16,66 +16,30 @@ use Flarum\Foundation\ApplicationInfoProvider; use Flarum\Foundation\Config; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Database\ConnectionInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableStyle; class InfoCommand extends AbstractCommand { - /** - * @var ExtensionManager - */ - protected $extensions; - - /** - * @var Config - */ - protected $config; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var ConnectionInterface - */ - protected $db; - - /** - * @var ApplicationInfoProvider - */ - private $appInfo; - public function __construct( - ExtensionManager $extensions, - Config $config, - SettingsRepositoryInterface $settings, - ConnectionInterface $db, - ApplicationInfoProvider $appInfo + protected ExtensionManager $extensions, + protected Config $config, + protected SettingsRepositoryInterface $settings, + protected ConnectionInterface $db, + protected ApplicationInfoProvider $appInfo ) { - $this->extensions = $extensions; - $this->config = $config; - $this->settings = $settings; - $this->db = $db; - $this->appInfo = $appInfo; - parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this ->setName('info') ->setDescription("Gather information about Flarum's core and installed extensions"); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $coreVersion = $this->findPackageVersion(__DIR__.'/../../../', Application::VERSION); $this->output->writeln("Flarum core: $coreVersion"); @@ -106,9 +70,11 @@ class InfoCommand extends AbstractCommand "Don't forget to turn off debug mode! It should never be turned on in a production system." ); } + + return Command::SUCCESS; } - private function getExtensionTable() + private function getExtensionTable(): Table { $table = (new Table($this->output)) ->setHeaders([ diff --git a/framework/core/src/Foundation/Console/ScheduleRunCommand.php b/framework/core/src/Foundation/Console/ScheduleRunCommand.php index 45b2779d2..23403d47e 100644 --- a/framework/core/src/Foundation/Console/ScheduleRunCommand.php +++ b/framework/core/src/Foundation/Console/ScheduleRunCommand.php @@ -16,25 +16,13 @@ use Illuminate\Contracts\Events\Dispatcher; class ScheduleRunCommand extends \Illuminate\Console\Scheduling\ScheduleRunCommand { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * {@inheritdoc} - */ - public function __construct(SettingsRepositoryInterface $settings) - { + public function __construct( + protected SettingsRepositoryInterface $settings + ) { parent::__construct(); - - $this->settings = $settings; } - /** - * {@inheritdoc} - */ - public function handle(Schedule $schedule, Dispatcher $dispatcher, ExceptionHandler $handler) + public function handle(Schedule $schedule, Dispatcher $dispatcher, ExceptionHandler $handler): void { parent::handle($schedule, $dispatcher, $handler); diff --git a/framework/core/src/Foundation/ContainerUtil.php b/framework/core/src/Foundation/ContainerUtil.php index acc571bd5..bf7d859e5 100644 --- a/framework/core/src/Foundation/ContainerUtil.php +++ b/framework/core/src/Foundation/ContainerUtil.php @@ -16,12 +16,13 @@ class ContainerUtil /** * Wraps a callback so that string-based invokable classes get resolved only when actually used. * - * @internal Backwards compatability not guaranteed. - * - * @param callable|string $callback: A callable, global function, or a ::class attribute of an invokable class + * @param callable|class-string $callback : A callable, global function, or a ::class attribute of an invokable class * @param Container $container + * + * @return callable + * @internal Backwards compatability not guaranteed. */ - public static function wrapCallback($callback, Container $container) + public static function wrapCallback(callable|string $callback, Container $container): callable { if (is_string($callback) && ! is_callable($callback)) { $callback = function (&...$args) use ($container, $callback) { diff --git a/framework/core/src/Foundation/DispatchEventsTrait.php b/framework/core/src/Foundation/DispatchEventsTrait.php index 4445cab50..46917fdfd 100644 --- a/framework/core/src/Foundation/DispatchEventsTrait.php +++ b/framework/core/src/Foundation/DispatchEventsTrait.php @@ -10,22 +10,13 @@ namespace Flarum\Foundation; use Flarum\User\User; -use Illuminate\Contracts\Events\Dispatcher; trait DispatchEventsTrait { - /** - * @var Dispatcher - */ - protected $events; - /** * Dispatch all events for an entity. - * - * @param object $entity - * @param User $actor */ - public function dispatchEventsFor($entity, User $actor = null) + public function dispatchEventsFor($entity, User $actor = null): void { foreach ($entity->releaseEvents() as $event) { $event->actor = $actor; diff --git a/framework/core/src/Foundation/ErrorHandling/ExceptionHandler/ValidationExceptionHandler.php b/framework/core/src/Foundation/ErrorHandling/ExceptionHandler/ValidationExceptionHandler.php index ceec9bd31..779ca7c7b 100644 --- a/framework/core/src/Foundation/ErrorHandling/ExceptionHandler/ValidationExceptionHandler.php +++ b/framework/core/src/Foundation/ErrorHandling/ExceptionHandler/ValidationExceptionHandler.php @@ -14,7 +14,7 @@ use Flarum\Foundation\ValidationException; class ValidationExceptionHandler { - public function handle(ValidationException $e) + public function handle(ValidationException $e): HandledError { return (new HandledError( $e, diff --git a/framework/core/src/Foundation/ErrorHandling/HandledError.php b/framework/core/src/Foundation/ErrorHandling/HandledError.php index 026d1b13e..2c55cfb70 100644 --- a/framework/core/src/Foundation/ErrorHandling/HandledError.php +++ b/framework/core/src/Foundation/ErrorHandling/HandledError.php @@ -20,22 +20,18 @@ use Throwable; */ class HandledError { - private $error; - private $type; - private $statusCode; + private array $details = []; - private $details = []; - - public static function unknown(Throwable $error) + public static function unknown(Throwable $error): static { return new static($error, 'unknown', 500); } - public function __construct(Throwable $error, $type, $statusCode) - { - $this->error = $error; - $this->type = $type; - $this->statusCode = $statusCode; + public function __construct( + private readonly Throwable $error, + private readonly string $type, + private readonly int $statusCode + ) { } public function withDetails(array $details): self diff --git a/framework/core/src/Foundation/ErrorHandling/JsonApiFormatter.php b/framework/core/src/Foundation/ErrorHandling/JsonApiFormatter.php index a51b8a305..e6276c44a 100644 --- a/framework/core/src/Foundation/ErrorHandling/JsonApiFormatter.php +++ b/framework/core/src/Foundation/ErrorHandling/JsonApiFormatter.php @@ -21,11 +21,9 @@ use Tobscure\JsonApi\Document; */ class JsonApiFormatter implements HttpFormatter { - private $includeTrace; - - public function __construct($includeTrace = false) - { - $this->includeTrace = $includeTrace; + public function __construct( + private readonly bool $includeTrace = false + ) { } public function format(HandledError $error, Request $request): Response diff --git a/framework/core/src/Foundation/ErrorHandling/LogReporter.php b/framework/core/src/Foundation/ErrorHandling/LogReporter.php index d4cb0c97a..8cb11bdaf 100644 --- a/framework/core/src/Foundation/ErrorHandling/LogReporter.php +++ b/framework/core/src/Foundation/ErrorHandling/LogReporter.php @@ -17,17 +17,12 @@ use Throwable; */ class LogReporter implements Reporter { - /** - * @var LoggerInterface - */ - protected $logger; - - public function __construct(LoggerInterface $logger) - { - $this->logger = $logger; + public function __construct( + protected LoggerInterface $logger + ) { } - public function report(Throwable $error) + public function report(Throwable $error): void { $this->logger->error($error); } diff --git a/framework/core/src/Foundation/ErrorHandling/Registry.php b/framework/core/src/Foundation/ErrorHandling/Registry.php index ae0aada1c..d7a36f8b0 100644 --- a/framework/core/src/Foundation/ErrorHandling/Registry.php +++ b/framework/core/src/Foundation/ErrorHandling/Registry.php @@ -21,23 +21,19 @@ use Throwable; */ class Registry { - private $statusMap; - private $classMap; - private $handlerMap; - - public function __construct(array $statusMap, array $classMap, array $handlerMap) - { - $this->statusMap = $statusMap; - $this->classMap = $classMap; - $this->handlerMap = $handlerMap; + public function __construct( + private readonly array $statusMap, + private readonly array $classMap, + private readonly array $handlerMap + ) { } /** * Map exceptions to handled errors. * - * This can map internal ({@see \Flarum\Foundation\KnownError}) as well as + * This can map internal ({@see KnownError}) as well as * external exceptions (any classes inheriting from \Throwable) to instances - * of {@see \Flarum\Foundation\ErrorHandling\HandledError}. + * of {@see HandledError}. * * Even for unknown exceptions, a generic fallback will always be returned. * diff --git a/framework/core/src/Foundation/ErrorHandling/Reporter.php b/framework/core/src/Foundation/ErrorHandling/Reporter.php index ca3277cc9..591c6df70 100644 --- a/framework/core/src/Foundation/ErrorHandling/Reporter.php +++ b/framework/core/src/Foundation/ErrorHandling/Reporter.php @@ -19,5 +19,5 @@ interface Reporter * @param Throwable $error * @return void */ - public function report(Throwable $error); + public function report(Throwable $error): void; } diff --git a/framework/core/src/Foundation/ErrorHandling/ViewFormatter.php b/framework/core/src/Foundation/ErrorHandling/ViewFormatter.php index 3de260b9c..ad0b31b15 100644 --- a/framework/core/src/Foundation/ErrorHandling/ViewFormatter.php +++ b/framework/core/src/Foundation/ErrorHandling/ViewFormatter.php @@ -9,12 +9,12 @@ namespace Flarum\Foundation\ErrorHandling; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\View\Factory as ViewFactory; use Laminas\Diactoros\Response\HtmlResponse; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Symfony\Contracts\Translation\TranslatorInterface; /** * A formatter for turning caught exceptions into "pretty" HTML error pages. @@ -29,39 +29,25 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class ViewFormatter implements HttpFormatter { - /** - * @var ViewFactory - */ - protected $view; + const ERRORS_WITH_VIEWS = ['csrf_token_mismatch', 'not_found']; - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - public function __construct(ViewFactory $view, TranslatorInterface $translator, SettingsRepositoryInterface $settings) - { - $this->view = $view; - $this->translator = $translator; - $this->settings = $settings; + public function __construct( + protected ViewFactory $view, + protected TranslatorInterface $translator, + protected SettingsRepositoryInterface $settings + ) { } public function format(HandledError $error, Request $request): Response { - $view = $this->view->make($this->determineView($error)) + $view = $this->view + ->make($this->determineView($error)) ->with('error', $error->getException()) ->with('message', $this->getMessage($error)); return new HtmlResponse($view->render(), $error->getStatusCode()); } - const ERRORS_WITH_VIEWS = ['csrf_token_mismatch', 'not_found']; - private function determineView(HandledError $error): string { $type = $error->getType(); @@ -73,14 +59,14 @@ class ViewFormatter implements HttpFormatter } } - private function getMessage(HandledError $error) + private function getMessage(HandledError $error): string { return $this->getTranslationIfExists($error->getType()) ?? $this->getTranslationIfExists('unknown') ?? 'An error occurred while trying to load this page.'; } - private function getTranslationIfExists(string $errorType) + private function getTranslationIfExists(string $errorType): ?string { $key = "core.views.error.$errorType"; $translation = $this->translator->trans($key, ['forum' => $this->settings->get('forum_title')]); diff --git a/framework/core/src/Foundation/ErrorServiceProvider.php b/framework/core/src/Foundation/ErrorServiceProvider.php index 7e9d63d41..8a27d1941 100644 --- a/framework/core/src/Foundation/ErrorServiceProvider.php +++ b/framework/core/src/Foundation/ErrorServiceProvider.php @@ -17,7 +17,7 @@ use Tobscure\JsonApi\Exception\InvalidParameterException; class ErrorServiceProvider extends AbstractServiceProvider { - public function register() + public function register(): void { $this->container->singleton('flarum.error.statuses', function () { return [ diff --git a/framework/core/src/Foundation/EventGeneratorTrait.php b/framework/core/src/Foundation/EventGeneratorTrait.php index c73f0601e..19cdcb873 100644 --- a/framework/core/src/Foundation/EventGeneratorTrait.php +++ b/framework/core/src/Foundation/EventGeneratorTrait.php @@ -11,27 +11,20 @@ namespace Flarum\Foundation; trait EventGeneratorTrait { - /** - * @var array - */ - protected $pendingEvents = []; + protected array $pendingEvents = []; /** * Raise a new event. - * - * @param mixed $event */ - public function raise($event) + public function raise($event): void { $this->pendingEvents[] = $event; } /** * Return and reset all pending events. - * - * @return array */ - public function releaseEvents() + public function releaseEvents(): array { $events = $this->pendingEvents; diff --git a/framework/core/src/Foundation/InstalledApp.php b/framework/core/src/Foundation/InstalledApp.php index e087aa3ee..7f04673ad 100644 --- a/framework/core/src/Foundation/InstalledApp.php +++ b/framework/core/src/Foundation/InstalledApp.php @@ -18,34 +18,22 @@ use Laminas\Stratigility\MiddlewarePipe; use Middlewares\BasePath; use Middlewares\BasePathRouter; use Middlewares\RequestHandler; +use Psr\Http\Server\RequestHandlerInterface; class InstalledApp implements AppInterface { - /** - * @var Container - */ - protected $container; - - /** - * @var Config - */ - protected $config; - - public function __construct(Container $container, Config $config) - { - $this->container = $container; - $this->config = $config; + public function __construct( + protected Container $container, + protected Config $config + ) { } - public function getContainer() + public function getContainer(): Container { return $this->container; } - /** - * @return \Psr\Http\Server\RequestHandlerInterface - */ - public function getRequestHandler() + public function getRequestHandler(): RequestHandlerInterface { if ($this->config->inMaintenanceMode()) { return $this->container->make('flarum.maintenance.handler'); @@ -78,10 +66,7 @@ class InstalledApp implements AppInterface return $version !== Application::VERSION; } - /** - * @return \Psr\Http\Server\RequestHandlerInterface - */ - protected function getUpdaterHandler() + protected function getUpdaterHandler(): RequestHandlerInterface|MiddlewarePipe { $pipe = new MiddlewarePipe; $pipe->pipe(new BasePath($this->basePath())); @@ -103,10 +88,7 @@ class InstalledApp implements AppInterface return '/'.($this->config['paths'][$pathName] ?? $pathName); } - /** - * @return \Symfony\Component\Console\Command\Command[] - */ - public function getConsoleCommands() + public function getConsoleCommands(): array { return array_map(function ($command) { $command = $this->container->make($command); diff --git a/framework/core/src/Foundation/InstalledSite.php b/framework/core/src/Foundation/InstalledSite.php index 6ccc248f1..37777dae0 100644 --- a/framework/core/src/Foundation/InstalledSite.php +++ b/framework/core/src/Foundation/InstalledSite.php @@ -15,6 +15,7 @@ use Flarum\Bus\BusServiceProvider; use Flarum\Console\ConsoleServiceProvider; use Flarum\Database\DatabaseServiceProvider; use Flarum\Discussion\DiscussionServiceProvider; +use Flarum\Extend\ExtenderInterface; use Flarum\Extension\ExtensionServiceProvider; use Flarum\Filesystem\FilesystemServiceProvider; use Flarum\Filter\FilterServiceProvider; @@ -51,24 +52,14 @@ use Psr\Log\LoggerInterface; class InstalledSite implements SiteInterface { /** - * @var Paths + * @var ExtenderInterface[] */ - protected $paths; + protected array $extenders = []; - /** - * @var Config - */ - protected $config; - - /** - * @var \Flarum\Extend\ExtenderInterface[] - */ - protected $extenders = []; - - public function __construct(Paths $paths, Config $config) - { - $this->paths = $paths; - $this->config = $config; + public function __construct( + protected Paths $paths, + protected Config $config + ) { } /** @@ -85,7 +76,7 @@ class InstalledSite implements SiteInterface } /** - * @param \Flarum\Extend\ExtenderInterface[] $extenders + * @param ExtenderInterface[] $extenders * @return InstalledSite */ public function extendWith(array $extenders): self @@ -153,10 +144,7 @@ class InstalledSite implements SiteInterface return $container; } - /** - * @return ConfigRepository - */ - protected function getIlluminateConfig() + protected function getIlluminateConfig(): ConfigRepository { return new ConfigRepository([ 'app' => [ @@ -174,7 +162,7 @@ class InstalledSite implements SiteInterface ]); } - protected function registerLogger(Container $container) + protected function registerLogger(Container $container): void { $logPath = $this->paths->storage.'/logs/flarum.log'; $logLevel = $this->config->inDebugMode() ? Logger::DEBUG : Logger::INFO; @@ -185,7 +173,7 @@ class InstalledSite implements SiteInterface $container->alias('log', LoggerInterface::class); } - protected function registerCache(Container $container) + protected function registerCache(Container $container): void { $container->singleton('cache.store', function ($container) { return new CacheRepository($container->make('cache.filestore')); diff --git a/framework/core/src/Foundation/Paths.php b/framework/core/src/Foundation/Paths.php index a873123f8..c40198397 100644 --- a/framework/core/src/Foundation/Paths.php +++ b/framework/core/src/Foundation/Paths.php @@ -19,7 +19,7 @@ use InvalidArgumentException; */ class Paths { - private $paths; + private array $paths; public function __construct(array $paths) { diff --git a/framework/core/src/Foundation/Site.php b/framework/core/src/Foundation/Site.php index 973214212..c127587eb 100644 --- a/framework/core/src/Foundation/Site.php +++ b/framework/core/src/Foundation/Site.php @@ -14,11 +14,7 @@ use RuntimeException; class Site { - /** - * @param array $paths - * @return SiteInterface - */ - public static function fromPaths(array $paths) + public static function fromPaths(array $paths): SiteInterface { $paths = new Paths($paths); @@ -38,7 +34,7 @@ class Site )->extendWith(static::loadExtenders($paths->base)); } - protected static function hasConfigFile($basePath) + protected static function hasConfigFile($basePath): bool { return file_exists("$basePath/config.php"); } diff --git a/framework/core/src/Foundation/SiteInterface.php b/framework/core/src/Foundation/SiteInterface.php index 5c1171994..c48b17521 100644 --- a/framework/core/src/Foundation/SiteInterface.php +++ b/framework/core/src/Foundation/SiteInterface.php @@ -13,8 +13,6 @@ interface SiteInterface { /** * Create and boot a Flarum application instance. - * - * @return AppInterface */ public function bootApp(): AppInterface; } diff --git a/framework/core/src/Foundation/UninstalledSite.php b/framework/core/src/Foundation/UninstalledSite.php index bf8855dcc..e933b8d04 100644 --- a/framework/core/src/Foundation/UninstalledSite.php +++ b/framework/core/src/Foundation/UninstalledSite.php @@ -30,26 +30,14 @@ use Psr\Log\LoggerInterface; class UninstalledSite implements SiteInterface { - /** - * @var Paths - */ - protected $paths; - - /** - * @var string - */ - private $baseUrl; - - public function __construct(Paths $paths, string $baseUrl) - { - $this->paths = $paths; - $this->baseUrl = $baseUrl; + public function __construct( + protected Paths $paths, + private readonly string $baseUrl + ) { } /** * Create and boot a Flarum application instance. - * - * @return AppInterface */ public function bootApp(): AppInterface { @@ -104,10 +92,7 @@ class UninstalledSite implements SiteInterface return $container; } - /** - * @return ConfigRepository - */ - protected function getIlluminateConfig() + protected function getIlluminateConfig(): ConfigRepository { return new ConfigRepository([ 'session' => [ @@ -121,7 +106,7 @@ class UninstalledSite implements SiteInterface ]); } - protected function registerLogger(Container $container) + protected function registerLogger(Container $container): void { $logPath = $this->paths->storage.'/logs/flarum-installer.log'; $handler = new StreamHandler($logPath, Logger::DEBUG); diff --git a/framework/core/src/Foundation/ValidationException.php b/framework/core/src/Foundation/ValidationException.php index 0f74c436d..d356c0913 100644 --- a/framework/core/src/Foundation/ValidationException.php +++ b/framework/core/src/Foundation/ValidationException.php @@ -13,25 +13,21 @@ use Exception; class ValidationException extends Exception { - protected $attributes; - protected $relationships; - - public function __construct(array $attributes, array $relationships = []) - { - $this->attributes = $attributes; - $this->relationships = $relationships; - + public function __construct( + protected array $attributes, + protected array $relationships = [] + ) { $messages = [implode("\n", $attributes), implode("\n", $relationships)]; parent::__construct(implode("\n", $messages)); } - public function getAttributes() + public function getAttributes(): array { return $this->attributes; } - public function getRelationships() + public function getRelationships(): array { return $this->relationships; } diff --git a/framework/core/src/Frontend/AddLocaleAssets.php b/framework/core/src/Frontend/AddLocaleAssets.php index 8dc089db4..384f467cb 100644 --- a/framework/core/src/Frontend/AddLocaleAssets.php +++ b/framework/core/src/Frontend/AddLocaleAssets.php @@ -17,20 +17,12 @@ use Flarum\Locale\LocaleManager; */ class AddLocaleAssets { - /** - * @var LocaleManager - */ - protected $locales; - - /** - * @param LocaleManager $locales - */ - public function __construct(LocaleManager $locales) - { - $this->locales = $locales; + public function __construct( + protected LocaleManager $locales + ) { } - public function to(Assets $assets) + public function to(Assets $assets): void { $assets->localeJs(function (SourceCollector $sources, string $locale) { foreach ($this->locales->getJsFiles($locale) as $file) { diff --git a/framework/core/src/Frontend/AddTranslations.php b/framework/core/src/Frontend/AddTranslations.php index 139724e1d..52b48f947 100644 --- a/framework/core/src/Frontend/AddTranslations.php +++ b/framework/core/src/Frontend/AddTranslations.php @@ -9,6 +9,7 @@ namespace Flarum\Frontend; +use Closure; use Flarum\Frontend\Compiler\Source\SourceCollector; use Flarum\Locale\LocaleManager; use Illuminate\Support\Arr; @@ -18,23 +19,13 @@ use Illuminate\Support\Arr; */ class AddTranslations { - /** - * @var LocaleManager - */ - protected $locales; - - /** - * @var callable - */ - protected $filter; - - public function __construct(LocaleManager $locales, callable $filter = null) - { - $this->locales = $locales; - $this->filter = $filter; + public function __construct( + protected LocaleManager $locales, + protected ?Closure $filter = null + ) { } - public function forFrontend(string $name) + public function forFrontend(string $name): static { $this->filter = function (string $id) use ($name) { return preg_match('/^.+(?:\.|::)(?:'.$name.'|lib)\./', $id); @@ -43,7 +34,7 @@ class AddTranslations return $this; } - public function to(Assets $assets) + public function to(Assets $assets): void { $assets->localeJs(function (SourceCollector $sources, string $locale) { $sources->addString(function () use ($locale) { @@ -54,7 +45,7 @@ class AddTranslations }); } - private function getTranslations(string $locale) + private function getTranslations(string $locale): array { $catalogue = $this->locales->getTranslator()->getCatalogue($locale); $translations = $catalogue->all('messages'); diff --git a/framework/core/src/Frontend/Assets.php b/framework/core/src/Frontend/Assets.php index 6750b7a6c..9a6abf6b3 100644 --- a/framework/core/src/Frontend/Assets.php +++ b/framework/core/src/Frontend/Assets.php @@ -25,91 +25,59 @@ class Assets /** * @var array */ - public $sources = [ + public array $sources = [ 'js' => [], 'css' => [], 'localeJs' => [], 'localeCss' => [] ]; - /** - * @var string - */ - protected $name; + protected array $lessImportOverrides = []; + protected array $fileSourceOverrides = []; - /** - * @var Cloud - */ - protected $assetsDir; - - /** - * @var string - */ - protected $cacheDir; - - /** - * @var array - */ - protected $lessImportDirs; - - /** - * @var array - */ - protected $lessImportOverrides = []; - - /** - * @var array - */ - protected $fileSourceOverrides = []; - - /** - * @var array - */ - protected $customFunctions = []; - - public function __construct(string $name, Cloud $assetsDir, string $cacheDir = null, array $lessImportDirs = null, array $customFunctions = []) - { - $this->name = $name; - $this->assetsDir = $assetsDir; - $this->cacheDir = $cacheDir; - $this->lessImportDirs = $lessImportDirs; - $this->customFunctions = $customFunctions; + public function __construct( + protected string $name, + protected Cloud $assetsDir, + protected ?string $cacheDir = null, + protected ?array $lessImportDirs = null, + protected array $customFunctions = [] + ) { } - public function js($sources) + public function js($sources): static { $this->addSources('js', $sources); return $this; } - public function css($callback) + public function css($callback): static { $this->addSources('css', $callback); return $this; } - public function localeJs($callback) + public function localeJs($callback): static { $this->addSources('localeJs', $callback); return $this; } - public function localeCss($callback) + public function localeCss($callback): static { $this->addSources('localeCss', $callback); return $this; } - private function addSources($type, $callback) + private function addSources($type, $callback): void { $this->sources[$type][] = $callback; } - private function populate(CompilerInterface $compiler, string $type, string $locale = null) + private function populate(CompilerInterface $compiler, string $type, string $locale = null): void { $compiler->addSources(function (SourceCollector $sources) use ($type, $locale) { foreach ($this->sources[$type] as $callback) { diff --git a/framework/core/src/Frontend/Compiler/CompilerInterface.php b/framework/core/src/Frontend/Compiler/CompilerInterface.php index dd5dcf562..6750c9233 100644 --- a/framework/core/src/Frontend/Compiler/CompilerInterface.php +++ b/framework/core/src/Frontend/Compiler/CompilerInterface.php @@ -13,13 +13,13 @@ interface CompilerInterface { public function getFilename(): string; - public function setFilename(string $filename); + public function setFilename(string $filename): void; - public function addSources(callable $callback); + public function addSources(callable $callback): void; - public function commit(bool $force = false); + public function commit(bool $force = false): void; public function getUrl(): ?string; - public function flush(); + public function flush(): void; } diff --git a/framework/core/src/Frontend/Compiler/FileVersioner.php b/framework/core/src/Frontend/Compiler/FileVersioner.php index 7c03df2c2..4260ff339 100644 --- a/framework/core/src/Frontend/Compiler/FileVersioner.php +++ b/framework/core/src/Frontend/Compiler/FileVersioner.php @@ -14,18 +14,14 @@ use Illuminate\Support\Arr; class FileVersioner implements VersionerInterface { - /** - * @var Filesystem - */ - protected $filesystem; const REV_MANIFEST = 'rev-manifest.json'; - public function __construct(Filesystem $filesystem) - { - $this->filesystem = $filesystem; + public function __construct( + protected Filesystem $filesystem + ) { } - public function putRevision(string $file, ?string $revision) + public function putRevision(string $file, ?string $revision): void { if ($this->filesystem->exists(static::REV_MANIFEST)) { $manifest = json_decode($this->filesystem->get(static::REV_MANIFEST), true); diff --git a/framework/core/src/Frontend/Compiler/JsCompiler.php b/framework/core/src/Frontend/Compiler/JsCompiler.php index c9c4510a7..7eb789b26 100644 --- a/framework/core/src/Frontend/Compiler/JsCompiler.php +++ b/framework/core/src/Frontend/Compiler/JsCompiler.php @@ -65,10 +65,7 @@ class JsCompiler extends RevisionCompiler return preg_replace('~//# sourceMappingURL.*$~m', '', $string)."\n"; } - /** - * {@inheritdoc} - */ - protected function delete(string $file) + protected function delete(string $file): void { parent::delete($file); diff --git a/framework/core/src/Frontend/Compiler/LessCompiler.php b/framework/core/src/Frontend/Compiler/LessCompiler.php index 3825215c7..381fc2b5e 100644 --- a/framework/core/src/Frontend/Compiler/LessCompiler.php +++ b/framework/core/src/Frontend/Compiler/LessCompiler.php @@ -19,37 +19,18 @@ use Less_Parser; */ class LessCompiler extends RevisionCompiler { - /** - * @var string - */ - protected $cacheDir; - - /** - * @var array - */ - protected $importDirs = []; - - /** - * @var array - */ - protected $customFunctions = []; - - /** - * @var Collection|null - */ - protected $lessImportOverrides; - - /** - * @var Collection|null - */ - protected $fileSourceOverrides; + protected string $cacheDir; + protected array $importDirs = []; + protected array $customFunctions = []; + protected ?Collection $lessImportOverrides = null; + protected ?Collection $fileSourceOverrides = null; public function getCacheDir(): string { return $this->cacheDir; } - public function setCacheDir(string $cacheDir) + public function setCacheDir(string $cacheDir): void { $this->cacheDir = $cacheDir; } @@ -59,22 +40,22 @@ class LessCompiler extends RevisionCompiler return $this->importDirs; } - public function setImportDirs(array $importDirs) + public function setImportDirs(array $importDirs): void { $this->importDirs = $importDirs; } - public function setLessImportOverrides(array $lessImportOverrides) + public function setLessImportOverrides(array $lessImportOverrides): void { $this->lessImportOverrides = new Collection($lessImportOverrides); } - public function setFileSourceOverrides(array $fileSourceOverrides) + public function setFileSourceOverrides(array $fileSourceOverrides): void { $this->fileSourceOverrides = new Collection($fileSourceOverrides); } - public function setCustomFunctions(array $customFunctions) + public function setCustomFunctions(array $customFunctions): void { $this->customFunctions = $customFunctions; } diff --git a/framework/core/src/Frontend/Compiler/RevisionCompiler.php b/framework/core/src/Frontend/Compiler/RevisionCompiler.php index adf2e9305..e1eae7116 100644 --- a/framework/core/src/Frontend/Compiler/RevisionCompiler.php +++ b/framework/core/src/Frontend/Compiler/RevisionCompiler.php @@ -57,12 +57,12 @@ class RevisionCompiler implements CompilerInterface return $this->filename; } - public function setFilename(string $filename) + public function setFilename(string $filename): void { $this->filename = $filename; } - public function commit(bool $force = false) + public function commit(bool $force = false): void { $sources = $this->getSources(); @@ -84,7 +84,7 @@ class RevisionCompiler implements CompilerInterface } } - public function addSources(callable $callback) + public function addSources(callable $callback): void { $this->sourcesCallbacks[] = $callback; } @@ -182,7 +182,7 @@ class RevisionCompiler implements CompilerInterface return null; } - public function flush() + public function flush(): void { if ($this->versioner->getRevision($this->filename) !== null) { $this->delete($this->filename); @@ -191,7 +191,7 @@ class RevisionCompiler implements CompilerInterface } } - protected function delete(string $file) + protected function delete(string $file): void { if ($this->assetsDir->exists($file)) { $this->assetsDir->delete($file); diff --git a/framework/core/src/Frontend/Compiler/Source/FileSource.php b/framework/core/src/Frontend/Compiler/Source/FileSource.php index 6fcd9b642..511e97242 100644 --- a/framework/core/src/Frontend/Compiler/Source/FileSource.php +++ b/framework/core/src/Frontend/Compiler/Source/FileSource.php @@ -16,48 +16,25 @@ use InvalidArgumentException; */ class FileSource implements SourceInterface { - /** - * @var string - */ - protected $path; - - /** - * @var string - */ - protected $extensionId; - - /** - * @param string $path - */ - public function __construct(string $path, ?string $extensionId = null) - { + public function __construct( + protected string $path, + protected ?string $extensionId = null + ) { if (! file_exists($path)) { throw new InvalidArgumentException("File not found at path: $path"); } - - $this->path = $path; - $this->extensionId = $extensionId; } - /** - * @return string - */ public function getContent(): string { return file_get_contents($this->path); } - /** - * @return mixed - */ - public function getCacheDifferentiator() + public function getCacheDifferentiator(): array { return [$this->path, filemtime($this->path)]; } - /** - * @return string - */ public function getPath(): string { return $this->path; diff --git a/framework/core/src/Frontend/Compiler/Source/SourceCollector.php b/framework/core/src/Frontend/Compiler/Source/SourceCollector.php index 452d78e87..88baa6983 100644 --- a/framework/core/src/Frontend/Compiler/Source/SourceCollector.php +++ b/framework/core/src/Frontend/Compiler/Source/SourceCollector.php @@ -9,6 +9,8 @@ namespace Flarum\Frontend\Compiler\Source; +use Closure; + /** * @internal */ @@ -17,24 +19,16 @@ class SourceCollector /** * @var SourceInterface[] */ - protected $sources = []; + protected array $sources = []; - /** - * @param string $file - * @return $this - */ - public function addFile(string $file, string $extensionId = null) + public function addFile(string $file, string $extensionId = null): static { $this->sources[] = new FileSource($file, $extensionId); return $this; } - /** - * @param callable $callback - * @return $this - */ - public function addString(callable $callback) + public function addString(Closure $callback): static { $this->sources[] = new StringSource($callback); @@ -44,7 +38,7 @@ class SourceCollector /** * @return SourceInterface[] */ - public function getSources() + public function getSources(): array { return $this->sources; } diff --git a/framework/core/src/Frontend/Compiler/Source/SourceInterface.php b/framework/core/src/Frontend/Compiler/Source/SourceInterface.php index 71f829c2b..0ccf5d648 100644 --- a/framework/core/src/Frontend/Compiler/Source/SourceInterface.php +++ b/framework/core/src/Frontend/Compiler/Source/SourceInterface.php @@ -11,13 +11,7 @@ namespace Flarum\Frontend\Compiler\Source; interface SourceInterface { - /** - * @return string - */ public function getContent(): string; - /** - * @return mixed - */ - public function getCacheDifferentiator(); + public function getCacheDifferentiator(): mixed; } diff --git a/framework/core/src/Frontend/Compiler/Source/StringSource.php b/framework/core/src/Frontend/Compiler/Source/StringSource.php index cd6cc1988..9c708cc65 100644 --- a/framework/core/src/Frontend/Compiler/Source/StringSource.php +++ b/framework/core/src/Frontend/Compiler/Source/StringSource.php @@ -9,42 +9,26 @@ namespace Flarum\Frontend\Compiler\Source; +use Closure; + /** * @internal */ class StringSource implements SourceInterface { - /** - * @var callable - */ - protected $callback; + private ?string $content = null; - private $content; - - /** - * @param callable $callback - */ - public function __construct(callable $callback) - { - $this->callback = $callback; + public function __construct( + protected Closure $callback + ) { } - /** - * @return string - */ public function getContent(): string { - if (is_null($this->content)) { - $this->content = call_user_func($this->callback); - } - - return $this->content; + return $this->content ??= call_user_func($this->callback); } - /** - * @return mixed - */ - public function getCacheDifferentiator() + public function getCacheDifferentiator(): string { return $this->getContent(); } diff --git a/framework/core/src/Frontend/Content/Assets.php b/framework/core/src/Frontend/Content/Assets.php index b5f852415..493b31de0 100644 --- a/framework/core/src/Frontend/Content/Assets.php +++ b/framework/core/src/Frontend/Content/Assets.php @@ -10,6 +10,7 @@ namespace Flarum\Frontend\Content; use Flarum\Foundation\Config; +use Flarum\Frontend\Assets as FrontendAssets; use Flarum\Frontend\Compiler\CompilerInterface; use Flarum\Frontend\Document; use Illuminate\Contracts\Container\Container; @@ -18,42 +19,27 @@ use Psr\Http\Message\ServerRequestInterface as Request; class Assets { - /** - * @var Container - */ - protected $container; + protected FrontendAssets $assets; - /** - * @var Config - */ - protected $config; - - /** - * @var \Flarum\Frontend\Assets - */ - protected $assets; - - public function __construct(Container $container, Config $config) - { - $this->container = $container; - $this->config = $config; + public function __construct( + protected Container $container, + protected Config $config + ) { } /** * Sets the frontend to generate assets for. * - * @param string $name frontend name - * @return $this * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function forFrontend(string $name): Assets + public function forFrontend(string $name): self { $this->assets = $this->container->make('flarum.assets.'.$name); return $this; } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): void { $locale = $request->getAttribute('locale'); @@ -69,7 +55,6 @@ class Assets /** * Assembles JS and CSS compilers to be used to generate frontend assets. * - * @param string|null $locale * @return array[] */ protected function assembleCompilers(?string $locale): array @@ -82,10 +67,6 @@ class Assets /** * Adds URLs of frontend JS and CSS to the {@link Document} class. - * - * @param Document $document - * @param array $compilers - * @return void */ protected function addAssetsToDocument(Document $document, array $compilers): void { @@ -96,11 +77,10 @@ class Assets /** * Force compilation of assets when in debug mode. * - * @param array $compilers + * @param CompilerInterface[] $compilers */ protected function forceCommit(array $compilers): void { - /** @var CompilerInterface $compiler */ foreach ($compilers as $compiler) { $compiler->commit(true); } diff --git a/framework/core/src/Frontend/Content/CorePayload.php b/framework/core/src/Frontend/Content/CorePayload.php index 5f02964fe..3bba17493 100644 --- a/framework/core/src/Frontend/Content/CorePayload.php +++ b/framework/core/src/Frontend/Content/CorePayload.php @@ -16,20 +16,12 @@ use Psr\Http\Message\ServerRequestInterface as Request; class CorePayload { - /** - * @var LocaleManager - */ - private $locales; - - /** - * @param LocaleManager $locales - */ - public function __construct(LocaleManager $locales) - { - $this->locales = $locales; + public function __construct( + private readonly LocaleManager $locales + ) { } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): void { $document->payload = array_merge( $document->payload, @@ -37,7 +29,7 @@ class CorePayload ); } - private function buildPayload(Document $document, Request $request) + private function buildPayload(Document $document, Request $request): array { $data = $this->getDataFromApiDocument($document->getForumApiDocument()); diff --git a/framework/core/src/Frontend/Content/Meta.php b/framework/core/src/Frontend/Content/Meta.php index 2d0c6dd0e..fd422d0e6 100644 --- a/framework/core/src/Frontend/Content/Meta.php +++ b/framework/core/src/Frontend/Content/Meta.php @@ -16,20 +16,12 @@ use Psr\Http\Message\ServerRequestInterface as Request; class Meta { - /** - * @var LocaleManager - */ - private $locales; - - /** - * @param LocaleManager $locales - */ - public function __construct(LocaleManager $locales) - { - $this->locales = $locales; + public function __construct( + private readonly LocaleManager $locales + ) { } - public function __invoke(Document $document, Request $request) + public function __invoke(Document $document, Request $request): void { $document->language = $this->locales->getLocale(); $document->direction = 'ltr'; @@ -38,20 +30,18 @@ class Meta $document->head = array_merge($document->head, $this->buildHead($document)); } - private function buildMeta(Document $document) + private function buildMeta(Document $document): array { $forumApiDocument = $document->getForumApiDocument(); - $meta = [ + return [ 'viewport' => 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1', 'description' => Arr::get($forumApiDocument, 'data.attributes.description'), 'theme-color' => Arr::get($forumApiDocument, 'data.attributes.themePrimaryColor') ]; - - return $meta; } - private function buildHead(Document $document) + private function buildHead(Document $document): array { $head = []; diff --git a/framework/core/src/Frontend/Controller.php b/framework/core/src/Frontend/Controller.php index 9e1601c44..7a2b93406 100644 --- a/framework/core/src/Frontend/Controller.php +++ b/framework/core/src/Frontend/Controller.php @@ -16,14 +16,9 @@ use Psr\Http\Server\RequestHandlerInterface; class Controller implements RequestHandlerInterface { - /** - * @var Frontend - */ - protected $frontend; - - public function __construct(Frontend $frontend) - { - $this->frontend = $frontend; + public function __construct( + protected Frontend $frontend + ) { } public function handle(Request $request): Response diff --git a/framework/core/src/Frontend/Document.php b/framework/core/src/Frontend/Document.php index 4b947059c..157dfeea8 100644 --- a/framework/core/src/Frontend/Document.php +++ b/framework/core/src/Frontend/Document.php @@ -23,66 +23,48 @@ class Document implements Renderable { /** * The title of the document, displayed in the tag. - * - * @var null|string */ - public $title; + public ?string $title = null; /** * The language of the document, displayed as the value of the attribute `lang` in the <html> tag. - * - * @var null|string */ - public $language; + public ?string $language = null; /** * The text direction of the document, displayed as the value of the attribute `dir` in the <html> tag. - * - * @var null|string */ - public $direction; + public ?string $direction = null; /** * The name of the frontend app view to display. - * - * @var string */ - public $appView = 'flarum::frontend.app'; + public string $appView = 'flarum::frontend.app'; /** * The name of the frontend layout view to display. - * - * @var string */ - public $layoutView; + public string $layoutView; /** * The name of the frontend content view to display. - * - * @var string */ - public $contentView = 'flarum::frontend.content'; + public string $contentView = 'flarum::frontend.content'; /** * The SEO content of the page, displayed within the layout in <noscript> tags. - * - * @var string|Renderable */ - public $content; + public string|Renderable|null $content = null; /** * Other variables to preload into the Flarum JS. - * - * @var array */ - public $payload = []; + public array $payload = []; /** * An array of meta tags to append to the page's <head>. - * - * @var array */ - public $meta = []; + public array $meta = []; /** * The canonical URL for this page. @@ -90,56 +72,42 @@ class Document implements Renderable * This will signal to search engines what URL should be used for this * content, if it can be found under multiple addresses. This is an * important tool to tackle duplicate content. - * - * @var null|string */ - public $canonicalUrl; + public ?string $canonicalUrl = null; /** * Which page of content are we on? * * This is used to build prev/next meta links for SEO. - * - * @var null|int */ - public $page; + public ?int $page = null; /** * Is there a next page? * * This is used with $page to build next meta links for SEO. - * - * @var null|bool */ - public $hasNextPage; + public ?bool $hasNextPage = null; /** * An array of strings to append to the page's <head>. - * - * @var array */ - public $head = []; + public array $head = []; /** * An array of strings to prepend before the page's </body>. - * - * @var array */ - public $foot = []; + public array $foot = []; /** * An array of JavaScript URLs to load. - * - * @var array */ - public $js = []; + public array $js = []; /** * An array of CSS URLs to load. - * - * @var array */ - public $css = []; + public array $css = []; /** * An array of preloaded assets. @@ -161,33 +129,16 @@ class Document implements Renderable * * @var array */ - public $preloads = []; + public array $preloads = []; - /** - * @var Factory - */ - protected $view; - - /** - * @var array - */ - protected $forumApiDocument; - - /** - * @var Request - */ - protected $request; - - public function __construct(Factory $view, array $forumApiDocument, Request $request) - { - $this->view = $view; - $this->forumApiDocument = $forumApiDocument; - $this->request = $request; + public function __construct( + protected Factory $view, + protected array $forumApiDocument, + protected Request $request, + protected TitleDriverInterface $titleDriver + ) { } - /** - * @return string - */ public function render(): string { $this->view->share('forum', Arr::get($this->forumApiDocument, 'data.attributes')); @@ -195,9 +146,6 @@ class Document implements Renderable return $this->makeView()->render(); } - /** - * @return View - */ protected function makeView(): View { return $this->view->make($this->appView)->with([ @@ -212,13 +160,9 @@ class Document implements Renderable ]); } - /** - * @return string - */ protected function makeTitle(): string { - // @todo v2.0 inject as dependency instead - return resolve(TitleDriverInterface::class)->makeTitle($this, $this->request, $this->forumApiDocument); + return $this->titleDriver->makeTitle($this, $this->request, $this->forumApiDocument); } protected function makeLayout(): ?View @@ -230,9 +174,6 @@ class Document implements Renderable return null; } - /** - * @return View - */ protected function makeContent(): View { return $this->view->make($this->contentView)->with('content', $this->content); @@ -251,9 +192,6 @@ class Document implements Renderable }, $this->preloads); } - /** - * @return string - */ protected function makeHead(): string { $head = array_map(function ($url) { @@ -282,9 +220,6 @@ class Document implements Renderable return implode("\n", array_merge($head, $this->head)); } - /** - * @return string - */ protected function makeJs(): string { return implode("\n", array_map(function ($url) { @@ -292,31 +227,22 @@ class Document implements Renderable }, $this->js)); } - /** - * @return string - */ protected function makeFoot(): string { return implode("\n", $this->foot); } - /** - * @return array - */ public function getForumApiDocument(): array { return $this->forumApiDocument; } - /** - * @param array $forumApiDocument - */ - public function setForumApiDocument(array $forumApiDocument) + public function setForumApiDocument(array $forumApiDocument): void { $this->forumApiDocument = $forumApiDocument; } - public static function setPageParam(string $url, ?int $page) + public static function setPageParam(string $url, ?int $page): string { if (! $page || $page === 1) { return self::setQueryParam($url, 'page', null); @@ -328,7 +254,7 @@ class Document implements Renderable /** * Set or override a query param on a string URL to a particular value. */ - protected static function setQueryParam(string $url, string $key, ?string $value) + protected static function setQueryParam(string $url, string $key, ?string $value): string { if (filter_var($url, FILTER_VALIDATE_URL)) { $urlParts = parse_url($url); diff --git a/framework/core/src/Frontend/Driver/BasicTitleDriver.php b/framework/core/src/Frontend/Driver/BasicTitleDriver.php index 36929602e..3d003b7fd 100644 --- a/framework/core/src/Frontend/Driver/BasicTitleDriver.php +++ b/framework/core/src/Frontend/Driver/BasicTitleDriver.php @@ -10,20 +10,15 @@ namespace Flarum\Frontend\Driver; use Flarum\Frontend\Document; +use Flarum\Locale\TranslatorInterface; use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; -use Symfony\Contracts\Translation\TranslatorInterface; class BasicTitleDriver implements TitleDriverInterface { - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; + public function __construct( + protected TranslatorInterface $translator + ) { } public function makeTitle(Document $document, ServerRequestInterface $request, array $forumApiDocument): string diff --git a/framework/core/src/Frontend/Frontend.php b/framework/core/src/Frontend/Frontend.php index 05a4e5405..8fa755f50 100644 --- a/framework/core/src/Frontend/Frontend.php +++ b/framework/core/src/Frontend/Frontend.php @@ -10,37 +10,26 @@ namespace Flarum\Frontend; use Flarum\Api\Client; +use Flarum\Frontend\Driver\TitleDriverInterface; use Illuminate\Contracts\View\Factory; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; class Frontend { - /** - * @var Factory - */ - protected $view; - - /** - * @var Client - */ - protected $api; - /** * @var callable[] */ - protected $content = []; + protected array $content = []; - public function __construct(Factory $view, Client $api) - { - $this->view = $view; - $this->api = $api; + public function __construct( + protected Factory $view, + protected Client $api, + protected TitleDriverInterface $titleDriver + ) { } - /** - * @param callable $content - */ - public function content(callable $content) + public function content(callable $content): void { $this->content[] = $content; } @@ -49,14 +38,14 @@ class Frontend { $forumDocument = $this->getForumDocument($request); - $document = new Document($this->view, $forumDocument, $request); + $document = new Document($this->view, $forumDocument, $request, $this->titleDriver); $this->populate($document, $request); return $document; } - protected function populate(Document $document, Request $request) + protected function populate(Document $document, Request $request): void { foreach ($this->content as $content) { $content($document, $request); diff --git a/framework/core/src/Frontend/FrontendServiceProvider.php b/framework/core/src/Frontend/FrontendServiceProvider.php index bcb5a11bd..4f51d3441 100644 --- a/framework/core/src/Frontend/FrontendServiceProvider.php +++ b/framework/core/src/Frontend/FrontendServiceProvider.php @@ -22,7 +22,7 @@ use Illuminate\Contracts\View\Factory as ViewFactory; class FrontendServiceProvider extends AbstractServiceProvider { - public function register() + public function register(): void { $this->container->singleton('flarum.assets.factory', function (Container $container) { return function (string $name) use ($container) { @@ -165,10 +165,7 @@ class FrontendServiceProvider extends AbstractServiceProvider ); } - /** - * {@inheritdoc} - */ - public function boot(Container $container, ViewFactory $views) + public function boot(Container $container, ViewFactory $views): void { $this->loadViewsFrom(__DIR__.'/../../views', 'flarum'); @@ -179,7 +176,7 @@ class FrontendServiceProvider extends AbstractServiceProvider ]); } - public function addBaseCss(SourceCollector $sources) + public function addBaseCss(SourceCollector $sources): void { $sources->addFile(__DIR__.'/../../less/common/variables.less'); $sources->addFile(__DIR__.'/../../less/common/mixins.less'); @@ -187,7 +184,7 @@ class FrontendServiceProvider extends AbstractServiceProvider $this->addLessVariables($sources); } - private function addLessVariables(SourceCollector $sources) + private function addLessVariables(SourceCollector $sources): void { $sources->addString(function () { $vars = $this->container->make('flarum.less.config'); diff --git a/framework/core/src/Frontend/RecompileFrontendAssets.php b/framework/core/src/Frontend/RecompileFrontendAssets.php index 0c4614957..799dbd479 100644 --- a/framework/core/src/Frontend/RecompileFrontendAssets.php +++ b/framework/core/src/Frontend/RecompileFrontendAssets.php @@ -17,27 +17,13 @@ use Flarum\Settings\Event\Saved; */ class RecompileFrontendAssets { - /** - * @var Assets - */ - protected $assets; - - /** - * @var LocaleManager - */ - protected $locales; - - /** - * @param Assets $assets - * @param LocaleManager $locales - */ - public function __construct(Assets $assets, LocaleManager $locales) - { - $this->assets = $assets; - $this->locales = $locales; + public function __construct( + protected Assets $assets, + protected LocaleManager $locales + ) { } - public function whenSettingsSaved(Saved $event) + public function whenSettingsSaved(Saved $event): void { // @deprecated 'theme_' check, to be removed in 2.0 if (preg_grep('/^theme_/i', array_keys($event->settings))) { @@ -45,13 +31,13 @@ class RecompileFrontendAssets } } - public function flush() + public function flush(): void { $this->flushCss(); $this->flushJs(); } - protected function flushCss() + protected function flushCss(): void { $this->assets->makeCss()->flush(); @@ -60,7 +46,7 @@ class RecompileFrontendAssets } } - protected function flushJs() + protected function flushJs(): void { $this->assets->makeJs()->flush(); diff --git a/framework/core/src/Group/Access/GroupPolicy.php b/framework/core/src/Group/Access/GroupPolicy.php index 965cfdf37..cff5c4749 100644 --- a/framework/core/src/Group/Access/GroupPolicy.php +++ b/framework/core/src/Group/Access/GroupPolicy.php @@ -14,12 +14,7 @@ use Flarum\User\User; class GroupPolicy extends AbstractPolicy { - /** - * @param User $actor - * @param string $ability - * @return bool|null - */ - public function can(User $actor, $ability) + public function can(User $actor, string $ability) { if ($actor->hasPermission('group.'.$ability)) { return $this->allow(); diff --git a/framework/core/src/Group/Access/ScopeGroupVisibility.php b/framework/core/src/Group/Access/ScopeGroupVisibility.php index 88f5a11ab..87794d8cb 100644 --- a/framework/core/src/Group/Access/ScopeGroupVisibility.php +++ b/framework/core/src/Group/Access/ScopeGroupVisibility.php @@ -14,11 +14,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopeGroupVisibility { - /** - * @param User $actor - * @param Builder $query - */ - public function __invoke(User $actor, $query) + public function __invoke(User $actor, Builder $query): void { if ($actor->cannot('viewHiddenGroups')) { $query->where('is_hidden', false); diff --git a/framework/core/src/Group/Command/CreateGroup.php b/framework/core/src/Group/Command/CreateGroup.php index 64fbb3363..247d23578 100644 --- a/framework/core/src/Group/Command/CreateGroup.php +++ b/framework/core/src/Group/Command/CreateGroup.php @@ -13,27 +13,9 @@ use Flarum\User\User; class CreateGroup { - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes of the new group. - * - * @var array - */ - public $data; - - /** - * @param User $actor The user performing the action. - * @param array $data The attributes of the new group. - */ - public function __construct(User $actor, array $data) - { - $this->actor = $actor; - $this->data = $data; + public function __construct( + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Group/Command/CreateGroupHandler.php b/framework/core/src/Group/Command/CreateGroupHandler.php index 9b1882f42..d85ad8be7 100644 --- a/framework/core/src/Group/Command/CreateGroupHandler.php +++ b/framework/core/src/Group/Command/CreateGroupHandler.php @@ -20,27 +20,13 @@ class CreateGroupHandler { use DispatchEventsTrait; - /** - * @var \Flarum\Group\GroupValidator - */ - protected $validator; - - /** - * @param Dispatcher $events - * @param \Flarum\Group\GroupValidator $validator - */ - public function __construct(Dispatcher $events, GroupValidator $validator) - { - $this->events = $events; - $this->validator = $validator; + public function __construct( + protected Dispatcher $events, + protected GroupValidator $validator + ) { } - /** - * @param CreateGroup $command - * @return \Flarum\Group\Group - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(CreateGroup $command) + public function handle(CreateGroup $command): Group { $actor = $command->actor; $data = $command->data; diff --git a/framework/core/src/Group/Command/DeleteGroup.php b/framework/core/src/Group/Command/DeleteGroup.php index 850fd8b29..7c1aadfad 100644 --- a/framework/core/src/Group/Command/DeleteGroup.php +++ b/framework/core/src/Group/Command/DeleteGroup.php @@ -13,38 +13,10 @@ use Flarum\User\User; class DeleteGroup { - /** - * The ID of the group to delete. - * - * @var int - */ - public $groupId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * Any other group input associated with the action. This is unused by - * default, but may be used by extensions. - * - * @var array - */ - public $data; - - /** - * @param int $groupId The ID of the group to delete. - * @param User $actor The user performing the action. - * @param array $data Any other group input associated with the action. This - * is unused by default, but may be used by extensions. - */ - public function __construct($groupId, User $actor, array $data = []) - { - $this->groupId = $groupId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $groupId, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/Group/Command/DeleteGroupHandler.php b/framework/core/src/Group/Command/DeleteGroupHandler.php index 7de78db37..6bca861fc 100644 --- a/framework/core/src/Group/Command/DeleteGroupHandler.php +++ b/framework/core/src/Group/Command/DeleteGroupHandler.php @@ -11,34 +11,21 @@ namespace Flarum\Group\Command; use Flarum\Foundation\DispatchEventsTrait; use Flarum\Group\Event\Deleting; +use Flarum\Group\Group; use Flarum\Group\GroupRepository; -use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Contracts\Events\Dispatcher; class DeleteGroupHandler { use DispatchEventsTrait; - /** - * @var GroupRepository - */ - protected $groups; - - /** - * @param GroupRepository $groups - */ - public function __construct(Dispatcher $events, GroupRepository $groups) - { - $this->groups = $groups; - $this->events = $events; + public function __construct( + protected Dispatcher $events, + protected GroupRepository $groups + ) { } - /** - * @param DeleteGroup $command - * @return \Flarum\Group\Group - * @throws PermissionDeniedException - */ - public function handle(DeleteGroup $command) + public function handle(DeleteGroup $command): Group { $actor = $command->actor; diff --git a/framework/core/src/Group/Command/EditGroup.php b/framework/core/src/Group/Command/EditGroup.php index 59f72499a..929107ee1 100644 --- a/framework/core/src/Group/Command/EditGroup.php +++ b/framework/core/src/Group/Command/EditGroup.php @@ -13,36 +13,10 @@ use Flarum\User\User; class EditGroup { - /** - * The ID of the group to edit. - * - * @var int - */ - public $groupId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the post. - * - * @var array - */ - public $data; - - /** - * @param int $groupId The ID of the group to edit. - * @param User $actor The user performing the action. - * @param array $data The attributes to update on the post. - */ - public function __construct($groupId, User $actor, array $data) - { - $this->groupId = $groupId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $groupId, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Group/Command/EditGroupHandler.php b/framework/core/src/Group/Command/EditGroupHandler.php index 657fc99fc..472db290a 100644 --- a/framework/core/src/Group/Command/EditGroupHandler.php +++ b/framework/core/src/Group/Command/EditGroupHandler.php @@ -14,7 +14,6 @@ use Flarum\Group\Event\Saving; use Flarum\Group\Group; use Flarum\Group\GroupRepository; use Flarum\Group\GroupValidator; -use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Support\Arr; @@ -22,34 +21,14 @@ class EditGroupHandler { use DispatchEventsTrait; - /** - * @var \Flarum\Group\GroupRepository - */ - protected $groups; - - /** - * @var GroupValidator - */ - protected $validator; - - /** - * @param Dispatcher $events - * @param GroupRepository $groups - * @param GroupValidator $validator - */ - public function __construct(Dispatcher $events, GroupRepository $groups, GroupValidator $validator) - { - $this->events = $events; - $this->groups = $groups; - $this->validator = $validator; + public function __construct( + protected Dispatcher $events, + protected GroupRepository $groups, + protected GroupValidator $validator + ) { } - /** - * @param EditGroup $command - * @return Group - * @throws PermissionDeniedException - */ - public function handle(EditGroup $command) + public function handle(EditGroup $command): Group { $actor = $command->actor; $data = $command->data; diff --git a/framework/core/src/Group/Event/Created.php b/framework/core/src/Group/Event/Created.php index dfe6cadea..0d78b4ec0 100644 --- a/framework/core/src/Group/Event/Created.php +++ b/framework/core/src/Group/Event/Created.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Created { - /** - * @var \Flarum\Group\Group - */ - public $group; - - /** - * @var User - */ - public $actor; - - /** - * @param Group $group - * @param User $actor - */ - public function __construct(Group $group, User $actor = null) - { - $this->group = $group; - $this->actor = $actor; + public function __construct( + public Group $group, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Group/Event/Deleted.php b/framework/core/src/Group/Event/Deleted.php index 71ec6cb9d..6899b23f5 100644 --- a/framework/core/src/Group/Event/Deleted.php +++ b/framework/core/src/Group/Event/Deleted.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Deleted { - /** - * @var \Flarum\Group\Group - */ - public $group; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Group\Group $group - * @param User $actor - */ - public function __construct(Group $group, User $actor = null) - { - $this->group = $group; - $this->actor = $actor; + public function __construct( + public Group $group, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Group/Event/Deleting.php b/framework/core/src/Group/Event/Deleting.php index c7870e974..22c37cc19 100644 --- a/framework/core/src/Group/Event/Deleting.php +++ b/framework/core/src/Group/Event/Deleting.php @@ -14,36 +14,10 @@ use Flarum\User\User; class Deleting { - /** - * The group that will be deleted. - * - * @var Group - */ - public $group; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * Any user input associated with the command. - * - * @var array - */ - public $data; - - /** - * @param Group $group The group that will be deleted. - * @param User $actor The user performing the action. - * @param array $data Any user input associated with the command. - */ - public function __construct(Group $group, User $actor, array $data) - { - $this->group = $group; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Group $group, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Group/Event/Renamed.php b/framework/core/src/Group/Event/Renamed.php index 904f8c9cb..c586e84cd 100644 --- a/framework/core/src/Group/Event/Renamed.php +++ b/framework/core/src/Group/Event/Renamed.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Renamed { - /** - * @var \Flarum\Group\Group - */ - public $group; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Group\Group $group - * @param User $actor - */ - public function __construct(Group $group, User $actor = null) - { - $this->group = $group; - $this->actor = $actor; + public function __construct( + public Group $group, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Group/Event/Saving.php b/framework/core/src/Group/Event/Saving.php index 725ddf6d2..db879e68a 100644 --- a/framework/core/src/Group/Event/Saving.php +++ b/framework/core/src/Group/Event/Saving.php @@ -14,36 +14,10 @@ use Flarum\User\User; class Saving { - /** - * The group that will be saved. - * - * @var \Flarum\Group\Group - */ - public $group; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the group. - * - * @var array - */ - public $data; - - /** - * @param Group $group The group that will be saved. - * @param User $actor The user who is performing the action. - * @param array $data The attributes to update on the group. - */ - public function __construct(Group $group, User $actor, array $data) - { - $this->group = $group; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Group $group, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Group/Filter/GroupFilterer.php b/framework/core/src/Group/Filter/GroupFilterer.php index 008202d12..8233b4780 100644 --- a/framework/core/src/Group/Filter/GroupFilterer.php +++ b/framework/core/src/Group/Filter/GroupFilterer.php @@ -16,21 +16,12 @@ use Illuminate\Database\Eloquent\Builder; class GroupFilterer extends AbstractFilterer { - /** - * @var GroupRepository - */ - protected $groups; - - /** - * @param GroupRepository $groups - * @param array $filters - * @param array $filterMutators - */ - public function __construct(GroupRepository $groups, array $filters, array $filterMutators) - { + public function __construct( + protected GroupRepository $groups, + array $filters, + array $filterMutators + ) { parent::__construct($filters, $filterMutators); - - $this->groups = $groups; } protected function getQuery(User $actor): Builder diff --git a/framework/core/src/Group/Filter/HiddenFilter.php b/framework/core/src/Group/Filter/HiddenFilter.php index e811f45e8..38d7c6567 100644 --- a/framework/core/src/Group/Filter/HiddenFilter.php +++ b/framework/core/src/Group/Filter/HiddenFilter.php @@ -22,7 +22,7 @@ class HiddenFilter implements FilterInterface return 'hidden'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $hidden = $this->asBool($filterValue); diff --git a/framework/core/src/Group/Group.php b/framework/core/src/Group/Group.php index 6275a84c1..927606ae4 100644 --- a/framework/core/src/Group/Group.php +++ b/framework/core/src/Group/Group.php @@ -16,6 +16,8 @@ use Flarum\Group\Event\Created; use Flarum\Group\Event\Deleted; use Flarum\Group\Event\Renamed; use Flarum\User\User; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @property int $id @@ -32,24 +34,9 @@ class Group extends AbstractModel use EventGeneratorTrait; use ScopeVisibilityTrait; - /** - * The ID of the administrator group. - */ const ADMINISTRATOR_ID = 1; - - /** - * The ID of the guest group. - */ const GUEST_ID = 2; - - /** - * The ID of the member group. - */ const MEMBER_ID = 3; - - /** - * The ID of the mod group. - */ const MODERATOR_ID = 4; /** @@ -59,11 +46,6 @@ class Group extends AbstractModel */ protected $dates = ['created_at', 'updated_at']; - /** - * Boot the model. - * - * @return void - */ public static function boot() { parent::boot(); @@ -73,17 +55,7 @@ class Group extends AbstractModel }); } - /** - * Create a new group. - * - * @param string $nameSingular - * @param string $namePlural - * @param string $color - * @param string $icon - * @param bool $isHidden - * @return static - */ - public static function build($nameSingular, $namePlural, $color = null, $icon = null, bool $isHidden = false): self + public static function build(?string $nameSingular, ?string $namePlural, ?string $color = null, ?string $icon = null, bool $isHidden = false): static { $group = new static; @@ -98,14 +70,7 @@ class Group extends AbstractModel return $group; } - /** - * Rename the group. - * - * @param string $nameSingular - * @param string $namePlural - * @return $this - */ - public function rename($nameSingular, $namePlural) + public function rename(string $nameSingular, string $namePlural): static { $this->name_singular = $nameSingular; $this->name_plural = $namePlural; @@ -116,32 +81,22 @@ class Group extends AbstractModel } /** - * Define the relationship with the group's users. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return BelongsToMany<User> */ - public function users() + public function users(): BelongsToMany { return $this->belongsToMany(User::class); } /** - * Define the relationship with the group's permissions. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function permissions() + public function permissions(): HasMany { return $this->hasMany(Permission::class); } - /** - * Check whether the group has a certain permission. - * - * @param string $permission - * @return bool - */ - public function hasPermission($permission) + public function hasPermission(string $permission): bool { if ($this->id == self::ADMINISTRATOR_ID) { return true; diff --git a/framework/core/src/Group/GroupRepository.php b/framework/core/src/Group/GroupRepository.php index 30bd06218..1a6bc4b51 100644 --- a/framework/core/src/Group/GroupRepository.php +++ b/framework/core/src/Group/GroupRepository.php @@ -15,8 +15,6 @@ use Illuminate\Database\Eloquent\Builder; class GroupRepository { /** - * Get a new query builder for the groups table. - * * @return Builder<Group> */ public function query() @@ -28,20 +26,16 @@ class GroupRepository * Find a user by ID, optionally making sure it is visible to a certain * user, or throw an exception. * - * @param int $id - * @param User|null $actor - * @return Group - * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ - public function findOrFail($id, User $actor = null) + public function findOrFail(string|int $id, ?User $actor = null): Group { $query = $this->query()->where('id', $id); return $this->scopeVisibleTo($query, $actor)->firstOrFail(); } - public function queryVisibleTo(?User $actor = null) + public function queryVisibleTo(?User $actor = null): Builder { return $this->scopeVisibleTo($this->query(), $actor); } @@ -53,7 +47,7 @@ class GroupRepository * @param User|null $actor * @return Builder<Group> */ - protected function scopeVisibleTo(Builder $query, ?User $actor = null) + protected function scopeVisibleTo(Builder $query, ?User $actor = null): Builder { if ($actor !== null) { $query->whereVisibleTo($actor); diff --git a/framework/core/src/Group/GroupServiceProvider.php b/framework/core/src/Group/GroupServiceProvider.php index 49a278e88..55801a07a 100644 --- a/framework/core/src/Group/GroupServiceProvider.php +++ b/framework/core/src/Group/GroupServiceProvider.php @@ -14,10 +14,7 @@ use Flarum\Group\Access\ScopeGroupVisibility; class GroupServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function boot() + public function boot(): void { Group::registerVisibilityScoper(new ScopeGroupVisibility(), 'view'); } diff --git a/framework/core/src/Group/GroupValidator.php b/framework/core/src/Group/GroupValidator.php index e1e09cfe3..26a571d1e 100644 --- a/framework/core/src/Group/GroupValidator.php +++ b/framework/core/src/Group/GroupValidator.php @@ -13,7 +13,7 @@ use Flarum\Foundation\AbstractValidator; class GroupValidator extends AbstractValidator { - protected $rules = [ + protected array $rules = [ 'name_singular' => ['required'], 'name_plural' => ['required'] ]; diff --git a/framework/core/src/Group/Permission.php b/framework/core/src/Group/Permission.php index 09ec03491..5ddb3e854 100644 --- a/framework/core/src/Group/Permission.php +++ b/framework/core/src/Group/Permission.php @@ -11,6 +11,7 @@ namespace Flarum\Group; use Flarum\Database\AbstractModel; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @property int $group_id @@ -18,9 +19,6 @@ use Illuminate\Database\Eloquent\Builder; */ class Permission extends AbstractModel { - /** - * {@inheritdoc} - */ protected $table = 'group_permission'; /** @@ -30,12 +28,7 @@ class Permission extends AbstractModel */ protected $dates = ['created_at']; - /** - * Define the relationship with the group that this permission is for. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function group() + public function group(): BelongsTo { return $this->belongsTo(Group::class); } @@ -59,7 +52,7 @@ class Permission extends AbstractModel * * @return array[] */ - public static function map() + public static function map(): array { $permissions = []; diff --git a/framework/core/src/Http/Access/ScopeAccessTokenVisibility.php b/framework/core/src/Http/Access/ScopeAccessTokenVisibility.php index 7fd4f5c5c..42e2f5183 100644 --- a/framework/core/src/Http/Access/ScopeAccessTokenVisibility.php +++ b/framework/core/src/Http/Access/ScopeAccessTokenVisibility.php @@ -14,11 +14,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopeAccessTokenVisibility { - /** - * @param User $actor - * @param Builder $query - */ - public function __invoke(User $actor, $query) + public function __invoke(User $actor, Builder $query): void { if ($actor->isGuest()) { $query->whereRaw('FALSE'); diff --git a/framework/core/src/Http/AccessToken.php b/framework/core/src/Http/AccessToken.php index 56c30e37c..25137b148 100644 --- a/framework/core/src/Http/AccessToken.php +++ b/framework/core/src/Http/AccessToken.php @@ -14,6 +14,7 @@ use Flarum\Database\AbstractModel; use Flarum\Database\ScopeVisibilityTrait; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Psr\Http\Message\ServerRequestInterface; @@ -43,10 +44,8 @@ class AccessToken extends AbstractModel /** * A map of access token types, as specified in the `type` column, to their classes. - * - * @var array */ - protected static $models = []; + protected static array $models = []; /** * The type of token this is, to be stored in the access tokens table. @@ -54,17 +53,15 @@ class AccessToken extends AbstractModel * Should be overwritten by subclasses with the value that is * to be stored in the database, which will then be used for * mapping the hydrated model instance to the proper subtype. - * - * @var string */ - public static $type = ''; + public static string $type = ''; /** * How long this access token should be valid from the time of last activity. * This value will be used in the validity and expiration checks. * @var int Lifetime in seconds. Zero means it will never expire. */ - protected static $lifetime = 0; + protected static int $lifetime = 0; /** * Difference from the current `last_activity_at` attribute value before `updateLastSeen()` @@ -74,11 +71,8 @@ class AccessToken extends AbstractModel /** * Generate an access token for the specified user. - * - * @param int $userId - * @return static */ - public static function generate($userId) + public static function generate(int $userId): static { if (static::class === self::class) { throw new \Exception('Use of AccessToken::generate() is not allowed: use the `generate` method on one of the subclasses.'); @@ -99,10 +93,8 @@ class AccessToken extends AbstractModel /** * Update the time of last usage of a token. * If a request object is provided, the IP address and User Agent will also be logged. - * @param ServerRequestInterface|null $request - * @return bool */ - public function touch(ServerRequestInterface $request = null) + public function touch(?ServerRequestInterface $request = null): bool { $now = Carbon::now(); @@ -127,12 +119,7 @@ class AccessToken extends AbstractModel return $this->save(); } - /** - * Define the relationship with the owner of this access token. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } @@ -140,10 +127,8 @@ class AccessToken extends AbstractModel /** * Filters which tokens are valid at the given date for this particular token type. * Uses the static::$lifetime value by default, can be overridden by children classes. - * @param Builder $query - * @param Carbon $date */ - protected static function scopeValid(Builder $query, Carbon $date) + protected static function scopeValid(Builder $query, Carbon $date): void { if (static::$lifetime > 0) { $query->where('last_activity_at', '>', $date->clone()->subSeconds(static::$lifetime)); @@ -153,10 +138,8 @@ class AccessToken extends AbstractModel /** * Filters which tokens are expired at the given date and ready for garbage collection. * Uses the static::$lifetime value by default, can be overridden by children classes. - * @param Builder $query - * @param Carbon $date */ - protected static function scopeExpired(Builder $query, Carbon $date) + protected static function scopeExpired(Builder $query, Carbon $date): void { if (static::$lifetime > 0) { $query->where('last_activity_at', '<', $date->clone()->subSeconds(static::$lifetime)); @@ -168,19 +151,16 @@ class AccessToken extends AbstractModel /** * Shortcut to find a valid token. * @param string $token Token as sent by the user. We allow non-string values like null so we can directly feed any value from a request. - * @return AccessToken|null */ - public static function findValid($token): ?AccessToken + public static function findValid(string $token): ?AccessToken { return static::query()->whereValid()->where('token', $token)->first(); } /** * This query scope is intended to be used on the base AccessToken object to query for valid tokens of any type. - * @param Builder $query - * @param Carbon|null $date */ - public function scopeWhereValid(Builder $query, Carbon $date = null) + public function scopeWhereValid(Builder $query, ?Carbon $date = null): void { if (is_null($date)) { $date = Carbon::now(); @@ -198,10 +178,8 @@ class AccessToken extends AbstractModel /** * This query scope is intended to be used on the base AccessToken object to query for expired tokens of any type. - * @param Builder $query - * @param Carbon|null $date */ - public function scopeWhereExpired(Builder $query, Carbon $date = null) + public function scopeWhereExpired(Builder $query, Carbon $date = null): void { if (is_null($date)) { $date = Carbon::now(); @@ -246,10 +224,8 @@ class AccessToken extends AbstractModel /** * Get the type-to-model map. - * - * @return array */ - public static function getModels() + public static function getModels(): array { return static::$models; } @@ -257,11 +233,9 @@ class AccessToken extends AbstractModel /** * Set the model for the given access token type. * - * @param string $type The access token type. - * @param string $model The class name of the model for that type. - * @return void + * @param class-string<self> $model The class name of the model for that type. */ - public static function setModel(string $type, string $model) + public static function setModel(string $type, string $model): void { static::$models[$type] = $model; } diff --git a/framework/core/src/Http/ActorReference.php b/framework/core/src/Http/ActorReference.php index 9d4a5c66e..8e2816e8b 100644 --- a/framework/core/src/Http/ActorReference.php +++ b/framework/core/src/Http/ActorReference.php @@ -13,12 +13,9 @@ use Flarum\User\User; class ActorReference { - /** - * @var User - */ - private $actor; + private User $actor; - public function setActor(User $actor) + public function setActor(User $actor): void { $this->actor = $actor; } diff --git a/framework/core/src/Http/Controller/AbstractHtmlController.php b/framework/core/src/Http/Controller/AbstractHtmlController.php index e30666248..2a02d64a9 100644 --- a/framework/core/src/Http/Controller/AbstractHtmlController.php +++ b/framework/core/src/Http/Controller/AbstractHtmlController.php @@ -17,10 +17,6 @@ use Psr\Http\Server\RequestHandlerInterface; abstract class AbstractHtmlController implements RequestHandlerInterface { - /** - * @param Request $request - * @return HtmlResponse - */ public function handle(Request $request): ResponseInterface { $view = $this->render($request); @@ -32,9 +28,5 @@ abstract class AbstractHtmlController implements RequestHandlerInterface return new HtmlResponse($view); } - /** - * @param Request $request - * @return string|Renderable - */ - abstract protected function render(Request $request); + abstract protected function render(Request $request): Renderable|string; } diff --git a/framework/core/src/Http/CookieFactory.php b/framework/core/src/Http/CookieFactory.php index fb5f72a69..bf955ccb0 100644 --- a/framework/core/src/Http/CookieFactory.php +++ b/framework/core/src/Http/CookieFactory.php @@ -15,54 +15,22 @@ use Flarum\Foundation\Config; class CookieFactory { - /** - * The prefix for the cookie names. - * - * @var string - */ - protected $prefix; + protected string $prefix; + protected string $path; + protected string $domain; + protected bool $secure; + protected ?string $samesite = null; - /** - * A path scope for the cookies. - * - * @var string - */ - protected $path; - - /** - * A domain scope for the cookies. - * - * @var string - */ - protected $domain; - - /** - * Whether the cookie(s) can be requested only over HTTPS. - * - * @var bool - */ - protected $secure; - - /** - * Same Site cookie value. - * - * @var string|null - */ - protected $samesite; - - /** - * @param Config $config - */ public function __construct(Config $config) { // If necessary, we will use the forum's base URL to determine smart defaults for cookie settings $url = $config->url(); // Get the cookie settings from the config or use the default values - $this->prefix = $config['cookie.name'] ?? 'flarum'; - $this->path = $config['cookie.path'] ?? $url->getPath() ?: '/'; - $this->domain = $config['cookie.domain']; - $this->secure = $config['cookie.secure'] ?? $url->getScheme() === 'https'; + $this->prefix = (string) ($config['cookie.name'] ?? 'flarum'); + $this->path = (string) ($config['cookie.path'] ?? $url->getPath() ?: '/'); + $this->domain = (string) $config['cookie.domain']; + $this->secure = (bool) ($config['cookie.secure'] ?? $url->getScheme() === 'https'); $this->samesite = $config['cookie.samesite']; } @@ -71,13 +39,8 @@ class CookieFactory * * This method returns a cookie instance for use with the Set-Cookie HTTP header. * It will be pre-configured according to Flarum's base URL and protocol. - * - * @param string $name - * @param string $value - * @param int $maxAge - * @return \Dflydev\FigCookies\SetCookie */ - public function make(string $name, string $value = null, int $maxAge = null): SetCookie + public function make(string $name, ?string $value = null, ?int $maxAge = null): SetCookie { $cookie = SetCookie::create($this->getName($name), $value); @@ -104,9 +67,6 @@ class CookieFactory /** * Make an expired cookie instance. - * - * @param string $name - * @return \Dflydev\FigCookies\SetCookie */ public function expire(string $name): SetCookie { @@ -115,9 +75,6 @@ class CookieFactory /** * Get a cookie name. - * - * @param string $name - * @return string */ public function getName(string $name): string { diff --git a/framework/core/src/Http/DeveloperAccessToken.php b/framework/core/src/Http/DeveloperAccessToken.php index 751a836a8..1b2e8fa77 100644 --- a/framework/core/src/Http/DeveloperAccessToken.php +++ b/framework/core/src/Http/DeveloperAccessToken.php @@ -11,7 +11,7 @@ namespace Flarum\Http; class DeveloperAccessToken extends AccessToken { - public static $type = 'developer'; + public static string $type = 'developer'; - protected static $lifetime = 0; + protected static int $lifetime = 0; } diff --git a/framework/core/src/Http/Event/DeveloperTokenCreated.php b/framework/core/src/Http/Event/DeveloperTokenCreated.php index 846077429..ec6839e9a 100644 --- a/framework/core/src/Http/Event/DeveloperTokenCreated.php +++ b/framework/core/src/Http/Event/DeveloperTokenCreated.php @@ -13,13 +13,8 @@ use Flarum\Http\AccessToken; class DeveloperTokenCreated { - /** - * @var AccessToken - */ - public $token; - - public function __construct(AccessToken $token) - { - $this->token = $token; + public function __construct( + public AccessToken $token + ) { } } diff --git a/framework/core/src/Http/Filter/UserFilter.php b/framework/core/src/Http/Filter/UserFilter.php index 12268042a..5a8e4f68b 100644 --- a/framework/core/src/Http/Filter/UserFilter.php +++ b/framework/core/src/Http/Filter/UserFilter.php @@ -23,18 +23,12 @@ class UserFilter implements FilterInterface { use ValidateFilterTrait; - /** - * @inheritDoc - */ public function getFilterKey(): string { return 'user'; } - /** - * @inheritDoc - */ - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $filterValue = $this->asInt($filterValue); diff --git a/framework/core/src/Http/HttpServiceProvider.php b/framework/core/src/Http/HttpServiceProvider.php index fd555cd6d..83d777cfc 100644 --- a/framework/core/src/Http/HttpServiceProvider.php +++ b/framework/core/src/Http/HttpServiceProvider.php @@ -23,10 +23,7 @@ use Illuminate\Support\Arr; class HttpServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.http.csrfExemptPaths', function () { return ['token']; @@ -64,22 +61,20 @@ class HttpServiceProvider extends AbstractServiceProvider return $compiledDrivers; }); + $this->container->bind(SlugManager::class, function (Container $container) { return new SlugManager($container->make('flarum.http.selectedSlugDrivers')); }); } - /** - * {@inheritdoc} - */ - public function boot() + public function boot(): void { $this->setAccessTokenTypes(); AccessToken::registerVisibilityScoper(new ScopeAccessTokenVisibility(), 'view'); } - protected function setAccessTokenTypes() + protected function setAccessTokenTypes(): void { $models = [ DeveloperAccessToken::class, diff --git a/framework/core/src/Http/Middleware/AuthenticateWithHeader.php b/framework/core/src/Http/Middleware/AuthenticateWithHeader.php index 857381c70..f505aeff3 100644 --- a/framework/core/src/Http/Middleware/AuthenticateWithHeader.php +++ b/framework/core/src/Http/Middleware/AuthenticateWithHeader.php @@ -58,12 +58,14 @@ class AuthenticateWithHeader implements Middleware return $handler->handle($request); } - private function getUser($string) + private function getUser($string): ?User { $parts = explode('=', trim($string)); if (isset($parts[0]) && $parts[0] === 'userId') { return User::find($parts[1]); } + + return null; } } diff --git a/framework/core/src/Http/Middleware/AuthenticateWithSession.php b/framework/core/src/Http/Middleware/AuthenticateWithSession.php index d4d5fbe06..3e98c74a0 100644 --- a/framework/core/src/Http/Middleware/AuthenticateWithSession.php +++ b/framework/core/src/Http/Middleware/AuthenticateWithSession.php @@ -12,6 +12,7 @@ namespace Flarum\Http\Middleware; use Flarum\Http\AccessToken; use Flarum\Http\RequestUtil; use Flarum\User\Guest; +use Flarum\User\User; use Illuminate\Contracts\Session\Session; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -31,7 +32,7 @@ class AuthenticateWithSession implements Middleware return $handler->handle($request); } - private function getActor(Session $session, Request $request) + private function getActor(Session $session, Request $request): Guest|User { if ($session->has('access_token')) { $token = AccessToken::findValid($session->get('access_token')); diff --git a/framework/core/src/Http/Middleware/CheckCsrfToken.php b/framework/core/src/Http/Middleware/CheckCsrfToken.php index 4b7f2e1f3..d4d3aa5dd 100644 --- a/framework/core/src/Http/Middleware/CheckCsrfToken.php +++ b/framework/core/src/Http/Middleware/CheckCsrfToken.php @@ -17,19 +17,15 @@ use Psr\Http\Server\RequestHandlerInterface as Handler; class CheckCsrfToken implements Middleware { - protected $exemptRoutes; - - public function __construct(array $exemptRoutes) - { - $this->exemptRoutes = $exemptRoutes; + public function __construct( + protected array $exemptRoutes + ) { } public function process(Request $request, Handler $handler): Response { - foreach ($this->exemptRoutes as $exemptRoute) { - if ($exemptRoute === $request->getAttribute('routeName')) { - return $handler->handle($request); - } + if (in_array($request->getAttribute('routeName'), $this->exemptRoutes, true)) { + return $handler->handle($request); } if (in_array($request->getMethod(), ['GET', 'HEAD', 'OPTIONS'])) { diff --git a/framework/core/src/Http/Middleware/CollectGarbage.php b/framework/core/src/Http/Middleware/CollectGarbage.php index c20330891..0f2e7353d 100644 --- a/framework/core/src/Http/Middleware/CollectGarbage.php +++ b/framework/core/src/Http/Middleware/CollectGarbage.php @@ -23,20 +23,13 @@ use SessionHandlerInterface; class CollectGarbage implements Middleware { - /** - * @var SessionHandlerInterface - */ - protected $sessionHandler; + protected array $sessionConfig; - /** - * @var array - */ - protected $sessionConfig; - - public function __construct(SessionHandlerInterface $handler, ConfigRepository $config) - { - $this->sessionHandler = $handler; - $this->sessionConfig = $config->get('session'); + public function __construct( + protected SessionHandlerInterface $sessionHandler, + ConfigRepository $config + ) { + $this->sessionConfig = (array) $config->get('session'); } public function process(Request $request, Handler $handler): Response @@ -46,7 +39,7 @@ class CollectGarbage implements Middleware return $handler->handle($request); } - private function collectGarbageSometimes() + private function collectGarbageSometimes(): void { // In order to save performance, we only execute this query // from time to time (with 2% chance). @@ -67,12 +60,12 @@ class CollectGarbage implements Middleware $this->sessionHandler->gc($this->getSessionLifetimeInSeconds()); } - private function hit() + private function hit(): bool { return mt_rand(1, 100) <= 2; } - private function getSessionLifetimeInSeconds() + private function getSessionLifetimeInSeconds(): float|int { return $this->sessionConfig['lifetime'] * 60; } diff --git a/framework/core/src/Http/Middleware/FlarumPromotionHeader.php b/framework/core/src/Http/Middleware/FlarumPromotionHeader.php index 773741434..fd27056da 100644 --- a/framework/core/src/Http/Middleware/FlarumPromotionHeader.php +++ b/framework/core/src/Http/Middleware/FlarumPromotionHeader.php @@ -18,11 +18,11 @@ use Psr\Http\Server\RequestHandlerInterface; class FlarumPromotionHeader implements Middleware { - protected $enabled = true; + protected bool $enabled = true; public function __construct(Config $config) { - $this->enabled = Arr::get($config, 'headers.poweredByHeader') ?? true; + $this->enabled = (bool) (Arr::get($config, 'headers.poweredByHeader') ?? true); } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/framework/core/src/Http/Middleware/HandleErrors.php b/framework/core/src/Http/Middleware/HandleErrors.php index a2d741884..102fe29a6 100644 --- a/framework/core/src/Http/Middleware/HandleErrors.php +++ b/framework/core/src/Http/Middleware/HandleErrors.php @@ -26,26 +26,12 @@ use Throwable; */ class HandleErrors implements Middleware { - /** - * @var Registry - */ - protected $registry; - - /** - * @var HttpFormatter - */ - protected $formatter; - - /** - * @var \Flarum\Foundation\ErrorHandling\Reporter[] - */ - protected $reporters; - - public function __construct(Registry $registry, HttpFormatter $formatter, iterable $reporters) - { - $this->registry = $registry; - $this->formatter = $formatter; - $this->reporters = $reporters; + public function __construct( + protected Registry $registry, + protected HttpFormatter $formatter, + /** @var \Flarum\Foundation\ErrorHandling\Reporter[] $reporters */ + protected iterable $reporters + ) { } /** diff --git a/framework/core/src/Http/Middleware/ReferrerPolicyHeader.php b/framework/core/src/Http/Middleware/ReferrerPolicyHeader.php index fd1769542..7627b109e 100644 --- a/framework/core/src/Http/Middleware/ReferrerPolicyHeader.php +++ b/framework/core/src/Http/Middleware/ReferrerPolicyHeader.php @@ -18,11 +18,11 @@ use Psr\Http\Server\RequestHandlerInterface; class ReferrerPolicyHeader implements Middleware { - protected $policy = ''; + protected string $policy = ''; public function __construct(Config $config) { - $this->policy = Arr::get($config, 'headers.referrerPolicy') ?? 'same-origin'; + $this->policy = strval(Arr::get($config, 'headers.referrerPolicy') ?? 'same-origin'); } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/framework/core/src/Http/Middleware/RememberFromCookie.php b/framework/core/src/Http/Middleware/RememberFromCookie.php index 8c933231f..3c9620372 100644 --- a/framework/core/src/Http/Middleware/RememberFromCookie.php +++ b/framework/core/src/Http/Middleware/RememberFromCookie.php @@ -20,17 +20,9 @@ use Psr\Http\Server\RequestHandlerInterface as Handler; class RememberFromCookie implements Middleware { - /** - * @var CookieFactory - */ - protected $cookie; - - /** - * @param CookieFactory $cookie - */ - public function __construct(CookieFactory $cookie) - { - $this->cookie = $cookie; + public function __construct( + protected CookieFactory $cookie + ) { } public function process(Request $request, Handler $handler): Response diff --git a/framework/core/src/Http/Middleware/ResolveRoute.php b/framework/core/src/Http/Middleware/ResolveRoute.php index dc27027fd..df9066f95 100644 --- a/framework/core/src/Http/Middleware/ResolveRoute.php +++ b/framework/core/src/Http/Middleware/ResolveRoute.php @@ -20,31 +20,16 @@ use Psr\Http\Server\RequestHandlerInterface as Handler; class ResolveRoute implements Middleware { - /** - * @var RouteCollection - */ - protected $routes; + protected ?Dispatcher\GroupCountBased $dispatcher = null; - /** - * @var Dispatcher|null - */ - protected $dispatcher; - - /** - * Create the middleware instance. - * - * @param RouteCollection $routes - */ - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; + public function __construct( + protected RouteCollection $routes + ) { } /** * Resolve the given request from our route collection. * - * @return Response - * * @throws MethodNotAllowedException * @throws RouteNotFoundException */ @@ -70,7 +55,7 @@ class ResolveRoute implements Middleware } } - protected function getDispatcher() + protected function getDispatcher(): Dispatcher\GroupCountBased { if (! isset($this->dispatcher)) { $this->dispatcher = new Dispatcher\GroupCountBased($this->routes->getRouteData()); diff --git a/framework/core/src/Http/Middleware/SetLocale.php b/framework/core/src/Http/Middleware/SetLocale.php index dd44afcb9..eeb09d7f7 100644 --- a/framework/core/src/Http/Middleware/SetLocale.php +++ b/framework/core/src/Http/Middleware/SetLocale.php @@ -19,17 +19,9 @@ use Psr\Http\Server\RequestHandlerInterface as Handler; class SetLocale implements Middleware { - /** - * @var LocaleManager - */ - protected $locales; - - /** - * @param LocaleManager $locales - */ - public function __construct(LocaleManager $locales) - { - $this->locales = $locales; + public function __construct( + protected LocaleManager $locales + ) { } public function process(Request $request, Handler $handler): Response diff --git a/framework/core/src/Http/Middleware/ShareErrorsFromSession.php b/framework/core/src/Http/Middleware/ShareErrorsFromSession.php index 17e8f7e78..c3511e6d8 100644 --- a/framework/core/src/Http/Middleware/ShareErrorsFromSession.php +++ b/framework/core/src/Http/Middleware/ShareErrorsFromSession.php @@ -23,17 +23,9 @@ use Psr\Http\Server\RequestHandlerInterface as Handler; */ class ShareErrorsFromSession implements Middleware { - /** - * @var ViewFactory - */ - protected $view; - - /** - * @param ViewFactory $view - */ - public function __construct(ViewFactory $view) - { - $this->view = $view; + public function __construct( + protected ViewFactory $view + ) { } public function process(Request $request, Handler $handler): Response diff --git a/framework/core/src/Http/Middleware/StartSession.php b/framework/core/src/Http/Middleware/StartSession.php index d6b89c456..cf812e5a3 100644 --- a/framework/core/src/Http/Middleware/StartSession.php +++ b/framework/core/src/Http/Middleware/StartSession.php @@ -23,31 +23,14 @@ use SessionHandlerInterface; class StartSession implements Middleware { - /** - * @var SessionHandlerInterface - */ - protected $handler; + protected array $config; - /** - * @var CookieFactory - */ - protected $cookie; - - /** - * @var array - */ - protected $config; - - /** - * @param SessionHandlerInterface $handler - * @param CookieFactory $cookie - * @param ConfigRepository $config - */ - public function __construct(SessionHandlerInterface $handler, CookieFactory $cookie, ConfigRepository $config) - { - $this->handler = $handler; - $this->cookie = $cookie; - $this->config = $config->get('session'); + public function __construct( + protected SessionHandlerInterface $handler, + protected CookieFactory $cookie, + ConfigRepository $config + ) { + $this->config = (array) $config->get('session'); } public function process(Request $request, Handler $handler): Response diff --git a/framework/core/src/Http/RememberAccessToken.php b/framework/core/src/Http/RememberAccessToken.php index 33c971d2b..c521f8ba6 100644 --- a/framework/core/src/Http/RememberAccessToken.php +++ b/framework/core/src/Http/RememberAccessToken.php @@ -11,15 +11,14 @@ namespace Flarum\Http; class RememberAccessToken extends AccessToken { - public static $type = 'session_remember'; + public static string $type = 'session_remember'; - protected static $lifetime = 5 * 365 * 24 * 60 * 60; // 5 years + protected static int $lifetime = 5 * 365 * 24 * 60 * 60; // 5 years protected $hidden = ['token']; /** * Just a helper method so we can re-use the lifetime value which is protected. - * @return int */ public static function rememberCookieLifeTime(): int { diff --git a/framework/core/src/Http/Rememberer.php b/framework/core/src/Http/Rememberer.php index 2f8eb763b..24dc23d90 100644 --- a/framework/core/src/Http/Rememberer.php +++ b/framework/core/src/Http/Rememberer.php @@ -16,26 +16,15 @@ class Rememberer { const COOKIE_NAME = 'remember'; - /** - * @var CookieFactory - */ - protected $cookie; - - /** - * @param CookieFactory $cookie - */ - public function __construct(CookieFactory $cookie) - { - $this->cookie = $cookie; + public function __construct( + protected CookieFactory $cookie + ) { } /** * Sets the remember cookie on a response. - * @param ResponseInterface $response - * @param RememberAccessToken $token The remember token to set on the response. - * @return ResponseInterface */ - public function remember(ResponseInterface $response, RememberAccessToken $token) + public function remember(ResponseInterface $response, RememberAccessToken $token): ResponseInterface { return FigResponseCookies::set( $response, @@ -43,7 +32,7 @@ class Rememberer ); } - public function forget(ResponseInterface $response) + public function forget(ResponseInterface $response): ResponseInterface { return FigResponseCookies::set( $response, diff --git a/framework/core/src/Http/RouteCollection.php b/framework/core/src/Http/RouteCollection.php index 6b19b9df9..a27640441 100644 --- a/framework/core/src/Http/RouteCollection.php +++ b/framework/core/src/Http/RouteCollection.php @@ -18,30 +18,11 @@ use Illuminate\Support\Arr; */ class RouteCollection { - /** - * @var array - */ - protected $reverse = []; - - /** - * @var DataGenerator - */ - protected $dataGenerator; - - /** - * @var RouteParser - */ - protected $routeParser; - - /** - * @var array - */ - protected $routes = []; - - /** - * @var array - */ - protected $pendingRoutes = []; + protected array $reverse = []; + protected DataGenerator $dataGenerator; + protected RouteParser $routeParser; + protected array $routes = []; + protected array $pendingRoutes = []; public function __construct() { @@ -49,32 +30,32 @@ class RouteCollection $this->routeParser = new RouteParser\Std; } - public function get($path, $name, $handler) + public function get($path, $name, $handler): self { return $this->addRoute('GET', $path, $name, $handler); } - public function post($path, $name, $handler) + public function post($path, $name, $handler): self { return $this->addRoute('POST', $path, $name, $handler); } - public function put($path, $name, $handler) + public function put($path, $name, $handler): self { return $this->addRoute('PUT', $path, $name, $handler); } - public function patch($path, $name, $handler) + public function patch($path, $name, $handler): self { return $this->addRoute('PATCH', $path, $name, $handler); } - public function delete($path, $name, $handler) + public function delete($path, $name, $handler): self { return $this->addRoute('DELETE', $path, $name, $handler); } - public function addRoute($method, $path, $name, $handler) + public function addRoute($method, $path, $name, $handler): self { if (isset($this->routes[$name])) { throw new \RuntimeException("Route $name already exists"); @@ -112,7 +93,7 @@ class RouteCollection return $this->routes; } - public function getRouteData() + public function getRouteData(): array { if (! empty($this->pendingRoutes)) { $this->applyRoutes(); @@ -121,7 +102,7 @@ class RouteCollection return $this->dataGenerator->getData(); } - protected function fixPathPart($part, array $parameters, string $routeName) + protected function fixPathPart(mixed $part, array $parameters, string $routeName) { if (! is_array($part)) { return $part; @@ -134,7 +115,7 @@ class RouteCollection return $parameters[$part[0]]; } - public function getPath($name, array $parameters = []) + public function getPath(string $name, array $parameters = []): string { if (! empty($this->pendingRoutes)) { $this->applyRoutes(); diff --git a/framework/core/src/Http/RouteCollectionUrlGenerator.php b/framework/core/src/Http/RouteCollectionUrlGenerator.php index dffa13982..236cbcbd6 100644 --- a/framework/core/src/Http/RouteCollectionUrlGenerator.php +++ b/framework/core/src/Http/RouteCollectionUrlGenerator.php @@ -14,34 +14,13 @@ namespace Flarum\Http; */ class RouteCollectionUrlGenerator { - /** - * @var string|null - */ - protected $baseUrl; - - /** - * @var RouteCollection - */ - protected $routes; - - /** - * @param string $baseUrl - * @param RouteCollection $routes - */ - public function __construct($baseUrl, RouteCollection $routes) - { - $this->baseUrl = $baseUrl; - $this->routes = $routes; + public function __construct( + protected string $baseUrl, + protected RouteCollection $routes + ) { } - /** - * Generate a URL to a named route. - * - * @param string $name - * @param array $parameters - * @return string - */ - public function route($name, $parameters = []) + public function route(string $name, array $parameters = []): string { $path = $this->routes->getPath($name, $parameters); $path = ltrim($path, '/'); @@ -49,23 +28,12 @@ class RouteCollectionUrlGenerator return $this->baseUrl.'/'.$path; } - /** - * Generate a URL to a path. - * - * @param string $path - * @return string - */ - public function path($path) + public function path(string $path): string { return $this->baseUrl.'/'.$path; } - /** - * Generate a URL to base with UrlGenerator's prefix. - * - * @return string - */ - public function base() + public function base(): string { return $this->baseUrl; } diff --git a/framework/core/src/Http/RouteHandlerFactory.php b/framework/core/src/Http/RouteHandlerFactory.php index ac49b7ca6..ea45c3b8b 100644 --- a/framework/core/src/Http/RouteHandlerFactory.php +++ b/framework/core/src/Http/RouteHandlerFactory.php @@ -21,14 +21,9 @@ use Psr\Http\Server\RequestHandlerInterface as Handler; */ class RouteHandlerFactory { - /** - * @var Container - */ - protected $container; - - public function __construct(Container $container) - { - $this->container = $container; + public function __construct( + protected Container $container + ) { } public function toController($controller): Closure @@ -42,11 +37,7 @@ class RouteHandlerFactory }; } - /** - * @param string $frontend - * @param string|callable|null $content - */ - public function toFrontend(string $frontend, $content = null): Closure + public function toFrontend(string $frontend, callable|string|null $content = null): Closure { return $this->toController(function (Container $container) use ($frontend, $content) { $frontend = $container->make("flarum.frontend.$frontend"); diff --git a/framework/core/src/Http/Server.php b/framework/core/src/Http/Server.php index 278caba66..c872d05f1 100644 --- a/framework/core/src/Http/Server.php +++ b/framework/core/src/Http/Server.php @@ -23,14 +23,12 @@ use Throwable; class Server { - private $site; - - public function __construct(SiteInterface $site) - { - $this->site = $site; + public function __construct( + private readonly SiteInterface $site + ) { } - public function listen() + public function listen(): void { $runner = new RequestHandlerRunner( $this->safelyBootAndGetHandler(), @@ -42,6 +40,7 @@ class Server return $generator($e, new ServerRequest, new Response); } ); + $runner->run(); } @@ -51,7 +50,7 @@ class Server * We catch all exceptions happening during this process and format them to * prevent exposure of sensitive information. * - * @return \Psr\Http\Server\RequestHandlerInterface|void + * @throws Throwable */ private function safelyBootAndGetHandler() { @@ -78,8 +77,9 @@ class Server * for example if the container bindings aren't present * or if there is a filesystem error. * @param Throwable $error + * @throws Throwable */ - private function cleanBootExceptionLog(Throwable $error) + private function cleanBootExceptionLog(Throwable $error): void { $container = resolve(Container::class); @@ -114,10 +114,10 @@ ERROR; /** * If the clean logging doesn't work, then we have a last opportunity. * Here we need to be extra careful not to include anything that might be sensitive on the page. - * @param Throwable $error + * * @throws Throwable */ - private function fallbackBootExceptionLog(Throwable $error) + private function fallbackBootExceptionLog(Throwable $error): void { echo 'Flarum encountered a boot error. Details have been logged to the system PHP log file.<br />'; diff --git a/framework/core/src/Http/SessionAccessToken.php b/framework/core/src/Http/SessionAccessToken.php index 12cb7fd67..4dae1f68f 100644 --- a/framework/core/src/Http/SessionAccessToken.php +++ b/framework/core/src/Http/SessionAccessToken.php @@ -11,9 +11,9 @@ namespace Flarum\Http; class SessionAccessToken extends AccessToken { - public static $type = 'session'; + public static string $type = 'session'; - protected static $lifetime = 60 * 60; // 1 hour + protected static int $lifetime = 60 * 60; // 1 hour protected $hidden = ['token']; } diff --git a/framework/core/src/Http/SessionAuthenticator.php b/framework/core/src/Http/SessionAuthenticator.php index 7698fee15..35ee76753 100644 --- a/framework/core/src/Http/SessionAuthenticator.php +++ b/framework/core/src/Http/SessionAuthenticator.php @@ -13,26 +13,17 @@ use Illuminate\Contracts\Session\Session; class SessionAuthenticator { - /** - * @param Session $session - * @param AccessToken $token - */ - public function logIn(Session $session, AccessToken $token) + public function logIn(Session $session, AccessToken $token): void { $session->regenerate(true); $session->put('access_token', $token->token); } - /** - * @param Session $session - */ - public function logOut(Session $session) + public function logOut(Session $session): void { $token = AccessToken::findValid($session->get('access_token')); - if ($token) { - $token->delete(); - } + $token?->delete(); $session->invalidate(); $session->regenerateToken(); diff --git a/framework/core/src/Http/SlugManager.php b/framework/core/src/Http/SlugManager.php index 3aa510e3d..9a6169683 100644 --- a/framework/core/src/Http/SlugManager.php +++ b/framework/core/src/Http/SlugManager.php @@ -9,24 +9,23 @@ namespace Flarum\Http; +use Flarum\Database\AbstractModel; use Illuminate\Support\Arr; class SlugManager { - protected $drivers = []; - - public function __construct(array $drivers) - { - $this->drivers = $drivers; + public function __construct( + protected array $drivers = [] + ) { } /** - * @template T of \Flarum\Database\AbstractModel + * @template T of AbstractModel * @param class-string<T> $resourceName * @return SlugDriverInterface<T> */ public function forResource(string $resourceName): SlugDriverInterface { - return Arr::get($this->drivers, $resourceName, null); + return Arr::get($this->drivers, $resourceName); } } diff --git a/framework/core/src/Http/UrlGenerator.php b/framework/core/src/Http/UrlGenerator.php index 4be39ab7d..036355ae6 100644 --- a/framework/core/src/Http/UrlGenerator.php +++ b/framework/core/src/Http/UrlGenerator.php @@ -13,33 +13,17 @@ use Flarum\Foundation\Application; class UrlGenerator { - /** - * @var array - */ - protected $routes = []; + protected array $routes = []; - /** - * @var Application - */ - protected $app; - - /** - * @param Application $app - */ - public function __construct(Application $app) - { - $this->app = $app; + public function __construct( + protected Application $app + ) { } /** * Register a named route collection for URL generation. - * - * @param string $key - * @param RouteCollection $routes - * @param string $prefix - * @return static */ - public function addCollection($key, RouteCollection $routes, $prefix = null) + public function addCollection(string $key, RouteCollection $routes, ?string $prefix = null): static { $this->routes[$key] = new RouteCollectionUrlGenerator( $this->app->url($prefix), @@ -50,12 +34,9 @@ class UrlGenerator } /** - * Retrieve an URL generator instance for the given named route collection. - * - * @param string $collection - * @return RouteCollectionUrlGenerator + * Retrieve a URL generator instance for the given named route collection. */ - public function to($collection) + public function to(string $collection): RouteCollectionUrlGenerator { return $this->routes[$collection]; } diff --git a/framework/core/src/Install/AdminUser.php b/framework/core/src/Install/AdminUser.php index f600f4951..f032c51d8 100644 --- a/framework/core/src/Install/AdminUser.php +++ b/framework/core/src/Install/AdminUser.php @@ -14,20 +14,15 @@ use Illuminate\Hashing\BcryptHasher; class AdminUser { - private $username; - private $password; - private $email; - - public function __construct($username, $password, $email) - { - $this->username = $username; - $this->password = $password; - $this->email = $email; - + public function __construct( + private readonly string $username, + private readonly string $password, + private readonly string $email + ) { $this->validate(); } - public function getUsername() + public function getUsername(): string { return $this->username; } @@ -43,7 +38,7 @@ class AdminUser ]; } - private function validate() + private function validate(): void { if (! filter_var($this->email, FILTER_VALIDATE_EMAIL)) { throw new ValidationFailed('You must enter a valid email.'); diff --git a/framework/core/src/Install/BaseUrl.php b/framework/core/src/Install/BaseUrl.php index 879949945..d6d0034a9 100644 --- a/framework/core/src/Install/BaseUrl.php +++ b/framework/core/src/Install/BaseUrl.php @@ -13,8 +13,7 @@ use Psr\Http\Message\UriInterface; final class BaseUrl { - /** @var string */ - private $normalized; + private string $normalized; private function __construct(string $baseUrl) { @@ -41,9 +40,6 @@ final class BaseUrl * * This uses the given mailbox name and our already normalized host name to * construct an email address. - * - * @param string $mailbox - * @return string */ public function toEmail(string $mailbox): string { diff --git a/framework/core/src/Install/Console/FileDataProvider.php b/framework/core/src/Install/Console/FileDataProvider.php index 356ebefef..4dd828407 100644 --- a/framework/core/src/Install/Console/FileDataProvider.php +++ b/framework/core/src/Install/Console/FileDataProvider.php @@ -19,12 +19,12 @@ use Symfony\Component\Yaml\Yaml; class FileDataProvider implements DataProviderInterface { - protected $debug = false; - protected $baseUrl = null; - protected $databaseConfiguration = []; - protected $adminUser = []; - protected $settings = []; - protected $extensions = []; + protected bool $debug = false; + protected ?string $baseUrl = null; + protected array $databaseConfiguration = []; + protected array $adminUser = []; + protected array $settings = []; + protected ?array $extensions = null; public function __construct(InputInterface $input) { @@ -44,12 +44,12 @@ class FileDataProvider implements DataProviderInterface } // Define configuration variables - $this->debug = $configuration['debug'] ?? false; - $this->baseUrl = $configuration['baseUrl'] ?? 'http://flarum.localhost'; - $this->databaseConfiguration = $configuration['databaseConfiguration'] ?? []; - $this->adminUser = $configuration['adminUser'] ?? []; - $this->settings = $configuration['settings'] ?? []; - $this->extensions = explode(',', $configuration['extensions'] ?? ''); + $this->debug = (bool) ($configuration['debug'] ?? false); + $this->baseUrl = (string) ($configuration['baseUrl'] ?? 'http://flarum.localhost'); + $this->databaseConfiguration = (array) ($configuration['databaseConfiguration'] ?? []); + $this->adminUser = (array) ($configuration['adminUser'] ?? []); + $this->settings = (array) ($configuration['settings'] ?? []); + $this->extensions = isset($configuration['extensions']) ? explode(',', (string) $configuration['extensions']) : null; } else { throw new Exception('Configuration file does not exist.'); } diff --git a/framework/core/src/Install/Console/InstallCommand.php b/framework/core/src/Install/Console/InstallCommand.php index e74d2cd0f..8c98eb376 100644 --- a/framework/core/src/Install/Console/InstallCommand.php +++ b/framework/core/src/Install/Console/InstallCommand.php @@ -13,32 +13,21 @@ use Flarum\Console\AbstractCommand; use Flarum\Install\Installation; use Flarum\Install\Pipeline; use Flarum\Install\Step; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputOption; class InstallCommand extends AbstractCommand { - /** - * @var Installation - */ - protected $installation; - - /** - * @var DataProviderInterface - */ - protected $dataSource; - - /** - * @param Installation $installation - */ - public function __construct(Installation $installation) - { - $this->installation = $installation; + protected DataProviderInterface $dataSource; + public function __construct( + protected Installation $installation + ) { parent::__construct(); } - protected function configure() + protected function configure(): void { $this ->setName('install') @@ -57,10 +46,7 @@ class InstallCommand extends AbstractCommand ); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $this->init(); @@ -77,9 +63,11 @@ class InstallCommand extends AbstractCommand return 1; } + + return Command::SUCCESS; } - protected function init() + protected function init(): void { if ($this->input->getOption('file')) { $this->dataSource = new FileDataProvider($this->input); @@ -90,7 +78,7 @@ class InstallCommand extends AbstractCommand } } - protected function install() + protected function install(): void { $pipeline = $this->dataSource->configure( $this->installation->configPath($this->input->getOption('config')) @@ -99,7 +87,7 @@ class InstallCommand extends AbstractCommand $this->runPipeline($pipeline); } - private function runPipeline(Pipeline $pipeline) + private function runPipeline(Pipeline $pipeline): void { $pipeline ->on('start', function (Step $step) { @@ -115,7 +103,7 @@ class InstallCommand extends AbstractCommand ->run(); } - protected function showProblems($problems) + protected function showProblems($problems): void { $this->output->writeln( '<error>Please fix the following problems before we can continue with the installation.</error>' diff --git a/framework/core/src/Install/Console/UserDataProvider.php b/framework/core/src/Install/Console/UserDataProvider.php index 2b30e6e3a..38cecf7fa 100644 --- a/framework/core/src/Install/Console/UserDataProvider.php +++ b/framework/core/src/Install/Console/UserDataProvider.php @@ -21,20 +21,13 @@ use Symfony\Component\Console\Question\Question; class UserDataProvider implements DataProviderInterface { - protected $input; + protected BaseUrl $baseUrl; - protected $output; - - protected $questionHelper; - - /** @var BaseUrl */ - protected $baseUrl; - - public function __construct(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper) - { - $this->input = $input; - $this->output = $output; - $this->questionHelper = $questionHelper; + public function __construct( + protected InputInterface $input, + protected OutputInterface $output, + protected QuestionHelper $questionHelper + ) { } public function configure(Installation $installation): Installation @@ -104,7 +97,7 @@ class UserDataProvider implements DataProviderInterface } } - private function getSettings() + private function getSettings(): array { $title = $this->ask('Forum title:'); @@ -115,14 +108,14 @@ class UserDataProvider implements DataProviderInterface ]; } - private function ask($question, $default = null) + private function ask($question, $default = null): mixed { $question = new Question("<question>$question</question> ", $default); return $this->questionHelper->ask($this->input, $this->output, $question); } - private function secret($question) + private function secret($question): mixed { $question = new Question("<question>$question</question> "); @@ -131,7 +124,7 @@ class UserDataProvider implements DataProviderInterface return $this->questionHelper->ask($this->input, $this->output, $question); } - private function validationError($message) + private function validationError($message): void { $this->output->writeln("<error>$message</error>"); $this->output->writeln('Please try again.'); diff --git a/framework/core/src/Install/Controller/IndexController.php b/framework/core/src/Install/Controller/IndexController.php index 642264291..6f742fefe 100644 --- a/framework/core/src/Install/Controller/IndexController.php +++ b/framework/core/src/Install/Controller/IndexController.php @@ -11,31 +11,19 @@ namespace Flarum\Install\Controller; use Flarum\Http\Controller\AbstractHtmlController; use Flarum\Install\Installation; +use Illuminate\Contracts\Support\Renderable; use Illuminate\Contracts\View\Factory; use Psr\Http\Message\ServerRequestInterface as Request; class IndexController extends AbstractHtmlController { - /** - * @var Factory - */ - protected $view; - - /** - * @var Installation - */ - protected $installation; - - public function __construct(Factory $view, Installation $installation) - { - $this->view = $view; - $this->installation = $installation; + public function __construct( + protected Factory $view, + protected Installation $installation + ) { } - /** - * @return \Illuminate\Contracts\Support\Renderable - */ - public function render(Request $request) + public function render(Request $request): Renderable|string { $view = $this->view->make('flarum.install::app')->with('title', 'Install Flarum'); diff --git a/framework/core/src/Install/Controller/InstallController.php b/framework/core/src/Install/Controller/InstallController.php index a226afb35..0d98540a4 100644 --- a/framework/core/src/Install/Controller/InstallController.php +++ b/framework/core/src/Install/Controller/InstallController.php @@ -27,38 +27,13 @@ use Psr\Http\Server\RequestHandlerInterface; class InstallController implements RequestHandlerInterface { - /** - * @var Installation - */ - protected $installation; - - /** - * @var SessionAuthenticator - */ - protected $authenticator; - - /** - * @var Rememberer - */ - protected $rememberer; - - /** - * InstallController constructor. - * @param Installation $installation - * @param SessionAuthenticator $authenticator - * @param Rememberer $rememberer - */ - public function __construct(Installation $installation, SessionAuthenticator $authenticator, Rememberer $rememberer) - { - $this->installation = $installation; - $this->authenticator = $authenticator; - $this->rememberer = $rememberer; + public function __construct( + protected Installation $installation, + protected SessionAuthenticator $authenticator, + protected Rememberer $rememberer + ) { } - /** - * @param Request $request - * @return ResponseInterface - */ public function handle(Request $request): ResponseInterface { $input = $request->getParsedBody(); @@ -120,8 +95,6 @@ class InstallController implements RequestHandlerInterface } /** - * @param array $input - * @return AdminUser * @throws ValidationFailed */ private function makeAdminUser(array $input): AdminUser diff --git a/framework/core/src/Install/DatabaseConfig.php b/framework/core/src/Install/DatabaseConfig.php index df6dcd1fa..49a5ee141 100644 --- a/framework/core/src/Install/DatabaseConfig.php +++ b/framework/core/src/Install/DatabaseConfig.php @@ -13,28 +13,19 @@ use Illuminate\Contracts\Support\Arrayable; class DatabaseConfig implements Arrayable { - private $driver; - private $host; - private $port; - private $database; - private $username; - private $password; - private $prefix; - - public function __construct($driver, $host, $port, $database, $username, $password, $prefix) - { - $this->driver = $driver; - $this->host = $host; - $this->port = $port; - $this->database = $database; - $this->username = $username; - $this->password = $password; - $this->prefix = $prefix; - + public function __construct( + private readonly string $driver, + private readonly string $host, + private readonly int $port, + private readonly string $database, + private readonly string $username, + private readonly string $password, + private readonly string $prefix + ) { $this->validate(); } - public function toArray() + public function toArray(): array { return [ 'driver' => $this->driver, @@ -52,7 +43,7 @@ class DatabaseConfig implements Arrayable ]; } - private function validate() + private function validate(): void { if (empty($this->driver)) { throw new ValidationFailed('Please specify a database driver.'); @@ -66,7 +57,7 @@ class DatabaseConfig implements Arrayable throw new ValidationFailed('Please specify the hostname of your database server.'); } - if (! is_int($this->port) || $this->port < 1 || $this->port > 65535) { + if ($this->port < 1 || $this->port > 65535) { throw new ValidationFailed('Please provide a valid port number between 1 and 65535.'); } @@ -74,18 +65,10 @@ class DatabaseConfig implements Arrayable throw new ValidationFailed('Please specify the database name.'); } - if (! is_string($this->database)) { - throw new ValidationFailed('The database name must be a non-empty string.'); - } - if (empty($this->username)) { throw new ValidationFailed('Please specify the username for accessing the database.'); } - if (! is_string($this->database)) { - throw new ValidationFailed('The username must be a non-empty string.'); - } - if (! empty($this->prefix)) { if (! preg_match('/^[\pL\pM\pN_]+$/u', $this->prefix)) { throw new ValidationFailed('The prefix may only contain characters and underscores.'); diff --git a/framework/core/src/Install/InstallServiceProvider.php b/framework/core/src/Install/InstallServiceProvider.php index 814c42847..3a86448e0 100644 --- a/framework/core/src/Install/InstallServiceProvider.php +++ b/framework/core/src/Install/InstallServiceProvider.php @@ -16,31 +16,21 @@ use Illuminate\Contracts\Container\Container; class InstallServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.install.routes', function () { return new RouteCollection; }); } - /** - * {@inheritdoc} - */ - public function boot(Container $container, RouteHandlerFactory $route) + public function boot(Container $container, RouteHandlerFactory $route): void { $this->loadViewsFrom(__DIR__.'/../../views/install', 'flarum.install'); $this->populateRoutes($container->make('flarum.install.routes'), $route); } - /** - * @param RouteCollection $routes - * @param RouteHandlerFactory $route - */ - protected function populateRoutes(RouteCollection $routes, RouteHandlerFactory $route) + protected function populateRoutes(RouteCollection $routes, RouteHandlerFactory $route): void { $routes->get( '/{path:.*}', diff --git a/framework/core/src/Install/Installation.php b/framework/core/src/Install/Installation.php index 243614da0..d233b0967 100644 --- a/framework/core/src/Install/Installation.php +++ b/framework/core/src/Install/Installation.php @@ -10,90 +10,79 @@ namespace Flarum\Install; use Flarum\Foundation\Paths; +use Illuminate\Database\ConnectionInterface; class Installation { - /** - * @var Paths - */ - private $paths; - - private $configPath; - private $debug = false; - private $baseUrl; - private $customSettings = []; - private $enabledExtensions = null; - - /** @var DatabaseConfig */ - private $dbConfig; - - /** @var AdminUser */ - private $adminUser; - - private $accessToken; + private string $configPath; + private bool $debug = false; + private BaseUrl $baseUrl; + private array $customSettings = []; + private ?array $enabledExtensions = null; + private DatabaseConfig $dbConfig; + private AdminUser $adminUser; + private ?string $accessToken = null; // A few instance variables to persist objects between steps. // Could also be local variables in build(), but this way // access in closures is easier. :) + private ConnectionInterface $db; - /** @var \Illuminate\Database\ConnectionInterface */ - private $db; - - public function __construct(Paths $paths) - { - $this->paths = $paths; + public function __construct( + private readonly Paths $paths + ) { } - public function configPath($path) + public function configPath(string $path): self { $this->configPath = $path; return $this; } - public function debugMode($flag) + public function debugMode(bool $flag): self { $this->debug = $flag; return $this; } - public function databaseConfig(DatabaseConfig $dbConfig) + public function databaseConfig(DatabaseConfig $dbConfig): self { $this->dbConfig = $dbConfig; return $this; } - public function baseUrl(BaseUrl $baseUrl) + public function baseUrl(BaseUrl $baseUrl): self { $this->baseUrl = $baseUrl; return $this; } - public function settings($settings) + public function settings(array $settings): self { $this->customSettings = $settings; return $this; } - public function extensions($enabledExtensions) + public function extensions(?array $enabledExtensions): self { $this->enabledExtensions = $enabledExtensions; return $this; } - public function adminUser(AdminUser $admin) + public function adminUser(AdminUser $admin): self { $this->adminUser = $admin; return $this; } - public function accessToken(string $token) + public function accessToken(string $token): self { $this->accessToken = $token; @@ -103,15 +92,17 @@ class Installation public function prerequisites(): Prerequisite\PrerequisiteInterface { return new Prerequisite\Composite( - new Prerequisite\PhpVersion('7.2.0'), + new Prerequisite\PhpVersion('8.1.0'), new Prerequisite\PhpExtensions([ 'dom', + 'fileinfo', 'gd', 'json', 'mbstring', 'openssl', 'pdo_mysql', 'tokenizer', + 'zip', ]), new Prerequisite\WritablePaths([ $this->paths->base, @@ -166,17 +157,17 @@ class Installation return $pipeline; } - private function getConfigPath() + private function getConfigPath(): string { return $this->paths->base.'/'.($this->configPath ?? 'config.php'); } - private function getAssetPath() + private function getAssetPath(): string { return $this->paths->public.'/assets'; } - private function getMigrationPath() + private function getMigrationPath(): string { return __DIR__.'/../../migrations'; } diff --git a/framework/core/src/Install/Installer.php b/framework/core/src/Install/Installer.php index 2765a1232..06da93f67 100644 --- a/framework/core/src/Install/Installer.php +++ b/framework/core/src/Install/Installer.php @@ -17,23 +17,16 @@ use Flarum\Http\Middleware as HttpMiddleware; use Flarum\Install\Console\InstallCommand; use Illuminate\Contracts\Container\Container; use Laminas\Stratigility\MiddlewarePipe; +use Psr\Http\Server\RequestHandlerInterface; class Installer implements AppInterface { - /** - * @var Container - */ - protected $container; - - public function __construct(Container $container) - { - $this->container = $container; + public function __construct( + protected Container $container + ) { } - /** - * @return \Psr\Http\Server\RequestHandlerInterface - */ - public function getRequestHandler() + public function getRequestHandler(): RequestHandlerInterface { $pipe = new MiddlewarePipe; $pipe->pipe(new HttpMiddleware\HandleErrors( @@ -53,7 +46,7 @@ class Installer implements AppInterface /** * @return \Symfony\Component\Console\Command\Command[] */ - public function getConsoleCommands() + public function getConsoleCommands(): array { return [ new InstallCommand( diff --git a/framework/core/src/Install/Pipeline.php b/framework/core/src/Install/Pipeline.php index 6701e0c2b..21a5fa571 100644 --- a/framework/core/src/Install/Pipeline.php +++ b/framework/core/src/Install/Pipeline.php @@ -17,38 +17,30 @@ class Pipeline /** * @var callable[] */ - private $steps; + private array $callbacks; + private SplStack $successfulSteps; - /** - * @var callable[] - */ - private $callbacks; - - /** - * @var SplStack - */ - private $successfulSteps; - - public function __construct(array $steps = []) - { - $this->steps = $steps; + public function __construct( + /** @var callable[] */ + private array $steps = [] + ) { } - public function pipe(callable $factory) + public function pipe(callable $factory): self { $this->steps[] = $factory; return $this; } - public function on($event, callable $callback) + public function on($event, callable $callback): self { $this->callbacks[$event] = $callback; return $this; } - public function run() + public function run(): void { $this->successfulSteps = new SplStack; @@ -64,12 +56,11 @@ class Pipeline } /** - * @param callable $factory + * @param callable(): Step $factory * @throws StepFailed */ - private function runStep(callable $factory) + private function runStep(callable $factory): void { - /** @var Step $step */ $step = $factory(); $this->fireCallbacks('start', $step); @@ -86,7 +77,7 @@ class Pipeline } } - private function revertReversibleSteps() + private function revertReversibleSteps(): void { foreach ($this->successfulSteps as $step) { if ($step instanceof ReversibleStep) { @@ -97,7 +88,7 @@ class Pipeline } } - private function fireCallbacks($event, Step $step) + private function fireCallbacks($event, Step $step): void { if (isset($this->callbacks[$event])) { ($this->callbacks[$event])($step); diff --git a/framework/core/src/Install/Prerequisite/Composite.php b/framework/core/src/Install/Prerequisite/Composite.php index 77b16044a..88a2c31f5 100644 --- a/framework/core/src/Install/Prerequisite/Composite.php +++ b/framework/core/src/Install/Prerequisite/Composite.php @@ -16,7 +16,7 @@ class Composite implements PrerequisiteInterface /** * @var PrerequisiteInterface[] */ - protected $prerequisites = []; + protected array $prerequisites = []; public function __construct(PrerequisiteInterface $first) { diff --git a/framework/core/src/Install/Prerequisite/PhpExtensions.php b/framework/core/src/Install/Prerequisite/PhpExtensions.php index 10a1b1571..1e4cbbe0f 100644 --- a/framework/core/src/Install/Prerequisite/PhpExtensions.php +++ b/framework/core/src/Install/Prerequisite/PhpExtensions.php @@ -13,11 +13,9 @@ use Illuminate\Support\Collection; class PhpExtensions implements PrerequisiteInterface { - protected $extensions; - - public function __construct(array $extensions) - { - $this->extensions = $extensions; + public function __construct( + protected array $extensions + ) { } public function problems(): Collection diff --git a/framework/core/src/Install/Prerequisite/PhpVersion.php b/framework/core/src/Install/Prerequisite/PhpVersion.php index 6a38a279b..daa457879 100644 --- a/framework/core/src/Install/Prerequisite/PhpVersion.php +++ b/framework/core/src/Install/Prerequisite/PhpVersion.php @@ -13,11 +13,9 @@ use Illuminate\Support\Collection; class PhpVersion implements PrerequisiteInterface { - protected $minVersion; - - public function __construct($minVersion) - { - $this->minVersion = $minVersion; + public function __construct( + protected string $minVersion + ) { } public function problems(): Collection diff --git a/framework/core/src/Install/Prerequisite/PrerequisiteInterface.php b/framework/core/src/Install/Prerequisite/PrerequisiteInterface.php index 5916d4484..14bd884a1 100644 --- a/framework/core/src/Install/Prerequisite/PrerequisiteInterface.php +++ b/framework/core/src/Install/Prerequisite/PrerequisiteInterface.php @@ -19,8 +19,6 @@ interface PrerequisiteInterface * If everything is okay, this method should return an empty Collection * instance. When problems are detected, it should return a Collection of * arrays, each having at least a "message" and optionally a "detail" key. - * - * @return Collection */ public function problems(): Collection; } diff --git a/framework/core/src/Install/Prerequisite/WritablePaths.php b/framework/core/src/Install/Prerequisite/WritablePaths.php index 9c4357d19..b5fb8a86d 100644 --- a/framework/core/src/Install/Prerequisite/WritablePaths.php +++ b/framework/core/src/Install/Prerequisite/WritablePaths.php @@ -14,12 +14,8 @@ use Illuminate\Support\Str; class WritablePaths implements PrerequisiteInterface { - /** - * @var Collection - */ - private $paths; - - private $wildcards = []; + private Collection $paths; + private array $wildcards = []; public function __construct(array $paths) { diff --git a/framework/core/src/Install/ReversibleStep.php b/framework/core/src/Install/ReversibleStep.php index 0189bbf3e..6002b865b 100644 --- a/framework/core/src/Install/ReversibleStep.php +++ b/framework/core/src/Install/ReversibleStep.php @@ -11,5 +11,5 @@ namespace Flarum\Install; interface ReversibleStep extends Step { - public function revert(); + public function revert(): void; } diff --git a/framework/core/src/Install/Step.php b/framework/core/src/Install/Step.php index d1cea6b5b..efa0e70be 100644 --- a/framework/core/src/Install/Step.php +++ b/framework/core/src/Install/Step.php @@ -13,10 +13,8 @@ interface Step { /** * A one-line status message summarizing what's happening in this step. - * - * @return string */ - public function getMessage(); + public function getMessage(): string; /** * Do the work that constitutes this step. @@ -24,8 +22,7 @@ interface Step * This method should raise a `StepFailed` exception whenever something goes * wrong that should result in the entire installation being reverted. * - * @return void * @throws StepFailed */ - public function run(); + public function run(): void; } diff --git a/framework/core/src/Install/Steps/ConnectToDatabase.php b/framework/core/src/Install/Steps/ConnectToDatabase.php index f2794252f..d06907022 100644 --- a/framework/core/src/Install/Steps/ConnectToDatabase.php +++ b/framework/core/src/Install/Steps/ConnectToDatabase.php @@ -9,6 +9,7 @@ namespace Flarum\Install\Steps; +use Closure; use Flarum\Install\DatabaseConfig; use Flarum\Install\Step; use Illuminate\Database\Connectors\MySqlConnector; @@ -18,21 +19,18 @@ use RangeException; class ConnectToDatabase implements Step { - private $dbConfig; - private $store; - - public function __construct(DatabaseConfig $dbConfig, callable $store) - { - $this->dbConfig = $dbConfig; - $this->store = $store; + public function __construct( + private readonly DatabaseConfig $dbConfig, + private readonly Closure $store + ) { } - public function getMessage() + public function getMessage(): string { return 'Connecting to database'; } - public function run() + public function run(): void { $config = $this->dbConfig->toArray(); $pdo = (new MySqlConnector)->connect($config); diff --git a/framework/core/src/Install/Steps/CreateAdminUser.php b/framework/core/src/Install/Steps/CreateAdminUser.php index f80d30a8c..1f94217ca 100644 --- a/framework/core/src/Install/Steps/CreateAdminUser.php +++ b/framework/core/src/Install/Steps/CreateAdminUser.php @@ -17,34 +17,19 @@ use Illuminate\Database\ConnectionInterface; class CreateAdminUser implements Step { - /** - * @var ConnectionInterface - */ - private $database; - - /** - * @var AdminUser - */ - private $admin; - - /** - * @var string|null - */ - private $accessToken; - - public function __construct(ConnectionInterface $database, AdminUser $admin, string $accessToken = null) - { - $this->database = $database; - $this->admin = $admin; - $this->accessToken = $accessToken; + public function __construct( + private readonly ConnectionInterface $database, + private readonly AdminUser $admin, + private readonly ?string $accessToken = null + ) { } - public function getMessage() + public function getMessage(): string { return 'Creating admin user '.$this->admin->getUsername(); } - public function run() + public function run(): void { $uid = $this->database->table('users')->insertGetId( $this->admin->getAttributes() diff --git a/framework/core/src/Install/Steps/EnableBundledExtensions.php b/framework/core/src/Install/Steps/EnableBundledExtensions.php index b26ec5087..e8e11af19 100644 --- a/framework/core/src/Install/Steps/EnableBundledExtensions.php +++ b/framework/core/src/Install/Steps/EnableBundledExtensions.php @@ -24,7 +24,7 @@ use League\Flysystem\Filesystem; class EnableBundledExtensions implements Step { - const EXTENSION_WHITELIST = [ + public const EXTENSION_WHITELIST = [ 'flarum-approval', 'flarum-bbcode', 'flarum-emoji', @@ -42,44 +42,27 @@ class EnableBundledExtensions implements Step ]; /** - * @var ConnectionInterface + * @var string[] */ - private $database; + private array $enabledExtensions; - /** - * @var string - */ - private $vendorPath; + private ?Migrator $migrator; - /** - * @var string - */ - private $assetPath; - - /** - * @var string[]|null - */ - private $enabledExtensions; - - /** - * @var Migrator|null - */ - private $migrator; - - public function __construct(ConnectionInterface $database, $vendorPath, $assetPath, $enabledExtensions = null) - { - $this->database = $database; - $this->vendorPath = $vendorPath; - $this->assetPath = $assetPath; + public function __construct( + private readonly ConnectionInterface $database, + private readonly string $vendorPath, + private readonly string $assetPath, + ?array $enabledExtensions = null + ) { $this->enabledExtensions = $enabledExtensions ?? self::EXTENSION_WHITELIST; } - public function getMessage() + public function getMessage(): string { return 'Enabling bundled extensions'; } - public function run() + public function run(): void { $extensions = ExtensionManager::resolveExtensionOrder($this->loadExtensions()->all())['valid']; @@ -98,9 +81,9 @@ class EnableBundledExtensions implements Step } /** - * @return \Illuminate\Support\Collection<Extension> + * @return Collection<Extension> */ - private function loadExtensions() + private function loadExtensions(): Collection { $json = file_get_contents("$this->vendorPath/composer/installed.json"); $installed = json_decode($json, true); diff --git a/framework/core/src/Install/Steps/PublishAssets.php b/framework/core/src/Install/Steps/PublishAssets.php index 4b321a1a0..19755816f 100644 --- a/framework/core/src/Install/Steps/PublishAssets.php +++ b/framework/core/src/Install/Steps/PublishAssets.php @@ -14,28 +14,18 @@ use Illuminate\Filesystem\Filesystem; class PublishAssets implements ReversibleStep { - /** - * @var string - */ - private $vendorPath; - - /** - * @var string - */ - private $assetPath; - - public function __construct($vendorPath, $assetPath) - { - $this->vendorPath = $vendorPath; - $this->assetPath = $assetPath; + public function __construct( + private readonly string $vendorPath, + private readonly string $assetPath + ) { } - public function getMessage() + public function getMessage(): string { return 'Publishing all assets'; } - public function run() + public function run(): void { (new Filesystem)->copyDirectory( "$this->vendorPath/components/font-awesome/webfonts", @@ -43,12 +33,12 @@ class PublishAssets implements ReversibleStep ); } - public function revert() + public function revert(): void { (new Filesystem)->deleteDirectory($this->targetPath()); } - private function targetPath() + private function targetPath(): string { return "$this->assetPath/fonts"; } diff --git a/framework/core/src/Install/Steps/RunMigrations.php b/framework/core/src/Install/Steps/RunMigrations.php index 32ee13b40..19d25c25c 100644 --- a/framework/core/src/Install/Steps/RunMigrations.php +++ b/framework/core/src/Install/Steps/RunMigrations.php @@ -17,28 +17,18 @@ use Illuminate\Filesystem\Filesystem; class RunMigrations implements Step { - /** - * @var ConnectionInterface - */ - private $database; - - /** - * @var string - */ - private $path; - - public function __construct(ConnectionInterface $database, $path) - { - $this->database = $database; - $this->path = $path; + public function __construct( + private readonly ConnectionInterface $database, + private readonly string $path + ) { } - public function getMessage() + public function getMessage(): string { return 'Running migrations'; } - public function run() + public function run(): void { $migrator = $this->getMigrator(); @@ -46,7 +36,7 @@ class RunMigrations implements Step $migrator->run($this->path); } - private function getMigrator() + private function getMigrator(): Migrator { $repository = new DatabaseMigrationRepository( $this->database, diff --git a/framework/core/src/Install/Steps/StoreConfig.php b/framework/core/src/Install/Steps/StoreConfig.php index e878e6013..f6ec0fc9f 100644 --- a/framework/core/src/Install/Steps/StoreConfig.php +++ b/framework/core/src/Install/Steps/StoreConfig.php @@ -15,29 +15,20 @@ use Flarum\Install\ReversibleStep; class StoreConfig implements ReversibleStep { - private $debugMode; - - private $dbConfig; - - private $baseUrl; - - private $configFile; - - public function __construct($debugMode, DatabaseConfig $dbConfig, BaseUrl $baseUrl, $configFile) - { - $this->debugMode = $debugMode; - $this->dbConfig = $dbConfig; - $this->baseUrl = $baseUrl; - - $this->configFile = $configFile; + public function __construct( + private readonly bool $debugMode, + private readonly DatabaseConfig $dbConfig, + private readonly BaseUrl $baseUrl, + private readonly string $configFile + ) { } - public function getMessage() + public function getMessage(): string { return 'Writing config file'; } - public function run() + public function run(): void { file_put_contents( $this->configFile, @@ -45,12 +36,12 @@ class StoreConfig implements ReversibleStep ); } - public function revert() + public function revert(): void { @unlink($this->configFile); } - private function buildConfig() + private function buildConfig(): array { return [ 'debug' => $this->debugMode, @@ -64,7 +55,7 @@ class StoreConfig implements ReversibleStep ]; } - private function getPathsConfig() + private function getPathsConfig(): array { return [ 'api' => 'api', diff --git a/framework/core/src/Install/Steps/WriteSettings.php b/framework/core/src/Install/Steps/WriteSettings.php index c23ca005d..28dd0c70e 100644 --- a/framework/core/src/Install/Steps/WriteSettings.php +++ b/framework/core/src/Install/Steps/WriteSettings.php @@ -16,28 +16,18 @@ use Illuminate\Database\ConnectionInterface; class WriteSettings implements Step { - /** - * @var ConnectionInterface - */ - private $database; - - /** - * @var array - */ - private $custom; - - public function __construct(ConnectionInterface $database, array $custom) - { - $this->database = $database; - $this->custom = $custom; + public function __construct( + private readonly ConnectionInterface $database, + private readonly array $custom + ) { } - public function getMessage() + public function getMessage(): string { return 'Writing default settings'; } - public function run() + public function run(): void { $repo = new DatabaseSettingsRepository($this->database); @@ -48,12 +38,12 @@ class WriteSettings implements Step } } - private function getSettings() + private function getSettings(): array { return $this->custom + $this->getDefaults(); } - private function getDefaults() + private function getDefaults(): array { return [ 'allow_hide_own_posts' => 'reply', diff --git a/framework/core/src/Locale/LocaleManager.php b/framework/core/src/Locale/LocaleManager.php index 7f011f2f0..36e14d749 100644 --- a/framework/core/src/Locale/LocaleManager.php +++ b/framework/core/src/Locale/LocaleManager.php @@ -14,26 +14,14 @@ use Symfony\Component\Translation\MessageCatalogueInterface; class LocaleManager { - /** - * @var Translator - */ - protected $translator; + protected array $locales = []; + protected array $js = []; + protected array $css = []; - protected $locales = []; - - protected $js = []; - - protected $css = []; - - /** - * @var string - */ - protected $cacheDir; - - public function __construct(Translator $translator, string $cacheDir = null) - { - $this->translator = $translator; - $this->cacheDir = $cacheDir; + public function __construct( + protected Translator $translator, + protected ?string $cacheDir = null + ) { } public function getLocale(): string @@ -41,12 +29,12 @@ class LocaleManager return $this->translator->getLocale(); } - public function setLocale(string $locale) + public function setLocale(string $locale): void { $this->translator->setLocale($locale); } - public function addLocale(string $locale, string $name) + public function addLocale(string $locale, string $name): void { $this->locales[$locale] = $name; } @@ -61,7 +49,7 @@ class LocaleManager return isset($this->locales[$locale]); } - public function addTranslations(string $locale, $file, string $module = null) + public function addTranslations(string $locale, $file, string $module = null): void { $prefix = $module ? $module.'::' : ''; @@ -72,7 +60,7 @@ class LocaleManager $this->translator->addResource('prefixed_yaml', compact('file', 'prefix'), $locale, $domain); } - public function addJsFile(string $locale, string $js) + public function addJsFile(string $locale, string $js): void { $this->js[$locale][] = $js; } @@ -90,7 +78,7 @@ class LocaleManager return $files; } - public function addCssFile(string $locale, string $css) + public function addCssFile(string $locale, string $css): void { $this->css[$locale][] = $css; } @@ -113,12 +101,12 @@ class LocaleManager return $this->translator; } - public function setTranslator(Translator $translator) + public function setTranslator(Translator $translator): void { $this->translator = $translator; } - public function clearCache() + public function clearCache(): void { if ($this->cacheDir) { array_map('unlink', glob($this->cacheDir.'/*')); diff --git a/framework/core/src/Locale/LocaleServiceProvider.php b/framework/core/src/Locale/LocaleServiceProvider.php index f4b785ff5..4ab4f258f 100644 --- a/framework/core/src/Locale/LocaleServiceProvider.php +++ b/framework/core/src/Locale/LocaleServiceProvider.php @@ -14,14 +14,11 @@ use Flarum\Foundation\Paths; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Translation\Translator as TranslatorContract; -use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslatorInterface; class LocaleServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton(LocaleManager::class, function (Container $container) { $locales = new LocaleManager( @@ -54,6 +51,7 @@ class LocaleServiceProvider extends AbstractServiceProvider $this->container->alias('translator', Translator::class); $this->container->alias('translator', TranslatorContract::class); + $this->container->alias('translator', SymfonyTranslatorInterface::class); $this->container->alias('translator', TranslatorInterface::class); } diff --git a/framework/core/src/Locale/PrefixedYamlFileLoader.php b/framework/core/src/Locale/PrefixedYamlFileLoader.php index 2e105439c..a320fe912 100644 --- a/framework/core/src/Locale/PrefixedYamlFileLoader.php +++ b/framework/core/src/Locale/PrefixedYamlFileLoader.php @@ -10,13 +10,11 @@ namespace Flarum\Locale; use Symfony\Component\Translation\Loader\YamlFileLoader; +use Symfony\Component\Translation\MessageCatalogue; class PrefixedYamlFileLoader extends YamlFileLoader { - /** - * {@inheritdoc} - */ - public function load($resource, $locale, $domain = 'messages') + public function load($resource, $locale, $domain = 'messages'): MessageCatalogue { $catalogue = parent::load($resource['file'], $locale, $domain); diff --git a/framework/core/src/Locale/Translator.php b/framework/core/src/Locale/Translator.php index dce685a4c..a89403843 100644 --- a/framework/core/src/Locale/Translator.php +++ b/framework/core/src/Locale/Translator.php @@ -9,29 +9,25 @@ namespace Flarum\Locale; -use Illuminate\Contracts\Translation\Translator as TranslatorContract; use Symfony\Component\Translation\MessageCatalogueInterface; use Symfony\Component\Translation\Translator as BaseTranslator; -class Translator extends BaseTranslator implements TranslatorContract +class Translator extends BaseTranslator implements TranslatorInterface { const REFERENCE_REGEX = '/^=>\s*([a-z0-9_\-\.]+)$/i'; - public function get($key, array $replace = [], $locale = null) + public function get($key, array $replace = [], $locale = null): string { return $this->trans($key, $replace, null, $locale); } - public function choice($key, $number, array $replace = [], $locale = null) + public function choice($key, $number, array $replace = [], $locale = null): string { // Symfony's translator uses ICU MessageFormat, which pluralizes based on arguments. return $this->trans($key, $replace, null, $locale); } - /** - * {@inheritdoc} - */ - public function getCatalogue($locale = null) + public function getCatalogue($locale = null): MessageCatalogueInterface { if (null === $locale) { $locale = $this->getLocale(); @@ -55,10 +51,7 @@ class Translator extends BaseTranslator implements TranslatorContract return $catalogue; } - /** - * @param MessageCatalogueInterface $catalogue - */ - private function parseCatalogue(MessageCatalogueInterface $catalogue) + private function parseCatalogue(MessageCatalogueInterface $catalogue): void { foreach ($catalogue->all() as $domain => $messages) { foreach ($messages as $id => $translation) { @@ -69,13 +62,7 @@ class Translator extends BaseTranslator implements TranslatorContract } } - /** - * @param MessageCatalogueInterface $catalogue - * @param string $id - * @param string $domain - * @return string - */ - private function getTranslation(MessageCatalogueInterface $catalogue, $id, $domain) + private function getTranslation(MessageCatalogueInterface $catalogue, string $id, string $domain): string { $translation = $catalogue->get($id, $domain); diff --git a/framework/core/src/Locale/TranslatorInterface.php b/framework/core/src/Locale/TranslatorInterface.php new file mode 100644 index 000000000..0453dab52 --- /dev/null +++ b/framework/core/src/Locale/TranslatorInterface.php @@ -0,0 +1,17 @@ +<?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\Locale; + +use Illuminate\Contracts\Translation\Translator; +use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslatorInterface; + +interface TranslatorInterface extends Translator, SymfonyTranslatorInterface +{ +} diff --git a/framework/core/src/Mail/Job/SendRawEmailJob.php b/framework/core/src/Mail/Job/SendRawEmailJob.php index 9eebc35e6..73ee07907 100644 --- a/framework/core/src/Mail/Job/SendRawEmailJob.php +++ b/framework/core/src/Mail/Job/SendRawEmailJob.php @@ -15,18 +15,14 @@ use Illuminate\Mail\Message; class SendRawEmailJob extends AbstractJob { - private $email; - private $subject; - private $body; - - public function __construct(string $email, string $subject, string $body) - { - $this->email = $email; - $this->subject = $subject; - $this->body = $body; + public function __construct( + private readonly string $email, + private readonly string $subject, + private readonly string $body + ) { } - public function handle(Mailer $mailer) + public function handle(Mailer $mailer): void { $mailer->raw($this->body, function (Message $message) { $message->to($this->email); diff --git a/framework/core/src/Mail/LogDriver.php b/framework/core/src/Mail/LogDriver.php index 276fee895..45dbd9b3d 100644 --- a/framework/core/src/Mail/LogDriver.php +++ b/framework/core/src/Mail/LogDriver.php @@ -17,14 +17,9 @@ use Swift_Transport; class LogDriver implements DriverInterface { - /** - * @var LoggerInterface - */ - private $logger; - - public function __construct(LoggerInterface $logger) - { - $this->logger = $logger; + public function __construct( + private readonly LoggerInterface $logger + ) { } public function availableSettings(): array diff --git a/framework/core/src/Mail/MailServiceProvider.php b/framework/core/src/Mail/MailServiceProvider.php index 875c13a57..811ce2573 100644 --- a/framework/core/src/Mail/MailServiceProvider.php +++ b/framework/core/src/Mail/MailServiceProvider.php @@ -19,7 +19,7 @@ use Swift_Mailer; class MailServiceProvider extends AbstractServiceProvider { - public function register() + public function register(): void { $this->container->singleton('mail.supported_drivers', function () { return [ diff --git a/framework/core/src/Notification/Blueprint/BlueprintInterface.php b/framework/core/src/Notification/Blueprint/BlueprintInterface.php index caae87e41..6a98e30e3 100644 --- a/framework/core/src/Notification/Blueprint/BlueprintInterface.php +++ b/framework/core/src/Notification/Blueprint/BlueprintInterface.php @@ -21,36 +21,28 @@ interface BlueprintInterface { /** * Get the user that sent the notification. - * - * @return User|null */ - public function getFromUser(); + public function getFromUser(): ?User; /** * Get the model that is the subject of this activity. - * - * @return AbstractModel|null */ - public function getSubject(); + public function getSubject(): ?AbstractModel; /** * Get the data to be stored in the notification. - * - * @return mixed */ - public function getData(); + public function getData(): mixed; /** * Get the serialized type of this activity. - * - * @return string */ - public static function getType(); + public static function getType(): string; /** * Get the name of the model class for the subject of this activity. * - * @return string + * @return class-string<AbstractModel> */ - public static function getSubjectModel(); + public static function getSubjectModel(): string; } diff --git a/framework/core/src/Notification/Blueprint/DiscussionRenamedBlueprint.php b/framework/core/src/Notification/Blueprint/DiscussionRenamedBlueprint.php index 181d298ad..2c34e1554 100644 --- a/framework/core/src/Notification/Blueprint/DiscussionRenamedBlueprint.php +++ b/framework/core/src/Notification/Blueprint/DiscussionRenamedBlueprint.php @@ -9,60 +9,39 @@ namespace Flarum\Notification\Blueprint; +use Flarum\Database\AbstractModel; use Flarum\Discussion\Discussion; use Flarum\Post\DiscussionRenamedPost; +use Flarum\User\User; class DiscussionRenamedBlueprint implements BlueprintInterface { - /** - * @var \Flarum\Post\DiscussionRenamedPost - */ - protected $post; - - /** - * @param DiscussionRenamedPost $post - */ - public function __construct(DiscussionRenamedPost $post) - { - $this->post = $post; + public function __construct( + protected DiscussionRenamedPost $post + ) { } - /** - * {@inheritdoc} - */ - public function getFromUser() + public function getFromUser(): ?User { return $this->post->user; } - /** - * {@inheritdoc} - */ - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->post->discussion; } - /** - * {@inheritdoc} - */ - public function getData() + public function getData(): array { return ['postNumber' => (int) $this->post->number]; } - /** - * {@inheritdoc} - */ - public static function getType() + public static function getType(): string { return 'discussionRenamed'; } - /** - * {@inheritdoc} - */ - public static function getSubjectModel() + public static function getSubjectModel(): string { return Discussion::class; } diff --git a/framework/core/src/Notification/Command/DeleteAllNotifications.php b/framework/core/src/Notification/Command/DeleteAllNotifications.php index 934e60665..2f001fb95 100644 --- a/framework/core/src/Notification/Command/DeleteAllNotifications.php +++ b/framework/core/src/Notification/Command/DeleteAllNotifications.php @@ -13,18 +13,8 @@ use Flarum\User\User; class DeleteAllNotifications { - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @param User $actor The user performing the action. - */ - public function __construct(User $actor) - { - $this->actor = $actor; + public function __construct( + public User $actor + ) { } } diff --git a/framework/core/src/Notification/Command/DeleteAllNotificationsHandler.php b/framework/core/src/Notification/Command/DeleteAllNotificationsHandler.php index a8d321694..16bda18c6 100644 --- a/framework/core/src/Notification/Command/DeleteAllNotificationsHandler.php +++ b/framework/core/src/Notification/Command/DeleteAllNotificationsHandler.php @@ -11,37 +11,18 @@ namespace Flarum\Notification\Command; use Flarum\Notification\Event\DeletedAll; use Flarum\Notification\NotificationRepository; -use Flarum\User\Exception\NotAuthenticatedException; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Support\Carbon; class DeleteAllNotificationsHandler { - /** - * @var NotificationRepository - */ - protected $notifications; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param NotificationRepository $notifications - * @param Dispatcher $events - */ - public function __construct(NotificationRepository $notifications, Dispatcher $events) - { - $this->notifications = $notifications; - $this->events = $events; + public function __construct( + protected NotificationRepository $notifications, + protected Dispatcher $events + ) { } - /** - * @param DeleteAllNotifications $command - * @throws NotAuthenticatedException - */ - public function handle(DeleteAllNotifications $command) + public function handle(DeleteAllNotifications $command): void { $actor = $command->actor; diff --git a/framework/core/src/Notification/Command/ReadAllNotifications.php b/framework/core/src/Notification/Command/ReadAllNotifications.php index 764594ee2..848a7ce53 100644 --- a/framework/core/src/Notification/Command/ReadAllNotifications.php +++ b/framework/core/src/Notification/Command/ReadAllNotifications.php @@ -13,18 +13,8 @@ use Flarum\User\User; class ReadAllNotifications { - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @param User $actor The user performing the action. - */ - public function __construct(User $actor) - { - $this->actor = $actor; + public function __construct( + public User $actor + ) { } } diff --git a/framework/core/src/Notification/Command/ReadAllNotificationsHandler.php b/framework/core/src/Notification/Command/ReadAllNotificationsHandler.php index e5914dfb7..b90c30587 100644 --- a/framework/core/src/Notification/Command/ReadAllNotificationsHandler.php +++ b/framework/core/src/Notification/Command/ReadAllNotificationsHandler.php @@ -16,31 +16,16 @@ use Illuminate\Support\Carbon; class ReadAllNotificationsHandler { - /** - * @var NotificationRepository - */ - protected $notifications; - - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param NotificationRepository $notifications - * @param Dispatcher $events - */ - public function __construct(NotificationRepository $notifications, Dispatcher $events) - { - $this->notifications = $notifications; - $this->events = $events; + public function __construct( + protected NotificationRepository $notifications, + protected Dispatcher $events + ) { } /** - * @param ReadAllNotifications $command - * @throws \Flarum\User\Exception\PermissionDeniedException + * @throws \Flarum\User\Exception\NotAuthenticatedException */ - public function handle(ReadAllNotifications $command) + public function handle(ReadAllNotifications $command): void { $actor = $command->actor; diff --git a/framework/core/src/Notification/Command/ReadNotification.php b/framework/core/src/Notification/Command/ReadNotification.php index d7ee58fe2..8b365ea93 100644 --- a/framework/core/src/Notification/Command/ReadNotification.php +++ b/framework/core/src/Notification/Command/ReadNotification.php @@ -13,27 +13,9 @@ use Flarum\User\User; class ReadNotification { - /** - * The ID of the notification to mark as read. - * - * @var int - */ - public $notificationId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @param int $notificationId The ID of the notification to mark as read. - * @param User $actor The user performing the action. - */ - public function __construct($notificationId, User $actor) - { - $this->notificationId = $notificationId; - $this->actor = $actor; + public function __construct( + public int $notificationId, + public User $actor + ) { } } diff --git a/framework/core/src/Notification/Command/ReadNotificationHandler.php b/framework/core/src/Notification/Command/ReadNotificationHandler.php index a39a4784f..d1bde8668 100644 --- a/framework/core/src/Notification/Command/ReadNotificationHandler.php +++ b/framework/core/src/Notification/Command/ReadNotificationHandler.php @@ -16,33 +16,26 @@ use Illuminate\Contracts\Events\Dispatcher; class ReadNotificationHandler { - /** - * @var Dispatcher - */ - protected $events; - - /** - * @param Dispatcher $events - */ - public function __construct(Dispatcher $events) - { - $this->events = $events; + public function __construct( + protected Dispatcher $events + ) { } /** - * @param ReadNotification $command - * @return \Flarum\Notification\Notification - * @throws \Flarum\User\Exception\PermissionDeniedException + * @throws \Flarum\User\Exception\NotAuthenticatedException */ - public function handle(ReadNotification $command) + public function handle(ReadNotification $command): Notification { $actor = $command->actor; $actor->assertRegistered(); - $notification = Notification::where('user_id', $actor->id)->findOrFail($command->notificationId); + /** @var Notification $notification */ + $notification = Notification::query() + ->where('user_id', $actor->id) + ->findOrFail($command->notificationId); - Notification::where([ + Notification::query()->where([ 'user_id' => $actor->id, 'type' => $notification->type, 'subject_id' => $notification->subject_id diff --git a/framework/core/src/Notification/Driver/AlertNotificationDriver.php b/framework/core/src/Notification/Driver/AlertNotificationDriver.php index 69f03ac95..d69c1d85d 100644 --- a/framework/core/src/Notification/Driver/AlertNotificationDriver.php +++ b/framework/core/src/Notification/Driver/AlertNotificationDriver.php @@ -16,19 +16,11 @@ use Illuminate\Contracts\Queue\Queue; class AlertNotificationDriver implements NotificationDriverInterface { - /** - * @var Queue - */ - private $queue; - - public function __construct(Queue $queue) - { - $this->queue = $queue; + public function __construct( + private readonly Queue $queue + ) { } - /** - * {@inheritDoc} - */ public function send(BlueprintInterface $blueprint, array $users): void { if (count($users)) { @@ -36,14 +28,11 @@ class AlertNotificationDriver implements NotificationDriverInterface } } - /** - * {@inheritdoc} - */ public function registerType(string $blueprintClass, array $driversEnabledByDefault): void { User::registerPreference( User::getNotificationPreferenceKey($blueprintClass::getType(), 'alert'), - 'boolval', + boolval(...), in_array('alert', $driversEnabledByDefault) ); } diff --git a/framework/core/src/Notification/Driver/EmailNotificationDriver.php b/framework/core/src/Notification/Driver/EmailNotificationDriver.php index d25620953..f0ea53344 100644 --- a/framework/core/src/Notification/Driver/EmailNotificationDriver.php +++ b/framework/core/src/Notification/Driver/EmailNotificationDriver.php @@ -18,19 +18,11 @@ use ReflectionClass; class EmailNotificationDriver implements NotificationDriverInterface { - /** - * @var Queue - */ - private $queue; - - public function __construct(Queue $queue) - { - $this->queue = $queue; + public function __construct( + private readonly Queue $queue + ) { } - /** - * {@inheritDoc} - */ public function send(BlueprintInterface $blueprint, array $users): void { if ($blueprint instanceof MailableInterface) { @@ -41,10 +33,9 @@ class EmailNotificationDriver implements NotificationDriverInterface /** * Mail a notification to a list of users. * - * @param MailableInterface&BlueprintInterface $blueprint * @param User[] $recipients */ - protected function mailNotifications(MailableInterface $blueprint, array $recipients) + protected function mailNotifications(MailableInterface&BlueprintInterface $blueprint, array $recipients): void { foreach ($recipients as $user) { if ($user->shouldEmail($blueprint::getType())) { @@ -53,15 +44,12 @@ class EmailNotificationDriver implements NotificationDriverInterface } } - /** - * {@inheritdoc} - */ public function registerType(string $blueprintClass, array $driversEnabledByDefault): void { if ((new ReflectionClass($blueprintClass))->implementsInterface(MailableInterface::class)) { User::registerPreference( User::getNotificationPreferenceKey($blueprintClass::getType(), 'email'), - 'boolval', + boolval(...), in_array('email', $driversEnabledByDefault) ); } diff --git a/framework/core/src/Notification/Driver/NotificationDriverInterface.php b/framework/core/src/Notification/Driver/NotificationDriverInterface.php index b2fb24bda..fe0e21e4a 100644 --- a/framework/core/src/Notification/Driver/NotificationDriverInterface.php +++ b/framework/core/src/Notification/Driver/NotificationDriverInterface.php @@ -17,18 +17,14 @@ interface NotificationDriverInterface /** * Conditionally sends a notification to users, generally using a queue. * - * @param BlueprintInterface $blueprint * @param User[] $users - * @return void */ public function send(BlueprintInterface $blueprint, array $users): void; /** * Logic for registering a notification type, generally used for adding a user preference. * - * @param string $blueprintClass - * @param array $driversEnabledByDefault - * @return void + * @param class-string<BlueprintInterface> $blueprintClass */ public function registerType(string $blueprintClass, array $driversEnabledByDefault): void; } diff --git a/framework/core/src/Notification/Event/DeletedAll.php b/framework/core/src/Notification/Event/DeletedAll.php index 84eb20fdc..308f066d3 100644 --- a/framework/core/src/Notification/Event/DeletedAll.php +++ b/framework/core/src/Notification/Event/DeletedAll.php @@ -14,19 +14,9 @@ use Flarum\User\User; class DeletedAll { - /** - * @var User - */ - public $actor; - - /** - * @var DateTime - */ - public $timestamp; - - public function __construct(User $user, DateTime $timestamp) - { - $this->actor = $user; - $this->timestamp = $timestamp; + public function __construct( + public User $user, + public DateTime $timestamp + ) { } } diff --git a/framework/core/src/Notification/Event/Read.php b/framework/core/src/Notification/Event/Read.php index 00618e4cd..e37d4e23a 100644 --- a/framework/core/src/Notification/Event/Read.php +++ b/framework/core/src/Notification/Event/Read.php @@ -15,25 +15,10 @@ use Flarum\User\User; class Read { - /** - * @var User - */ - public $actor; - - /** - * @var Notification - */ - public $notification; - - /** - * @var DateTime - */ - public $timestamp; - - public function __construct(User $user, Notification $notification, DateTime $timestamp) - { - $this->actor = $user; - $this->notification = $notification; - $this->timestamp = $timestamp; + public function __construct( + public User $actor, + public Notification $notification, + public DateTime $timestamp + ) { } } diff --git a/framework/core/src/Notification/Event/ReadAll.php b/framework/core/src/Notification/Event/ReadAll.php index 6cb7b5fe2..07b2f29d9 100644 --- a/framework/core/src/Notification/Event/ReadAll.php +++ b/framework/core/src/Notification/Event/ReadAll.php @@ -14,19 +14,9 @@ use Flarum\User\User; class ReadAll { - /** - * @var User - */ - public $actor; - - /** - * @var DateTime - */ - public $timestamp; - - public function __construct(User $user, DateTime $timestamp) - { - $this->actor = $user; - $this->timestamp = $timestamp; + public function __construct( + public User $actor, + public DateTime $timestamp + ) { } } diff --git a/framework/core/src/Notification/Job/SendEmailNotificationJob.php b/framework/core/src/Notification/Job/SendEmailNotificationJob.php index 68bffeb17..f01617d64 100644 --- a/framework/core/src/Notification/Job/SendEmailNotificationJob.php +++ b/framework/core/src/Notification/Job/SendEmailNotificationJob.php @@ -16,23 +16,13 @@ use Flarum\User\User; class SendEmailNotificationJob extends AbstractJob { - /** - * @var MailableInterface - */ - private $blueprint; - - /** - * @var User - */ - private $recipient; - - public function __construct(MailableInterface $blueprint, User $recipient) - { - $this->blueprint = $blueprint; - $this->recipient = $recipient; + public function __construct( + private readonly MailableInterface $blueprint, + private readonly User $recipient + ) { } - public function handle(NotificationMailer $mailer) + public function handle(NotificationMailer $mailer): void { $mailer->send($this->blueprint, $this->recipient); } diff --git a/framework/core/src/Notification/Job/SendNotificationsJob.php b/framework/core/src/Notification/Job/SendNotificationsJob.php index f33fda7af..7226bedbd 100644 --- a/framework/core/src/Notification/Job/SendNotificationsJob.php +++ b/framework/core/src/Notification/Job/SendNotificationsJob.php @@ -16,23 +16,14 @@ use Flarum\User\User; class SendNotificationsJob extends AbstractJob { - /** - * @var BlueprintInterface - */ - private $blueprint; - - /** - * @var User[] - */ - private $recipients; - - public function __construct(BlueprintInterface $blueprint, array $recipients = []) - { - $this->blueprint = $blueprint; - $this->recipients = $recipients; + public function __construct( + private readonly BlueprintInterface $blueprint, + /** @var User[] */ + private readonly array $recipients = [] + ) { } - public function handle() + public function handle(): void { Notification::notify($this->recipients, $this->blueprint); } diff --git a/framework/core/src/Notification/MailableInterface.php b/framework/core/src/Notification/MailableInterface.php index f95b17a9b..a5cf4a760 100644 --- a/framework/core/src/Notification/MailableInterface.php +++ b/framework/core/src/Notification/MailableInterface.php @@ -9,23 +9,17 @@ namespace Flarum\Notification; -use Symfony\Contracts\Translation\TranslatorInterface; +use Flarum\Locale\TranslatorInterface; interface MailableInterface { /** * Get the name of the view to construct a notification email with. - * - * @return string|array */ - public function getEmailView(); + public function getEmailView(): string|array; /** * Get the subject line for a notification email. - * - * @param TranslatorInterface $translator - * - * @return string */ - public function getEmailSubject(TranslatorInterface $translator); + public function getEmailSubject(TranslatorInterface $translator): string; } diff --git a/framework/core/src/Notification/Notification.php b/framework/core/src/Notification/Notification.php index 91da2c6c8..62e7ccfae 100644 --- a/framework/core/src/Notification/Notification.php +++ b/framework/core/src/Notification/Notification.php @@ -14,6 +14,8 @@ use Flarum\Database\AbstractModel; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Support\Arr; /** @@ -58,16 +60,11 @@ class Notification extends AbstractModel * represents that a user's discussion was renamed, has the subject model * class 'Flarum\Discussion\Discussion'. * - * @var array + * @var array<string, class-string<AbstractModel>> */ - protected static $subjectModels = []; + protected static array $subjectModels = []; - /** - * Mark a notification as read. - * - * @return void - */ - public function read() + public function read(): void { $this->read_at = Carbon::now(); } @@ -75,11 +72,8 @@ class Notification extends AbstractModel /** * When getting the data attribute, unserialize the JSON stored in the * database into a plain array. - * - * @param string|null $value - * @return mixed */ - public function getDataAttribute($value) + public function getDataAttribute(?string $value): mixed { return $value !== null ? json_decode($value, true) @@ -89,10 +83,8 @@ class Notification extends AbstractModel /** * When setting the data attribute, serialize it into JSON for storage in * the database. - * - * @param mixed $value */ - public function setDataAttribute($value) + public function setDataAttribute(mixed $value): void { $this->attributes['data'] = json_encode($value); } @@ -100,40 +92,26 @@ class Notification extends AbstractModel /** * Get the subject model for this notification record by looking up its * type in our subject model map. - * - * @return string|null */ - public function getSubjectModelAttribute() + public function getSubjectModelAttribute(): ?string { return $this->type ? Arr::get(static::$subjectModels, $this->type) : null; } - /** - * Define the relationship with the notification's recipient. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } - /** - * Define the relationship with the notification's sender. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function fromUser() + public function fromUser(): BelongsTo { return $this->belongsTo(User::class, 'from_user_id'); } /** - * Define the relationship with the notification's subject. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo + * @return MorphTo */ - public function subject() + public function subject(): MorphTo { return $this->morphTo('subject', 'subjectModel'); } @@ -141,11 +119,8 @@ class Notification extends AbstractModel /** * Scope the query to include only notifications whose subjects are visible * to the given user. - * - * @param Builder $query - * @return Builder */ - public function scopeWhereSubjectVisibleTo(Builder $query, User $actor) + public function scopeWhereSubjectVisibleTo(Builder $query, User $actor): Builder { return $query->where(function ($query) use ($actor) { $classes = []; @@ -174,29 +149,21 @@ class Notification extends AbstractModel /** * Scope the query to include only notifications that have the given * subject. - * - * @param Builder $query - * @param object $model - * @return Builder */ - public function scopeWhereSubject(Builder $query, $model) + public function scopeWhereSubject(Builder $query, AbstractModel $model): Builder { return $query->whereSubjectModel(get_class($model)) - ->where('subject_id', $model->id); + ->where('subject_id', $model->getAttribute('id')); } /** * Scope the query to include only notification types that use the given * subject model. - * - * @param Builder $query - * @param string $class - * @return Builder */ - public function scopeWhereSubjectModel(Builder $query, string $class) + public function scopeWhereSubjectModel(Builder $query, string $class): Builder { - $notificationTypes = array_filter(self::getSubjectModels(), function ($modelClass) use ($class) { - return $modelClass === $class or is_subclass_of($class, $modelClass); + $notificationTypes = array_filter(self::getSubjectModels(), function (string $modelClass) use ($class) { + return $modelClass === $class || is_subclass_of($class, $modelClass); }); return $query->whereIn('type', array_keys($notificationTypes)); @@ -204,12 +171,8 @@ class Notification extends AbstractModel /** * Scope the query to find all records matching the given blueprint. - * - * @param Builder $query - * @param BlueprintInterface $blueprint - * @return Builder */ - public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $blueprint) + public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $blueprint): Builder { return $query->where(static::getBlueprintAttributes($blueprint)); } @@ -218,9 +181,8 @@ class Notification extends AbstractModel * Send notifications to the given recipients. * * @param User[] $recipients - * @param BlueprintInterface $blueprint */ - public static function notify(array $recipients, BlueprintInterface $blueprint) + public static function notify(array $recipients, BlueprintInterface $blueprint): void { $attributes = static::getBlueprintAttributes($blueprint); $now = Carbon::now()->toDateTimeString(); @@ -237,10 +199,8 @@ class Notification extends AbstractModel /** * Get the type-to-subject-model map. - * - * @return array */ - public static function getSubjectModels() + public static function getSubjectModels(): array { return static::$subjectModels; } @@ -249,11 +209,10 @@ class Notification extends AbstractModel * Set the subject model for the given notification type. * * @param string $type The notification type. - * @param string $subjectModel The class name of the subject model for that + * @param class-string<AbstractModel> $subjectModel The class name of the subject model for that * type. - * @return void */ - public static function setSubjectModel($type, $subjectModel) + public static function setSubjectModel(string $type, string $subjectModel): void { static::$subjectModels[$type] = $subjectModel; } @@ -263,7 +222,7 @@ class Notification extends AbstractModel return [ 'type' => $blueprint::getType(), 'from_user_id' => ($fromUser = $blueprint->getFromUser()) ? $fromUser->id : null, - 'subject_id' => ($subject = $blueprint->getSubject()) ? $subject->id : null, + 'subject_id' => ($subject = $blueprint->getSubject()) ? $subject->getAttribute('id') : null, 'data' => ($data = $blueprint->getData()) ? json_encode($data) : null ]; } diff --git a/framework/core/src/Notification/NotificationMailer.php b/framework/core/src/Notification/NotificationMailer.php index 7b5a1ee62..b847f9a4c 100644 --- a/framework/core/src/Notification/NotificationMailer.php +++ b/framework/core/src/Notification/NotificationMailer.php @@ -9,45 +9,22 @@ namespace Flarum\Notification; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\User; use Illuminate\Contracts\Mail\Mailer; -use Illuminate\Contracts\Translation\Translator; use Illuminate\Mail\Message; -use Symfony\Contracts\Translation\TranslatorInterface; class NotificationMailer { - /** - * @var Mailer - */ - protected $mailer; - - /** - * @var TranslatorInterface&Translator - */ - protected $translator; - - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @param TranslatorInterface&Translator $translator - */ - public function __construct(Mailer $mailer, TranslatorInterface $translator, SettingsRepositoryInterface $settings) - { - $this->mailer = $mailer; - $this->translator = $translator; - $this->settings = $settings; + public function __construct( + protected Mailer $mailer, + protected TranslatorInterface $translator, + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param MailableInterface $blueprint - * @param User $user - */ - public function send(MailableInterface $blueprint, User $user) + public function send(MailableInterface $blueprint, User $user): void { // Ensure that notifications are delivered to the user in their default language, if they've selected one. // If the selected locale is no longer available, the forum default will be used instead. diff --git a/framework/core/src/Notification/NotificationRepository.php b/framework/core/src/Notification/NotificationRepository.php index d34941e65..7de4a59b0 100644 --- a/framework/core/src/Notification/NotificationRepository.php +++ b/framework/core/src/Notification/NotificationRepository.php @@ -11,18 +11,11 @@ namespace Flarum\Notification; use Carbon\Carbon; use Flarum\User\User; +use Illuminate\Database\Eloquent\Collection; class NotificationRepository { - /** - * Find a user's notifications. - * - * @param User $user - * @param int|null $limit - * @param int $offset - * @return \Illuminate\Database\Eloquent\Collection - */ - public function findByUser(User $user, $limit = null, $offset = 0) + public function findByUser(User $user, ?int $limit = null, int $offset = 0): Collection { $primaries = Notification::query() ->selectRaw('MAX(id) AS id') @@ -43,22 +36,16 @@ class NotificationRepository ->get(); } - /** - * Mark all of a user's notifications as read. - * - * @param User $user - * - * @return void - */ - public function markAllAsRead(User $user) + public function markAllAsRead(User $user): void { - Notification::where('user_id', $user->id) + Notification::query() + ->where('user_id', $user->id) ->whereNull('read_at') ->update(['read_at' => Carbon::now()]); } - public function deleteAll(User $user) + public function deleteAll(User $user): void { - Notification::where('user_id', $user->id)->delete(); + Notification::query()->where('user_id', $user->id)->delete(); } } diff --git a/framework/core/src/Notification/NotificationServiceProvider.php b/framework/core/src/Notification/NotificationServiceProvider.php index 333ead0c1..98c4d1d57 100644 --- a/framework/core/src/Notification/NotificationServiceProvider.php +++ b/framework/core/src/Notification/NotificationServiceProvider.php @@ -10,15 +10,13 @@ namespace Flarum\Notification; use Flarum\Foundation\AbstractServiceProvider; +use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\Blueprint\DiscussionRenamedBlueprint; use Illuminate\Contracts\Container\Container; class NotificationServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.notification.drivers', function () { return [ @@ -34,29 +32,20 @@ class NotificationServiceProvider extends AbstractServiceProvider }); } - /** - * {@inheritdoc} - */ - public function boot(Container $container) + public function boot(Container $container): void { $this->setNotificationDrivers($container); $this->setNotificationTypes($container); } - /** - * Register notification drivers. - */ - protected function setNotificationDrivers(Container $container) + protected function setNotificationDrivers(Container $container): void { foreach ($container->make('flarum.notification.drivers') as $driverName => $driver) { NotificationSyncer::addNotificationDriver($driverName, $container->make($driver)); } } - /** - * Register notification types. - */ - protected function setNotificationTypes(Container $container) + protected function setNotificationTypes(Container $container): void { $blueprints = $container->make('flarum.notification.blueprints'); @@ -65,16 +54,19 @@ class NotificationServiceProvider extends AbstractServiceProvider } } - protected function addType(string $blueprint, array $driversEnabledByDefault) + /** + * @param class-string<BlueprintInterface> $blueprintClass + */ + protected function addType(string $blueprintClass, array $driversEnabledByDefault): void { Notification::setSubjectModel( - $type = $blueprint::getType(), - $blueprint::getSubjectModel() + $blueprintClass::getType(), + $blueprintClass::getSubjectModel() ); foreach (NotificationSyncer::getNotificationDrivers() as $driverName => $driver) { $driver->registerType( - $blueprint, + $blueprintClass, $driversEnabledByDefault ); } diff --git a/framework/core/src/Notification/NotificationSyncer.php b/framework/core/src/Notification/NotificationSyncer.php index 18d845a8d..3c6aaa5d3 100644 --- a/framework/core/src/Notification/NotificationSyncer.php +++ b/framework/core/src/Notification/NotificationSyncer.php @@ -22,41 +22,37 @@ use Flarum\User\User; class NotificationSyncer { /** - * Whether or not notifications are being limited to one per user. - * - * @var bool + * Whether notifications are being limited to one per user. */ - protected static $onePerUser = false; + protected static bool $onePerUser = false; /** * An internal list of user IDs that notifications have been sent to. * * @var int[] */ - protected static $sentTo = []; + protected static array $sentTo = []; /** * A map of notification drivers. * * @var NotificationDriverInterface[] */ - protected static $notificationDrivers = []; + protected static array $notificationDrivers = []; /** - * @var array + * @var callable[] */ - protected static $beforeSendingCallbacks = []; + protected static array $beforeSendingCallbacks = []; /** * Sync a notification so that it is visible to the specified users, and not * visible to anyone else. If it is being made visible for the first time, * attempt to send the user an email. * - * @param \Flarum\Notification\Blueprint\BlueprintInterface $blueprint * @param User[] $users - * @return void */ - public function sync(Blueprint\BlueprintInterface $blueprint, array $users) + public function sync(BlueprintInterface $blueprint, array $users): void { // Find all existing notification records in the database matching this // blueprint. We will begin by assuming that they all need to be @@ -87,7 +83,7 @@ class NotificationSyncer } } - // Delete all of the remaining notification records which weren't + // Delete all the remaining notification records which weren't // removed from this collection by the above loop. Un-delete the // existing records that we want to keep. if (count($toDelete)) { @@ -113,22 +109,16 @@ class NotificationSyncer /** * Delete a notification for all users. - * - * @param \Flarum\Notification\Blueprint\BlueprintInterface $blueprint - * @return void */ - public function delete(BlueprintInterface $blueprint) + public function delete(BlueprintInterface $blueprint): void { Notification::matchingBlueprint($blueprint)->update(['is_deleted' => true]); } /** * Restore a notification for all users. - * - * @param BlueprintInterface $blueprint - * @return void */ - public function restore(BlueprintInterface $blueprint) + public function restore(BlueprintInterface $blueprint): void { Notification::matchingBlueprint($blueprint)->update(['is_deleted' => false]); } @@ -136,11 +126,8 @@ class NotificationSyncer /** * Limit notifications to one per user for the entire duration of the given * callback. - * - * @param callable $callback - * @return void */ - public function onePerUser(callable $callback) + public function onePerUser(callable $callback): void { static::$sentTo = []; static::$onePerUser = true; @@ -154,19 +141,13 @@ class NotificationSyncer * Set the deleted status of a list of notification records. * * @param int[] $ids - * @param bool $isDeleted */ - protected function setDeleted(array $ids, $isDeleted) + protected function setDeleted(array $ids, bool $isDeleted): void { - Notification::whereIn('id', $ids)->update(['is_deleted' => $isDeleted]); + Notification::query()->whereIn('id', $ids)->update(['is_deleted' => $isDeleted]); } /** - * Adds a notification driver to the list. - * - * @param string $driverName - * @param NotificationDriverInterface $driver - * * @internal */ public static function addNotificationDriver(string $driverName, NotificationDriverInterface $driver): void @@ -183,11 +164,9 @@ class NotificationSyncer } /** - * @param callable|string $callback - * * @internal */ - public static function beforeSending($callback): void + public static function beforeSending(callable $callback): void { static::$beforeSendingCallbacks[] = $callback; } diff --git a/framework/core/src/Post/AbstractEventPost.php b/framework/core/src/Post/AbstractEventPost.php index 38956fe07..d9551e2cf 100644 --- a/framework/core/src/Post/AbstractEventPost.php +++ b/framework/core/src/Post/AbstractEventPost.php @@ -16,21 +16,16 @@ abstract class AbstractEventPost extends Post { /** * Unserialize the content attribute from the database's JSON value. - * - * @param string $value - * @return array */ - public function getContentAttribute($value) + public function getContentAttribute(string $value): ?array { return json_decode($value, true); } /** * Serialize the content attribute to be stored in the database as JSON. - * - * @param string $value */ - public function setContentAttribute($value) + public function setContentAttribute(mixed $value): void { $this->attributes['content'] = json_encode($value); } diff --git a/framework/core/src/Post/Access/PostPolicy.php b/framework/core/src/Post/Access/PostPolicy.php index 88fb041de..839fa57a2 100644 --- a/framework/core/src/Post/Access/PostPolicy.php +++ b/framework/core/src/Post/Access/PostPolicy.php @@ -17,37 +17,18 @@ use Flarum\User\User; class PostPolicy extends AbstractPolicy { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @param SettingsRepositoryInterface $settings - */ - public function __construct(SettingsRepositoryInterface $settings) - { - $this->settings = $settings; + public function __construct( + protected SettingsRepositoryInterface $settings + ) { } - /** - * @param User $actor - * @param string $ability - * @param \Flarum\Post\Post $post - * @return bool|null - */ - public function can(User $actor, $ability, Post $post) + public function can(User $actor, string $ability, Post $post) { if ($actor->can($ability.'Posts', $post->discussion)) { return $this->allow(); } } - /** - * @param User $actor - * @param Post $post - * @return bool|null - */ public function edit(User $actor, Post $post) { // A post is allowed to be edited if the user is the author, the post @@ -64,11 +45,6 @@ class PostPolicy extends AbstractPolicy } } - /** - * @param User $actor - * @param Post $post - * @return bool|null - */ public function hide(User $actor, Post $post) { if ($post->user_id == $actor->id && (! $post->hidden_at || $post->hidden_user_id == $actor->id) && $actor->can('reply', $post->discussion)) { diff --git a/framework/core/src/Post/Access/ScopePostVisibility.php b/framework/core/src/Post/Access/ScopePostVisibility.php index c0e739076..91c87baf9 100644 --- a/framework/core/src/Post/Access/ScopePostVisibility.php +++ b/framework/core/src/Post/Access/ScopePostVisibility.php @@ -15,11 +15,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopePostVisibility { - /** - * @param User $actor - * @param Builder $query - */ - public function __invoke(User $actor, $query) + public function __invoke(User $actor, Builder $query): void { // Make sure the post's discussion is visible as well. $query->whereExists(function ($query) use ($actor) { diff --git a/framework/core/src/Post/Command/DeletePost.php b/framework/core/src/Post/Command/DeletePost.php index 071727c8e..9841de522 100644 --- a/framework/core/src/Post/Command/DeletePost.php +++ b/framework/core/src/Post/Command/DeletePost.php @@ -13,38 +13,10 @@ use Flarum\User\User; class DeletePost { - /** - * The ID of the post to delete. - * - * @var int - */ - public $postId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * Any other user input associated with the action. This is unused by - * default, but may be used by extensions. - * - * @var array - */ - public $data; - - /** - * @param int $postId The ID of the post to delete. - * @param User $actor The user performing the action. - * @param array $data Any other user input associated with the action. This - * is unused by default, but may be used by extensions. - */ - public function __construct($postId, User $actor, array $data = []) - { - $this->postId = $postId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $postId, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/Post/Command/DeletePostHandler.php b/framework/core/src/Post/Command/DeletePostHandler.php index f6a037d9f..816e14d64 100644 --- a/framework/core/src/Post/Command/DeletePostHandler.php +++ b/framework/core/src/Post/Command/DeletePostHandler.php @@ -11,6 +11,7 @@ namespace Flarum\Post\Command; use Flarum\Foundation\DispatchEventsTrait; use Flarum\Post\Event\Deleting; +use Flarum\Post\Post; use Flarum\Post\PostRepository; use Illuminate\Contracts\Events\Dispatcher; @@ -18,27 +19,13 @@ class DeletePostHandler { use DispatchEventsTrait; - /** - * @var \Flarum\Post\PostRepository - */ - protected $posts; - - /** - * @param Dispatcher $events - * @param \Flarum\Post\PostRepository $posts - */ - public function __construct(Dispatcher $events, PostRepository $posts) - { - $this->events = $events; - $this->posts = $posts; + public function __construct( + protected Dispatcher $events, + protected PostRepository $posts + ) { } - /** - * @param DeletePost $command - * @return \Flarum\Post\Post - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(DeletePost $command) + public function handle(DeletePost $command): Post { $actor = $command->actor; diff --git a/framework/core/src/Post/Command/EditPost.php b/framework/core/src/Post/Command/EditPost.php index dec29a8c2..591ea5b11 100644 --- a/framework/core/src/Post/Command/EditPost.php +++ b/framework/core/src/Post/Command/EditPost.php @@ -13,36 +13,10 @@ use Flarum\User\User; class EditPost { - /** - * The ID of the post to edit. - * - * @var int - */ - public $postId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the post. - * - * @var array - */ - public $data; - - /** - * @param int $postId The ID of the post to edit. - * @param User $actor The user performing the action. - * @param array $data The attributes to update on the post. - */ - public function __construct($postId, User $actor, array $data) - { - $this->postId = $postId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $postId, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Post/Command/EditPostHandler.php b/framework/core/src/Post/Command/EditPostHandler.php index 6add71e96..e68ce7ba8 100644 --- a/framework/core/src/Post/Command/EditPostHandler.php +++ b/framework/core/src/Post/Command/EditPostHandler.php @@ -12,6 +12,7 @@ namespace Flarum\Post\Command; use Flarum\Foundation\DispatchEventsTrait; use Flarum\Post\CommentPost; use Flarum\Post\Event\Saving; +use Flarum\Post\Post; use Flarum\Post\PostRepository; use Flarum\Post\PostValidator; use Illuminate\Contracts\Events\Dispatcher; @@ -21,34 +22,14 @@ class EditPostHandler { use DispatchEventsTrait; - /** - * @var \Flarum\Post\PostRepository - */ - protected $posts; - - /** - * @var \Flarum\Post\PostValidator - */ - protected $validator; - - /** - * @param Dispatcher $events - * @param PostRepository $posts - * @param \Flarum\Post\PostValidator $validator - */ - public function __construct(Dispatcher $events, PostRepository $posts, PostValidator $validator) - { - $this->events = $events; - $this->posts = $posts; - $this->validator = $validator; + public function __construct( + protected Dispatcher $events, + protected PostRepository $posts, + protected PostValidator $validator + ) { } - /** - * @param EditPost $command - * @return \Flarum\Post\Post - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(EditPost $command) + public function handle(EditPost $command): Post|CommentPost { $actor = $command->actor; $data = $command->data; diff --git a/framework/core/src/Post/Command/PostReply.php b/framework/core/src/Post/Command/PostReply.php index 226464926..d1e09b43d 100644 --- a/framework/core/src/Post/Command/PostReply.php +++ b/framework/core/src/Post/Command/PostReply.php @@ -13,51 +13,12 @@ use Flarum\User\User; class PostReply { - /** - * The ID of the discussion to post the reply to. - * - * @var int - */ - public $discussionId; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to assign to the new post. - * - * @var array - */ - public $data; - - /** - * The IP address of the actor. - * - * @var string - */ - public $ipAddress; - - /** - * @var bool - */ - public $isFirstPost; - - /** - * @param int $discussionId The ID of the discussion to post the reply to. - * @param User $actor The user who is performing the action. - * @param array $data The attributes to assign to the new post. - * @param string $ipAddress The IP address of the actor. - */ - public function __construct($discussionId, User $actor, array $data, $ipAddress = null, bool $isFirstPost = false) - { - $this->discussionId = $discussionId; - $this->actor = $actor; - $this->data = $data; - $this->ipAddress = $ipAddress; - $this->isFirstPost = $isFirstPost; + public function __construct( + public int $discussionId, + public User $actor, + public array $data, + public ?string $ipAddress = null, + public bool $isFirstPost = false + ) { } } diff --git a/framework/core/src/Post/Command/PostReplyHandler.php b/framework/core/src/Post/Command/PostReplyHandler.php index f634a2dac..4f2a1889b 100644 --- a/framework/core/src/Post/Command/PostReplyHandler.php +++ b/framework/core/src/Post/Command/PostReplyHandler.php @@ -23,45 +23,15 @@ class PostReplyHandler { use DispatchEventsTrait; - /** - * @var DiscussionRepository - */ - protected $discussions; - - /** - * @var \Flarum\Notification\NotificationSyncer - */ - protected $notifications; - - /** - * @var \Flarum\Post\PostValidator - */ - protected $validator; - - /** - * @param Dispatcher $events - * @param DiscussionRepository $discussions - * @param \Flarum\Notification\NotificationSyncer $notifications - * @param PostValidator $validator - */ public function __construct( - Dispatcher $events, - DiscussionRepository $discussions, - NotificationSyncer $notifications, - PostValidator $validator + protected Dispatcher $events, + protected DiscussionRepository $discussions, + protected NotificationSyncer $notifications, + protected PostValidator $validator ) { - $this->events = $events; - $this->discussions = $discussions; - $this->notifications = $notifications; - $this->validator = $validator; } - /** - * @param PostReply $command - * @return CommentPost - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(PostReply $command) + public function handle(PostReply $command): CommentPost { $actor = $command->actor; diff --git a/framework/core/src/Post/CommentPost.php b/framework/core/src/Post/CommentPost.php index 35f38e852..c1b150ddb 100644 --- a/framework/core/src/Post/CommentPost.php +++ b/framework/core/src/Post/CommentPost.php @@ -25,29 +25,10 @@ use Psr\Http\Message\ServerRequestInterface; */ class CommentPost extends Post { - /** - * {@inheritdoc} - */ - public static $type = 'comment'; + public static string $type = 'comment'; + protected static Formatter $formatter; - /** - * The text formatter instance. - * - * @var \Flarum\Formatter\Formatter - */ - protected static $formatter; - - /** - * Create a new instance in reply to a discussion. - * - * @param int $discussionId - * @param string $content - * @param int $userId - * @param string $ipAddress - * @param User|null $actor - * @return static - */ - public static function reply($discussionId, $content, $userId, $ipAddress, User $actor = null) + public static function reply(int $discussionId, string $content, int $userId, ?string $ipAddress, ?User $actor = null): static { $post = new static; @@ -65,14 +46,7 @@ class CommentPost extends Post return $post; } - /** - * Revise the post's content. - * - * @param string $content - * @param User $actor - * @return $this - */ - public function revise($content, User $actor) + public function revise(string $content, User $actor): static { if ($this->content !== $content) { $oldContent = $this->content; @@ -88,17 +62,11 @@ class CommentPost extends Post return $this; } - /** - * Hide the post. - * - * @param User $actor - * @return $this - */ - public function hide(User $actor = null) + public function hide(?User $actor = null): static { if (! $this->hidden_at) { $this->hidden_at = Carbon::now(); - $this->hidden_user_id = $actor ? $actor->id : null; + $this->hidden_user_id = $actor?->id; $this->raise(new Hidden($this)); } @@ -106,12 +74,7 @@ class CommentPost extends Post return $this; } - /** - * Restore the post. - * - * @return $this - */ - public function restore() + public function restore(): static { if ($this->hidden_at !== null) { $this->hidden_at = null; @@ -123,75 +86,40 @@ class CommentPost extends Post return $this; } - /** - * Unparse the parsed content. - * - * @param string $value - * @return string - */ - public function getContentAttribute($value) + public function getContentAttribute(string $value): string { return static::$formatter->unparse($value, $this); } - /** - * Get the parsed/raw content. - * - * @return string - */ - public function getParsedContentAttribute() + public function getParsedContentAttribute(): string { return $this->attributes['content']; } - /** - * Parse the content before it is saved to the database. - * - * @param string $value - * @param User $actor - */ - public function setContentAttribute($value, User $actor = null) + public function setContentAttribute(string $value, ?User $actor = null): void { $this->attributes['content'] = $value ? static::$formatter->parse($value, $this, $actor ?? $this->user) : null; } - /** - * Set the parsed/raw content. - * - * @param string $value - */ - public function setParsedContentAttribute($value) + public function setParsedContentAttribute(string $value): void { $this->attributes['content'] = $value; } /** * Get the content rendered as HTML. - * - * @param ServerRequestInterface $request - * @return string */ - public function formatContent(ServerRequestInterface $request = null) + public function formatContent(?ServerRequestInterface $request = null): string { return static::$formatter->render($this->attributes['content'], $this, $request); } - /** - * Get the text formatter instance. - * - * @return \Flarum\Formatter\Formatter - */ - public static function getFormatter() + public static function getFormatter(): Formatter { return static::$formatter; } - /** - * Set the text formatter instance. - * - * @param \Flarum\Formatter\Formatter $formatter - */ - public static function setFormatter(Formatter $formatter) + public static function setFormatter(Formatter $formatter): void { static::$formatter = $formatter; } diff --git a/framework/core/src/Post/DiscussionRenamedPost.php b/framework/core/src/Post/DiscussionRenamedPost.php index e115f3bd2..0866ad704 100644 --- a/framework/core/src/Post/DiscussionRenamedPost.php +++ b/framework/core/src/Post/DiscussionRenamedPost.php @@ -19,15 +19,9 @@ use Carbon\Carbon; */ class DiscussionRenamedPost extends AbstractEventPost implements MergeableInterface { - /** - * {@inheritdoc} - */ - public static $type = 'discussionRenamed'; + public static string $type = 'discussionRenamed'; - /** - * {@inheritdoc} - */ - public function saveAfter(Post $previous = null) + public function saveAfter(Post $previous = null): static { // If the previous post is another 'discussion renamed' post, and it's // by the same user, then we can merge this post into it. If we find @@ -50,16 +44,7 @@ class DiscussionRenamedPost extends AbstractEventPost implements MergeableInterf return $this; } - /** - * Create a new instance in reply to a discussion. - * - * @param int $discussionId - * @param int $userId - * @param string $oldTitle - * @param string $newTitle - * @return static - */ - public static function reply($discussionId, $userId, $oldTitle, $newTitle) + public static function reply(int $discussionId, int $userId, string $oldTitle, string $newTitle): static { $post = new static; @@ -71,14 +56,7 @@ class DiscussionRenamedPost extends AbstractEventPost implements MergeableInterf return $post; } - /** - * Build the content attribute. - * - * @param string $oldTitle The old title of the discussion. - * @param string $newTitle The new title of the discussion. - * @return array - */ - protected static function buildContent($oldTitle, $newTitle) + protected static function buildContent(string $oldTitle, string $newTitle): array { return [$oldTitle, $newTitle]; } diff --git a/framework/core/src/Post/Event/Deleted.php b/framework/core/src/Post/Event/Deleted.php index 80b2d51d2..259c8ff8b 100644 --- a/framework/core/src/Post/Event/Deleted.php +++ b/framework/core/src/Post/Event/Deleted.php @@ -14,22 +14,9 @@ use Flarum\User\User; class Deleted { - /** - * @var \Flarum\Post\Post - */ - public $post; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Post\Post $post - */ - public function __construct(Post $post, User $actor = null) - { - $this->post = $post; - $this->actor = $actor; + public function __construct( + public Post $post, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Post/Event/Deleting.php b/framework/core/src/Post/Event/Deleting.php index 4f3a8d195..bd88e87fa 100644 --- a/framework/core/src/Post/Event/Deleting.php +++ b/framework/core/src/Post/Event/Deleting.php @@ -14,36 +14,10 @@ use Flarum\User\User; class Deleting { - /** - * The post that is going to be deleted. - * - * @var \Flarum\Post\Post - */ - public $post; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * Any user input associated with the command. - * - * @var array - */ - public $data; - - /** - * @param \Flarum\Post\Post $post - * @param User $actor - * @param array $data - */ - public function __construct(Post $post, User $actor, array $data) - { - $this->post = $post; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Post $post, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/Post/Event/Hidden.php b/framework/core/src/Post/Event/Hidden.php index 138cda73a..250489ccc 100644 --- a/framework/core/src/Post/Event/Hidden.php +++ b/framework/core/src/Post/Event/Hidden.php @@ -14,22 +14,9 @@ use Flarum\User\User; class Hidden { - /** - * @var CommentPost - */ - public $post; - - /** - * @var User - */ - public $actor; - - /** - * @param CommentPost $post - */ - public function __construct(CommentPost $post, User $actor = null) - { - $this->post = $post; - $this->actor = $actor; + public function __construct( + public CommentPost $post, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Post/Event/Posted.php b/framework/core/src/Post/Event/Posted.php index 158e6a55b..19504864d 100644 --- a/framework/core/src/Post/Event/Posted.php +++ b/framework/core/src/Post/Event/Posted.php @@ -14,23 +14,9 @@ use Flarum\User\User; class Posted { - /** - * @var CommentPost - */ - public $post; - - /** - * @var User|null - */ - public $actor; - - /** - * @param CommentPost $post - * @param User|null $actor - */ - public function __construct(CommentPost $post, User $actor = null) - { - $this->post = $post; - $this->actor = $actor; + public function __construct( + public CommentPost $post, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Post/Event/Restored.php b/framework/core/src/Post/Event/Restored.php index 0ae61357f..78b4c37a6 100644 --- a/framework/core/src/Post/Event/Restored.php +++ b/framework/core/src/Post/Event/Restored.php @@ -14,22 +14,9 @@ use Flarum\User\User; class Restored { - /** - * @var \Flarum\Post\CommentPost - */ - public $post; - - /** - * @var User - */ - public $actor; - - /** - * @param \Flarum\Post\CommentPost $post - */ - public function __construct(CommentPost $post, User $actor = null) - { - $this->post = $post; - $this->actor = $actor; + public function __construct( + public CommentPost $post, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/Post/Event/Revised.php b/framework/core/src/Post/Event/Revised.php index 8d4f85725..8bbfb75a0 100644 --- a/framework/core/src/Post/Event/Revised.php +++ b/framework/core/src/Post/Event/Revised.php @@ -14,29 +14,10 @@ use Flarum\User\User; class Revised { - /** - * @var CommentPost - */ - public $post; - - /** - * @var User - */ - public $actor; - - /** - * We manually set the old content because at this stage the post - * has already been updated with the new content. So the original - * content is not available anymore. - * - * @var string - */ - public $oldContent; - - public function __construct(CommentPost $post, User $actor, string $oldContent) - { - $this->post = $post; - $this->actor = $actor; - $this->oldContent = $oldContent; + public function __construct( + public CommentPost $post, + public User $actor, + public string $oldContent + ) { } } diff --git a/framework/core/src/Post/Event/Saving.php b/framework/core/src/Post/Event/Saving.php index f15edd030..c4aad7507 100644 --- a/framework/core/src/Post/Event/Saving.php +++ b/framework/core/src/Post/Event/Saving.php @@ -14,36 +14,10 @@ use Flarum\User\User; class Saving { - /** - * The post that will be saved. - * - * @var \Flarum\Post\Post - */ - public $post; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the post. - * - * @var array - */ - public $data; - - /** - * @param \Flarum\Post\Post $post - * @param User $actor - * @param array $data - */ - public function __construct(Post $post, User $actor, array $data = []) - { - $this->post = $post; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public Post $post, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/Post/Filter/AuthorFilter.php b/framework/core/src/Post/Filter/AuthorFilter.php index 761969e29..b9f337db6 100644 --- a/framework/core/src/Post/Filter/AuthorFilter.php +++ b/framework/core/src/Post/Filter/AuthorFilter.php @@ -18,14 +18,9 @@ class AuthorFilter implements FilterInterface { use ValidateFilterTrait; - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } public function getFilterKey(): string @@ -33,7 +28,7 @@ class AuthorFilter implements FilterInterface return 'author'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $usernames = $this->asStringArray($filterValue); diff --git a/framework/core/src/Post/Filter/DiscussionFilter.php b/framework/core/src/Post/Filter/DiscussionFilter.php index c10436bce..1c7fa566b 100644 --- a/framework/core/src/Post/Filter/DiscussionFilter.php +++ b/framework/core/src/Post/Filter/DiscussionFilter.php @@ -22,7 +22,7 @@ class DiscussionFilter implements FilterInterface return 'discussion'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $discussionId = $this->asInt($filterValue); diff --git a/framework/core/src/Post/Filter/IdFilter.php b/framework/core/src/Post/Filter/IdFilter.php index f9928adc4..fe908920b 100644 --- a/framework/core/src/Post/Filter/IdFilter.php +++ b/framework/core/src/Post/Filter/IdFilter.php @@ -22,7 +22,7 @@ class IdFilter implements FilterInterface return 'id'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $ids = $this->asIntArray($filterValue); diff --git a/framework/core/src/Post/Filter/NumberFilter.php b/framework/core/src/Post/Filter/NumberFilter.php index e2dff477b..182ed8d32 100644 --- a/framework/core/src/Post/Filter/NumberFilter.php +++ b/framework/core/src/Post/Filter/NumberFilter.php @@ -22,7 +22,7 @@ class NumberFilter implements FilterInterface return 'number'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $number = $this->asInt($filterValue); diff --git a/framework/core/src/Post/Filter/PostFilterer.php b/framework/core/src/Post/Filter/PostFilterer.php index 67d1c7da9..1cc559f3d 100644 --- a/framework/core/src/Post/Filter/PostFilterer.php +++ b/framework/core/src/Post/Filter/PostFilterer.php @@ -16,21 +16,12 @@ use Illuminate\Database\Eloquent\Builder; class PostFilterer extends AbstractFilterer { - /** - * @var PostRepository - */ - protected $posts; - - /** - * @param PostRepository $posts - * @param array $filters - * @param array $filterMutators - */ - public function __construct(PostRepository $posts, array $filters, array $filterMutators) - { + public function __construct( + protected PostRepository $posts, + array $filters, + array $filterMutators + ) { parent::__construct($filters, $filterMutators); - - $this->posts = $posts; } protected function getQuery(User $actor): Builder diff --git a/framework/core/src/Post/Filter/TypeFilter.php b/framework/core/src/Post/Filter/TypeFilter.php index a3120bd91..e8fa0debf 100644 --- a/framework/core/src/Post/Filter/TypeFilter.php +++ b/framework/core/src/Post/Filter/TypeFilter.php @@ -22,7 +22,7 @@ class TypeFilter implements FilterInterface return 'type'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $type = $this->asString($filterValue); diff --git a/framework/core/src/Post/MergeableInterface.php b/framework/core/src/Post/MergeableInterface.php index 71260c6da..19e59bd57 100644 --- a/framework/core/src/Post/MergeableInterface.php +++ b/framework/core/src/Post/MergeableInterface.php @@ -22,10 +22,9 @@ interface MergeableInterface * Save the model, given that it is going to appear immediately after the * passed model. * - * @param \Flarum\Post\Post|null $previous * @return static The model resulting after the merge. If the merge is * unsuccessful, this should be the current model instance. Otherwise, * it should be the model that was merged into. */ - public function saveAfter(Post $previous = null); + public function saveAfter(Post $previous = null): static; } diff --git a/framework/core/src/Post/Post.php b/framework/core/src/Post/Post.php index fa86b8db1..18f5448c9 100644 --- a/framework/core/src/Post/Post.php +++ b/framework/core/src/Post/Post.php @@ -17,6 +17,7 @@ use Flarum\Notification\Notification; use Flarum\Post\Event\Deleted; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Query\Expression; use Staudenmeir\EloquentEagerLimit\HasEagerLimit; @@ -67,9 +68,9 @@ class Post extends AbstractModel * A map of post types, as specified in the `type` column, to their * classes. * - * @var array + * @var array<string, class-string<Post>> */ - protected static $models = []; + protected static array $models = []; /** * The type of post this is, to be stored in the posts table. @@ -77,14 +78,9 @@ class Post extends AbstractModel * Should be overwritten by subclasses with the value that is * to be stored in the database, which will then be used for * mapping the hydrated model instance to the proper subtype. - * - * @var string */ - public static $type = ''; + public static string $type = ''; - /** - * {@inheritdoc} - */ public static function boot() { parent::boot(); @@ -121,52 +117,29 @@ class Post extends AbstractModel } /** - * Determine whether or not this post is visible to the given user. - * - * @param User $user - * @return bool + * Determine whether this post is visible to the given user. */ - public function isVisibleTo(User $user) + public function isVisibleTo(User $user): bool { return (bool) $this->newQuery()->whereVisibleTo($user)->find($this->id); } - /** - * Define the relationship with the post's discussion. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function discussion() + public function discussion(): BelongsTo { return $this->belongsTo(Discussion::class); } - /** - * Define the relationship with the post's author. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } - /** - * Define the relationship with the user who edited the post. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function editedUser() + public function editedUser(): BelongsTo { return $this->belongsTo(User::class, 'edited_user_id'); } - /** - * Define the relationship with the user who hid the post. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function hiddenUser() + public function hiddenUser(): BelongsTo { return $this->belongsTo(User::class, 'hidden_user_id'); } @@ -174,11 +147,8 @@ class Post extends AbstractModel /** * Get all posts, regardless of their type, by removing the * `RegisteredTypesScope` global scope constraints applied on this model. - * - * @param Builder $query - * @return Builder */ - public function scopeAllTypes(Builder $query) + public function scopeAllTypes(Builder $query): Builder { return $query->withoutGlobalScopes(); } @@ -210,26 +180,15 @@ class Post extends AbstractModel return parent::newFromBuilder($attributes, $connection); } - /** - * Get the type-to-model map. - * - * @return array - */ - public static function getModels() + public static function getModels(): array { return static::$models; } /** - * Set the model for the given post type. - * - * @param string $type The post type. - * @param string $model The class name of the model for that type. - * @return void - * * @internal */ - public static function setModel(string $type, string $model) + public static function setModel(string $type, string $model): void { static::$models[$type] = $model; } diff --git a/framework/core/src/Post/PostCreationThrottler.php b/framework/core/src/Post/PostCreationThrottler.php index d390f640b..86d44c7e5 100644 --- a/framework/core/src/Post/PostCreationThrottler.php +++ b/framework/core/src/Post/PostCreationThrottler.php @@ -15,15 +15,12 @@ use Psr\Http\Message\ServerRequestInterface; class PostCreationThrottler { - public static $timeout = 10; + public static int $timeout = 10; - /** - * @return bool|void - */ - public function __invoke(ServerRequestInterface $request) + public function __invoke(ServerRequestInterface $request): ?bool { if (! in_array($request->getAttribute('routeName'), ['discussions.create', 'posts.create'])) { - return; + return null; } $actor = RequestUtil::getActor($request); @@ -35,5 +32,7 @@ class PostCreationThrottler if (Post::where('user_id', $actor->id)->where('created_at', '>=', Carbon::now()->subSeconds(self::$timeout))->exists()) { return true; } + + return null; } } diff --git a/framework/core/src/Post/PostRepository.php b/framework/core/src/Post/PostRepository.php index b764ae8eb..056a056f0 100644 --- a/framework/core/src/Post/PostRepository.php +++ b/framework/core/src/Post/PostRepository.php @@ -12,24 +12,22 @@ namespace Flarum\Post; use Flarum\Discussion\Discussion; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; class PostRepository { /** - * Get a new query builder for the posts table. - * * @return Builder<Post> */ - public function query() + public function query(): Builder { return Post::query(); } /** - * @param User|null $user * @return Builder<Post> */ - public function queryVisibleTo(?User $user = null) + public function queryVisibleTo(?User $user = null): Builder { $query = $this->query(); @@ -44,13 +42,9 @@ class PostRepository * Find a post by ID, optionally making sure it is visible to a certain * user, or throw an exception. * - * @param int $id - * @param \Flarum\User\User|null $actor - * @return Post - * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ - public function findOrFail($id, User $actor = null) + public function findOrFail(int $id, ?User $actor = null): Post { return $this->queryVisibleTo($actor)->findOrFail($id); } @@ -58,15 +52,8 @@ class PostRepository /** * Find posts that match certain conditions, optionally making sure they * are visible to a certain user, and/or using other criteria. - * - * @param array $where - * @param \Flarum\User\User|null $actor - * @param array $sort - * @param int $count - * @param int $start - * @return \Illuminate\Database\Eloquent\Collection */ - public function findWhere(array $where = [], User $actor = null, $sort = [], $count = null, $start = 0) + public function findWhere(array $where = [], User $actor = null, array $sort = [], int $count = null, int $start = 0): Collection { $query = $this->queryVisibleTo($actor) ->where($where) @@ -84,11 +71,9 @@ class PostRepository * Filter a list of post IDs to only include posts that are visible to a * certain user. * - * @param array $ids - * @param User $actor - * @return array + * @param int[] $ids */ - public function filterVisibleIds(array $ids, User $actor) + public function filterVisibleIds(array $ids, User $actor): array { return $this->queryIds($ids, $actor)->pluck('posts.id')->all(); } @@ -97,13 +82,8 @@ class PostRepository * Get the position within a discussion where a post with a certain number * is. If the post with that number does not exist, the index of the * closest post to it will be returned. - * - * @param int $discussionId - * @param int $number - * @param \Flarum\User\User|null $actor - * @return int */ - public function getIndexForNumber($discussionId, $number, User $actor = null) + public function getIndexForNumber(int $discussionId, int $number, ?User $actor = null): int { if (! ($discussion = Discussion::find($discussionId))) { return 0; @@ -127,11 +107,10 @@ class PostRepository } /** - * @param array $ids - * @param User|null $actor + * @param int[] $ids * @return Builder<Post> */ - protected function queryIds(array $ids, User $actor = null) + protected function queryIds(array $ids, User $actor = null): Builder { return $this->queryVisibleTo($actor)->whereIn('posts.id', $ids); } diff --git a/framework/core/src/Post/PostServiceProvider.php b/framework/core/src/Post/PostServiceProvider.php index bbc28c655..d4de174a8 100644 --- a/framework/core/src/Post/PostServiceProvider.php +++ b/framework/core/src/Post/PostServiceProvider.php @@ -16,10 +16,7 @@ use Illuminate\Contracts\Container\Container; class PostServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->extend('flarum.api.throttlers', function (array $throttlers, Container $container) { $throttlers['postTimeout'] = $container->make(PostCreationThrottler::class); @@ -28,7 +25,7 @@ class PostServiceProvider extends AbstractServiceProvider }); } - public function boot(Formatter $formatter) + public function boot(Formatter $formatter): void { CommentPost::setFormatter($formatter); @@ -37,7 +34,7 @@ class PostServiceProvider extends AbstractServiceProvider Post::registerVisibilityScoper(new ScopePostVisibility(), 'view'); } - protected function setPostTypes() + protected function setPostTypes(): void { $models = [ CommentPost::class, diff --git a/framework/core/src/Post/PostValidator.php b/framework/core/src/Post/PostValidator.php index 267cd4661..2018d9e11 100644 --- a/framework/core/src/Post/PostValidator.php +++ b/framework/core/src/Post/PostValidator.php @@ -13,7 +13,7 @@ use Flarum\Foundation\AbstractValidator; class PostValidator extends AbstractValidator { - protected $rules = [ + protected array $rules = [ 'content' => [ 'required', 'max:65535' diff --git a/framework/core/src/Post/RegisteredTypesScope.php b/framework/core/src/Post/RegisteredTypesScope.php index b4e0417b4..8c969a57f 100644 --- a/framework/core/src/Post/RegisteredTypesScope.php +++ b/framework/core/src/Post/RegisteredTypesScope.php @@ -18,8 +18,7 @@ class RegisteredTypesScope implements Scope /** * Apply the scope to a given Eloquent query builder. * - * @param Builder $builder - * @param Model $post + * @param Post $post */ public function apply(Builder $builder, Model $post) { diff --git a/framework/core/src/Query/AbstractQueryState.php b/framework/core/src/Query/AbstractQueryState.php index 257871961..0c9400f0f 100644 --- a/framework/core/src/Query/AbstractQueryState.php +++ b/framework/core/src/Query/AbstractQueryState.php @@ -9,63 +9,41 @@ namespace Flarum\Query; +use Closure; use Flarum\User\User; use Illuminate\Database\Query\Builder; abstract class AbstractQueryState { - /** - * @var Builder - */ - protected $query; - - /** - * @var User - */ - protected $actor; - - /** - * @var mixed - */ - protected $defaultSort = []; - - /** - * @param Builder $query - * @param User $actor - */ - public function __construct(Builder $query, User $actor, $defaultSort = []) - { - $this->query = $query; - $this->actor = $actor; - $this->defaultSort = $defaultSort; + public function __construct( + protected Builder $query, + protected User $actor, + /** + * An array of sort-order pairs, where the column + * is the key, and the order is the value. The order may be 'asc', + * 'desc', or an array of IDs to order by. + * Alternatively, a callable may be used. + * + * @var array<string, string|int[]>|Closure $defaultSort + */ + protected array|Closure $defaultSort = [] + ) { } /** * Get the query builder for the search results query. - * - * @return Builder */ - public function getQuery() + public function getQuery(): Builder { return $this->query; } - /** - * Get the user who is performing the search. - * - * @return User - */ - public function getActor() + public function getActor(): User { return $this->actor; } - /** - * Get the default sort order for the search. - * - * @return array - */ - public function getDefaultSort() + public function getDefaultSort(): array|Closure { return $this->defaultSort; } @@ -73,14 +51,8 @@ abstract class AbstractQueryState /** * Set the default sort order for the search. This will only be applied if * a sort order has not been specified in the search criteria. - * - * @param mixed $defaultSort An array of sort-order pairs, where the column - * is the key, and the order is the value. The order may be 'asc', - * 'desc', or an array of IDs to order by. - * Alternatively, a callable may be used. - * @return mixed */ - public function setDefaultSort($defaultSort) + public function setDefaultSort(array|Closure $defaultSort): void { $this->defaultSort = $defaultSort; } diff --git a/framework/core/src/Query/ApplyQueryParametersTrait.php b/framework/core/src/Query/ApplyQueryParametersTrait.php index a9a69fc6c..a6e1f7b88 100644 --- a/framework/core/src/Query/ApplyQueryParametersTrait.php +++ b/framework/core/src/Query/ApplyQueryParametersTrait.php @@ -18,12 +18,8 @@ trait ApplyQueryParametersTrait { /** * Apply sort criteria to a discussion query. - * - * @param AbstractQueryState $query - * @param array $sort - * @param bool $sortIsDefault */ - protected function applySort(AbstractQueryState $query, array $sort = null, bool $sortIsDefault = false) + protected function applySort(AbstractQueryState $query, ?array $sort = null, bool $sortIsDefault = false): void { if ($sortIsDefault && ! empty($query->getDefaultSort())) { $sort = $query->getDefaultSort(); @@ -44,22 +40,14 @@ trait ApplyQueryParametersTrait } } - /** - * @param AbstractQueryState $query - * @param int $offset - */ - protected function applyOffset(AbstractQueryState $query, $offset) + protected function applyOffset(AbstractQueryState $query, int $offset): void { if ($offset > 0) { $query->getQuery()->skip($offset); } } - /** - * @param AbstractQueryState $query - * @param int|null $limit - */ - protected function applyLimit(AbstractQueryState $query, $limit) + protected function applyLimit(AbstractQueryState $query, ?int $limit): void { if ($limit > 0) { $query->getQuery()->take($limit); diff --git a/framework/core/src/Query/QueryCriteria.php b/framework/core/src/Query/QueryCriteria.php index 2a286d36d..44d472821 100644 --- a/framework/core/src/Query/QueryCriteria.php +++ b/framework/core/src/Query/QueryCriteria.php @@ -18,49 +18,22 @@ use Flarum\User\User; */ class QueryCriteria { - /** - * The user performing the query. - * - * @var User - */ - public $actor; - - /** - * Query params. - * - * @var array - */ - public $query; - - /** - * An array of sort-order pairs, where the column is the key, and the order - * is the value. The order may be 'asc', 'desc', or an array of IDs to - * order by. - * - * @var array - */ - public $sort; - - /** - * Is the sort for this request the default sort from the controller? - * If false, the current request specifies a sort. - * - * @var bool - */ - public $sortIsDefault; - - /** - * @param User $actor The user performing the query. - * @param array $query The query params. - * @param array $sort An array of sort-order pairs, where the column is the - * key, and the order is the value. The order may be 'asc', 'desc', or - * an array of IDs to order by. - */ - public function __construct(User $actor, $query, array $sort = null, bool $sortIsDefault = false) - { - $this->actor = $actor; - $this->query = $query; - $this->sort = $sort; - $this->sortIsDefault = $sortIsDefault; + public function __construct( + public User $actor, + public array $query, + /** + * An array of sort-order pairs, where the column is the key, and the order + * is the value. The order may be 'asc', 'desc', or an array of IDs to + * order by. + * + * @var array<string, string|int[]> $sort + */ + public ?array $sort = null, + /** + * Is the sort for this request the default sort from the controller? + * If false, the current request specifies a sort. + */ + public bool $sortIsDefault = false + ) { } } diff --git a/framework/core/src/Query/QueryResults.php b/framework/core/src/Query/QueryResults.php index bf8fe5c32..a3882dce0 100644 --- a/framework/core/src/Query/QueryResults.php +++ b/framework/core/src/Query/QueryResults.php @@ -13,38 +13,18 @@ use Illuminate\Database\Eloquent\Collection; class QueryResults { - /** - * @var Collection - */ - protected $results; - - /** - * @var bool - */ - protected $areMoreResults; - - /** - * @param Collection $results - * @param bool $areMoreResults - */ - public function __construct(Collection $results, $areMoreResults) - { - $this->results = $results; - $this->areMoreResults = $areMoreResults; + public function __construct( + protected Collection $results, + protected bool $areMoreResults + ) { } - /** - * @return Collection - */ - public function getResults() + public function getResults(): Collection { return $this->results; } - /** - * @return bool - */ - public function areMoreResults() + public function areMoreResults(): bool { return $this->areMoreResults; } diff --git a/framework/core/src/Queue/ExceptionHandler.php b/framework/core/src/Queue/ExceptionHandler.php index 2870ac942..7bb575563 100644 --- a/framework/core/src/Queue/ExceptionHandler.php +++ b/framework/core/src/Queue/ExceptionHandler.php @@ -16,14 +16,9 @@ use Throwable; class ExceptionHandler implements ExceptionHandling { - /** - * @var LoggerInterface - */ - private $logger; - - public function __construct(LoggerInterface $logger) - { - $this->logger = $logger; + public function __construct( + private readonly LoggerInterface $logger + ) { } /** diff --git a/framework/core/src/Queue/QueueFactory.php b/framework/core/src/Queue/QueueFactory.php index cb6ae9c50..9701189be 100644 --- a/framework/core/src/Queue/QueueFactory.php +++ b/framework/core/src/Queue/QueueFactory.php @@ -9,40 +9,31 @@ namespace Flarum\Queue; +use Closure; use Illuminate\Contracts\Queue\Factory; +use Illuminate\Contracts\Queue\Queue; class QueueFactory implements Factory { - /** - * @var callable - */ - private $factory; - /** * The cached queue instance. - * - * @var \Illuminate\Contracts\Queue\Queue|null */ - private $queue; + private ?Queue $queue; /** - * QueueFactory constructor. - * * Expects a callback that will be called to instantiate the queue adapter, * once requested by the application. - * - * @param callable $factory */ - public function __construct(callable $factory) - { - $this->factory = $factory; + public function __construct( + private readonly Closure $factory + ) { } /** * Resolve a queue connection instance. * * @param string $name - * @return \Illuminate\Contracts\Queue\Queue + * @return Queue */ public function connection($name = null) { diff --git a/framework/core/src/Queue/QueueRestarter.php b/framework/core/src/Queue/QueueRestarter.php index a168ee48d..f2e7a71fe 100644 --- a/framework/core/src/Queue/QueueRestarter.php +++ b/framework/core/src/Queue/QueueRestarter.php @@ -21,31 +21,21 @@ use Symfony\Component\Console\Output\NullOutput; class QueueRestarter { - /** - * @var Container - */ - protected $container; - - /** - * @var RestartCommand - */ - protected $command; - - public function __construct(Container $container, RestartCommand $command) - { - $this->container = $container; - $this->command = $command; + public function __construct( + protected Container $container, + protected RestartCommand $command + ) { } - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { $events->listen([ ClearingCache::class, Saved::class, Enabled::class, Disabled::class - ], [$this, 'restart']); + ], $this->restart(...)); } - public function restart() + public function restart(): void { $this->command->setLaravel($this->container); diff --git a/framework/core/src/Queue/QueueServiceProvider.php b/framework/core/src/Queue/QueueServiceProvider.php index b813b62d7..4d19b30fc 100644 --- a/framework/core/src/Queue/QueueServiceProvider.php +++ b/framework/core/src/Queue/QueueServiceProvider.php @@ -31,7 +31,7 @@ use Illuminate\Queue\Worker; class QueueServiceProvider extends AbstractServiceProvider { - protected $commands = [ + protected array $commands = [ Commands\FlushFailedCommand::class, Commands\ForgetFailedCommand::class, Console\ListenCommand::class, @@ -41,7 +41,7 @@ class QueueServiceProvider extends AbstractServiceProvider Console\WorkCommand::class, ]; - public function register() + public function register(): void { // Register a simple connection factory that always returns the same // connection, as that is enough for our purposes. @@ -134,7 +134,7 @@ class QueueServiceProvider extends AbstractServiceProvider $this->registerCommands(); } - protected function registerCommands() + protected function registerCommands(): void { $this->container->extend('flarum.console.commands', function ($commands, Container $container) { $queue = $container->make(Queue::class); @@ -150,7 +150,7 @@ class QueueServiceProvider extends AbstractServiceProvider }); } - public function boot(Dispatcher $events, Container $container) + public function boot(Dispatcher $events, Container $container): void { $events->listen(JobFailed::class, function (JobFailed $event) use ($container) { /** @var Registry $registry */ diff --git a/framework/core/src/Search/AbstractRegexGambit.php b/framework/core/src/Search/AbstractRegexGambit.php index 3f3294e6c..937284217 100644 --- a/framework/core/src/Search/AbstractRegexGambit.php +++ b/framework/core/src/Search/AbstractRegexGambit.php @@ -14,12 +14,9 @@ abstract class AbstractRegexGambit implements GambitInterface /** * The regex pattern to match the bit against. */ - abstract protected function getGambitPattern(); + abstract protected function getGambitPattern(): string; - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $bit) + public function apply(SearchState $search, string $bit): bool { if ($matches = $this->match($bit)) { list($negate) = array_splice($matches, 1, 1); @@ -32,11 +29,8 @@ abstract class AbstractRegexGambit implements GambitInterface /** * Match the bit against this gambit. - * - * @param string $bit - * @return array|null */ - protected function match($bit) + protected function match(string $bit): ?array { if (! empty($bit) && preg_match('/^(-?)'.$this->getGambitPattern().'$/i', $bit, $matches)) { return $matches; @@ -48,11 +42,8 @@ abstract class AbstractRegexGambit implements GambitInterface /** * Apply conditions to the search, given that the gambit was matched. * - * @param SearchState $search The search object. * @param array $matches An array of matches from the search bit. - * @param bool $negate Whether or not the bit was negated, and thus whether - * or not the conditions should be negated. - * @return mixed + * @param bool $negate Whether the bit was negated, and thus whether the conditions should be negated. */ - abstract protected function conditions(SearchState $search, array $matches, $negate); + abstract protected function conditions(SearchState $search, array $matches, bool $negate): void; } diff --git a/framework/core/src/Search/AbstractSearcher.php b/framework/core/src/Search/AbstractSearcher.php index a5fbb244b..a59408a91 100644 --- a/framework/core/src/Search/AbstractSearcher.php +++ b/framework/core/src/Search/AbstractSearcher.php @@ -19,32 +19,15 @@ abstract class AbstractSearcher { use ApplyQueryParametersTrait; - /** - * @var GambitManager - */ - protected $gambits; - - /** - * @var array - */ - protected $searchMutators; - - public function __construct(GambitManager $gambits, array $searchMutators) - { - $this->gambits = $gambits; - $this->searchMutators = $searchMutators; + public function __construct( + protected GambitManager $gambits, + protected array $searchMutators + ) { } abstract protected function getQuery(User $actor): Builder; - /** - * @param QueryCriteria $criteria - * @param int|null $limit - * @param int $offset - * - * @return QueryResults - */ - public function search(QueryCriteria $criteria, $limit = null, $offset = 0): QueryResults + public function search(QueryCriteria $criteria, ?int $limit = null, int $offset = 0): QueryResults { $actor = $criteria->actor; diff --git a/framework/core/src/Search/GambitInterface.php b/framework/core/src/Search/GambitInterface.php index cbb691e63..99fb01729 100644 --- a/framework/core/src/Search/GambitInterface.php +++ b/framework/core/src/Search/GambitInterface.php @@ -14,9 +14,8 @@ interface GambitInterface /** * Apply conditions to the searcher for a bit of the search string. * - * @param SearchState $search * @param string $bit The piece of the search string. - * @return bool Whether or not the gambit was active for this bit. + * @return bool Whether the gambit was active for this bit. */ - public function apply(SearchState $search, $bit); + public function apply(SearchState $search, string $bit): bool; } diff --git a/framework/core/src/Search/GambitManager.php b/framework/core/src/Search/GambitManager.php index 9429d03c1..cb0a98864 100644 --- a/framework/core/src/Search/GambitManager.php +++ b/framework/core/src/Search/GambitManager.php @@ -16,38 +16,22 @@ use LogicException; */ class GambitManager { - /** - * @var array - */ - protected $gambits = []; + protected array $gambits = []; - /** - * @var GambitInterface - */ - protected $fulltextGambit; - - public function __construct(GambitInterface $fulltextGambit) - { - $this->fulltextGambit = $fulltextGambit; + public function __construct( + protected GambitInterface $fulltextGambit + ) { } - /** - * Add a gambit. - * - * @param GambitInterface $gambit - */ - public function add(GambitInterface $gambit) + public function add(GambitInterface $gambit): void { $this->gambits[] = $gambit; } /** * Apply gambits to a search, given a search query. - * - * @param SearchState $search - * @param string $query */ - public function apply(SearchState $search, $query) + public function apply(SearchState $search, string $query): void { $query = $this->applyGambits($search, $query); @@ -58,21 +42,13 @@ class GambitManager /** * Explode a search query into an array of bits. - * - * @param string $query - * @return array */ - protected function explode($query) + protected function explode(string $query): array { return str_getcsv($query, ' '); } - /** - * @param SearchState $search - * @param string $query - * @return string - */ - protected function applyGambits(SearchState $search, $query) + protected function applyGambits(SearchState $search, string $query): string { $bits = $this->explode($query); @@ -99,11 +75,7 @@ class GambitManager return implode(' ', $bits); } - /** - * @param SearchState $search - * @param string $query - */ - protected function applyFulltext(SearchState $search, $query) + protected function applyFulltext(SearchState $search, string $query): void { $search->addActiveGambit($this->fulltextGambit); $this->fulltextGambit->apply($search, $query); diff --git a/framework/core/src/Search/SearchServiceProvider.php b/framework/core/src/Search/SearchServiceProvider.php index 26035c694..65d1eb275 100644 --- a/framework/core/src/Search/SearchServiceProvider.php +++ b/framework/core/src/Search/SearchServiceProvider.php @@ -22,10 +22,7 @@ use Illuminate\Support\Arr; class SearchServiceProvider extends AbstractServiceProvider { - /** - * @inheritDoc - */ - public function register() + public function register(): void { $this->container->singleton('flarum.simple_search.fulltext_gambits', function () { return [ @@ -54,7 +51,7 @@ class SearchServiceProvider extends AbstractServiceProvider }); } - public function boot(Container $container) + public function boot(Container $container): void { $fullTextGambits = $container->make('flarum.simple_search.fulltext_gambits'); diff --git a/framework/core/src/Search/SearchState.php b/framework/core/src/Search/SearchState.php index 392cc99a1..bee14cb8b 100644 --- a/framework/core/src/Search/SearchState.php +++ b/framework/core/src/Search/SearchState.php @@ -16,25 +16,22 @@ class SearchState extends AbstractQueryState /** * @var GambitInterface[] */ - protected $activeGambits = []; + protected array $activeGambits = []; /** * Get a list of the gambits that are active in this search. * * @return GambitInterface[] */ - public function getActiveGambits() + public function getActiveGambits(): array { return $this->activeGambits; } /** * Add a gambit as being active in this search. - * - * @param GambitInterface $gambit - * @return void */ - public function addActiveGambit(GambitInterface $gambit) + public function addActiveGambit(GambitInterface $gambit): void { $this->activeGambits[] = $gambit; } diff --git a/framework/core/src/Settings/DatabaseSettingsRepository.php b/framework/core/src/Settings/DatabaseSettingsRepository.php index 44d1495ca..801d0c7e9 100644 --- a/framework/core/src/Settings/DatabaseSettingsRepository.php +++ b/framework/core/src/Settings/DatabaseSettingsRepository.php @@ -13,11 +13,9 @@ use Illuminate\Database\ConnectionInterface; class DatabaseSettingsRepository implements SettingsRepositoryInterface { - protected $database; - - public function __construct(ConnectionInterface $connection) - { - $this->database = $connection; + public function __construct( + protected ConnectionInterface $database + ) { } public function all(): array @@ -25,7 +23,7 @@ class DatabaseSettingsRepository implements SettingsRepositoryInterface return $this->database->table('settings')->pluck('value', 'key')->all(); } - public function get($key, $default = null) + public function get(string $key, $default = null): mixed { if (is_null($value = $this->database->table('settings')->where('key', $key)->value('value'))) { return $default; @@ -34,7 +32,7 @@ class DatabaseSettingsRepository implements SettingsRepositoryInterface return $value; } - public function set($key, $value) + public function set(string $key, mixed $value): void { $query = $this->database->table('settings')->where('key', $key); @@ -43,8 +41,8 @@ class DatabaseSettingsRepository implements SettingsRepositoryInterface $query->$method(compact('key', 'value')); } - public function delete($key) + public function delete(string $keyLike): void { - $this->database->table('settings')->where('key', $key)->delete(); + $this->database->table('settings')->where('key', $keyLike)->delete(); } } diff --git a/framework/core/src/Settings/DefaultSettingsRepository.php b/framework/core/src/Settings/DefaultSettingsRepository.php index ad5300cf0..ee0235fa3 100644 --- a/framework/core/src/Settings/DefaultSettingsRepository.php +++ b/framework/core/src/Settings/DefaultSettingsRepository.php @@ -13,29 +13,25 @@ use Illuminate\Support\Collection; class DefaultSettingsRepository implements SettingsRepositoryInterface { - protected $defaults; - - private $inner; - - public function __construct(SettingsRepositoryInterface $inner, Collection $defaults) - { - $this->inner = $inner; - $this->defaults = $defaults; + public function __construct( + private readonly SettingsRepositoryInterface $inner, + protected Collection $defaults + ) { } - public function get($key, $default = null) + public function get(string $key, $default = null): mixed { // Global default overrules local default because local default is deprecated, // and will be removed in 2.0 return $this->inner->get($key, $this->defaults->get($key, $default)); } - public function set($key, $value) + public function set(string $key, mixed $value): void { $this->inner->set($key, $value); } - public function delete($keyLike) + public function delete(string $keyLike): void { $this->inner->delete($keyLike); } diff --git a/framework/core/src/Settings/Event/Deserializing.php b/framework/core/src/Settings/Event/Deserializing.php index afdb6d4b3..1574debd3 100644 --- a/framework/core/src/Settings/Event/Deserializing.php +++ b/framework/core/src/Settings/Event/Deserializing.php @@ -17,18 +17,11 @@ namespace Flarum\Settings\Event; */ class Deserializing { - /** - * The settings array to be unserialized. - * - * @var array - */ - public $settings; - - /** - * @param array $settings The settings array to be unserialized. - */ - public function __construct(&$settings) - { - $this->settings = &$settings; + public function __construct( + /** + * The settings array to be unserialized. + */ + public array &$settings + ) { } } diff --git a/framework/core/src/Settings/Event/Saved.php b/framework/core/src/Settings/Event/Saved.php index 11f13de97..3321c338a 100644 --- a/framework/core/src/Settings/Event/Saved.php +++ b/framework/core/src/Settings/Event/Saved.php @@ -11,16 +11,8 @@ namespace Flarum\Settings\Event; class Saved { - /** - * @var array - */ - public $settings; - - /** - * @param array $settings - */ - public function __construct(array $settings) - { - $this->settings = $settings; + public function __construct( + public array $settings + ) { } } diff --git a/framework/core/src/Settings/Event/Saving.php b/framework/core/src/Settings/Event/Saving.php index 82a0635cd..f10420024 100644 --- a/framework/core/src/Settings/Event/Saving.php +++ b/framework/core/src/Settings/Event/Saving.php @@ -11,16 +11,8 @@ namespace Flarum\Settings\Event; class Saving { - /** - * @var array - */ - public $settings; - - /** - * @param array $settings - */ - public function __construct(array &$settings) - { - $this->settings = &$settings; + public function __construct( + public array &$settings + ) { } } diff --git a/framework/core/src/Settings/Event/Serializing.php b/framework/core/src/Settings/Event/Serializing.php index 725079e96..ad91441f8 100644 --- a/framework/core/src/Settings/Event/Serializing.php +++ b/framework/core/src/Settings/Event/Serializing.php @@ -11,27 +11,15 @@ namespace Flarum\Settings\Event; class Serializing { - /** - * The settings key being saved. - * - * @var string - */ - public $key; - - /** - * The settings value to save. - * - * @var string - */ - public $value; - - /** - * @param string $key The settings key being saved. - * @param string $value The settings value to save. - */ - public function __construct($key, &$value) - { - $this->key = $key; - $this->value = &$value; + public function __construct( + /** + * The settings key being saved. + */ + public string $key, + /** + * The settings value to save. + */ + public string &$value + ) { } } diff --git a/framework/core/src/Settings/MemoryCacheSettingsRepository.php b/framework/core/src/Settings/MemoryCacheSettingsRepository.php index 1328e282e..b045fa123 100644 --- a/framework/core/src/Settings/MemoryCacheSettingsRepository.php +++ b/framework/core/src/Settings/MemoryCacheSettingsRepository.php @@ -13,15 +13,12 @@ use Illuminate\Support\Arr; class MemoryCacheSettingsRepository implements SettingsRepositoryInterface { - protected $inner; + protected bool $isCached = false; + protected array $cache = []; - protected $isCached; - - protected $cache = []; - - public function __construct(SettingsRepositoryInterface $inner) - { - $this->inner = $inner; + public function __construct( + protected SettingsRepositoryInterface $inner + ) { } public function all(): array @@ -34,7 +31,7 @@ class MemoryCacheSettingsRepository implements SettingsRepositoryInterface return $this->cache; } - public function get($key, $default = null) + public function get(string $key, $default = null): mixed { if (array_key_exists($key, $this->cache)) { return $this->cache[$key]; @@ -45,17 +42,17 @@ class MemoryCacheSettingsRepository implements SettingsRepositoryInterface return $default; } - public function set($key, $value) + public function set(string $key, mixed $value): void { $this->cache[$key] = $value; $this->inner->set($key, $value); } - public function delete($key) + public function delete(string $keyLike): void { - unset($this->cache[$key]); + unset($this->cache[$keyLike]); - $this->inner->delete($key); + $this->inner->delete($keyLike); } } diff --git a/framework/core/src/Settings/OverrideSettingsRepository.php b/framework/core/src/Settings/OverrideSettingsRepository.php index 4f735c0ba..efc9468ef 100644 --- a/framework/core/src/Settings/OverrideSettingsRepository.php +++ b/framework/core/src/Settings/OverrideSettingsRepository.php @@ -25,14 +25,10 @@ use Illuminate\Support\Arr; */ class OverrideSettingsRepository implements SettingsRepositoryInterface { - protected $inner; - - protected $overrides = []; - - public function __construct(SettingsRepositoryInterface $inner, array $overrides) - { - $this->inner = $inner; - $this->overrides = $overrides; + public function __construct( + protected SettingsRepositoryInterface $inner, + protected array $overrides + ) { } public function all(): array @@ -40,7 +36,7 @@ class OverrideSettingsRepository implements SettingsRepositoryInterface return array_merge($this->inner->all(), $this->overrides); } - public function get($key, $default = null) + public function get(string $key, $default = null): mixed { if (array_key_exists($key, $this->overrides)) { return $this->overrides[$key]; @@ -49,13 +45,13 @@ class OverrideSettingsRepository implements SettingsRepositoryInterface return Arr::get($this->all(), $key, $default); } - public function set($key, $value) + public function set(string $key, mixed $value): void { $this->inner->set($key, $value); } - public function delete($key) + public function delete(string $keyLike): void { - $this->inner->delete($key); + $this->inner->delete($keyLike); } } diff --git a/framework/core/src/Settings/SettingsRepositoryInterface.php b/framework/core/src/Settings/SettingsRepositoryInterface.php index b96a95cde..0c6e4c42f 100644 --- a/framework/core/src/Settings/SettingsRepositoryInterface.php +++ b/framework/core/src/Settings/SettingsRepositoryInterface.php @@ -14,15 +14,11 @@ interface SettingsRepositoryInterface public function all(): array; /** - * @todo remove $default in 2.0 - * - * @param $key - * @param mixed $default: Deprecated - * @return mixed + * @todo remove deprecated $default in 2.0 */ - public function get($key, $default = null); + public function get(string $key, $default = null): mixed; - public function set($key, $value); + public function set(string $key, mixed $value): void; - public function delete($keyLike); + public function delete(string $keyLike): void; } diff --git a/framework/core/src/Settings/SettingsServiceProvider.php b/framework/core/src/Settings/SettingsServiceProvider.php index 942d842c9..ff8fd02cb 100644 --- a/framework/core/src/Settings/SettingsServiceProvider.php +++ b/framework/core/src/Settings/SettingsServiceProvider.php @@ -18,10 +18,7 @@ use Illuminate\Support\Collection; class SettingsServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.settings.default', function () { return new Collection([ @@ -44,7 +41,7 @@ class SettingsServiceProvider extends AbstractServiceProvider $this->container->alias(SettingsRepositoryInterface::class, 'flarum.settings'); } - public function boot(Dispatcher $events, SettingsValidator $settingsValidator) + public function boot(Dispatcher $events, SettingsValidator $settingsValidator): void { $events->listen( Saving::class, diff --git a/framework/core/src/Settings/SettingsValidator.php b/framework/core/src/Settings/SettingsValidator.php index f967cf40f..8819391e8 100644 --- a/framework/core/src/Settings/SettingsValidator.php +++ b/framework/core/src/Settings/SettingsValidator.php @@ -10,6 +10,7 @@ namespace Flarum\Settings; use Flarum\Foundation\AbstractValidator; +use Illuminate\Validation\Validator; class SettingsValidator extends AbstractValidator { @@ -18,20 +19,12 @@ class SettingsValidator extends AbstractValidator * * Entries in the default DB settings table are limited to 65,000 * characters. We validate against this to avoid confusing errors. - * - * @var array */ - protected $globalRules = [ + protected array $globalRules = [ 'max:65000', ]; - /** - * Make a new validator instance for this model. - * - * @param array $attributes - * @return \Illuminate\Validation\Validator - */ - protected function makeValidator(array $attributes) + protected function makeValidator(array $attributes): Validator { // Apply global rules first. $rules = array_map(function () { diff --git a/framework/core/src/Settings/UninstalledSettingsRepository.php b/framework/core/src/Settings/UninstalledSettingsRepository.php index de1675350..e602180af 100644 --- a/framework/core/src/Settings/UninstalledSettingsRepository.php +++ b/framework/core/src/Settings/UninstalledSettingsRepository.php @@ -16,17 +16,17 @@ class UninstalledSettingsRepository implements SettingsRepositoryInterface return []; } - public function get($key, $default = null) + public function get(string $key, $default = null): mixed { return $default; } - public function set($key, $value) + public function set(string $key, mixed $value): void { // Do nothing } - public function delete($keyLike) + public function delete(string $keyLike): void { // Do nothing } diff --git a/framework/core/src/Update/Controller/IndexController.php b/framework/core/src/Update/Controller/IndexController.php index d499e2c22..c9ae10579 100644 --- a/framework/core/src/Update/Controller/IndexController.php +++ b/framework/core/src/Update/Controller/IndexController.php @@ -10,25 +10,18 @@ namespace Flarum\Update\Controller; use Flarum\Http\Controller\AbstractHtmlController; +use Illuminate\Contracts\Support\Renderable; use Illuminate\Contracts\View\Factory; use Psr\Http\Message\ServerRequestInterface as Request; class IndexController extends AbstractHtmlController { - /** - * @var Factory - */ - protected $view; - - /** - * @param Factory $view - */ - public function __construct(Factory $view) - { - $this->view = $view; + public function __construct( + protected Factory $view + ) { } - public function render(Request $request) + public function render(Request $request): Renderable|string { $view = $this->view->make('flarum.update::app')->with('title', 'Update Flarum'); diff --git a/framework/core/src/Update/Controller/UpdateController.php b/framework/core/src/Update/Controller/UpdateController.php index 5b5bf4959..d018664be 100644 --- a/framework/core/src/Update/Controller/UpdateController.php +++ b/framework/core/src/Update/Controller/UpdateController.php @@ -23,27 +23,12 @@ use Symfony\Component\Console\Output\StreamOutput; class UpdateController implements RequestHandlerInterface { - protected $command; - - /** - * @var Config - */ - protected $config; - - /** - * @param MigrateCommand $command - * @param Config $config - */ - public function __construct(MigrateCommand $command, Config $config) - { - $this->command = $command; - $this->config = $config; + public function __construct( + protected MigrateCommand $command, + protected Config $config + ) { } - /** - * @param Request $request - * @return ResponseInterface - */ public function handle(Request $request): ResponseInterface { $input = $request->getParsedBody(); diff --git a/framework/core/src/Update/UpdateServiceProvider.php b/framework/core/src/Update/UpdateServiceProvider.php index 1083e190b..42f08567a 100644 --- a/framework/core/src/Update/UpdateServiceProvider.php +++ b/framework/core/src/Update/UpdateServiceProvider.php @@ -16,10 +16,7 @@ use Illuminate\Contracts\Container\Container; class UpdateServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.update.routes', function (Container $container) { $routes = new RouteCollection; @@ -30,16 +27,12 @@ class UpdateServiceProvider extends AbstractServiceProvider }); } - public function boot() + public function boot(): void { $this->loadViewsFrom(__DIR__.'/../../views/install', 'flarum.update'); } - /** - * @param RouteCollection $routes - * @param RouteHandlerFactory $route - */ - protected function populateRoutes(RouteCollection $routes, RouteHandlerFactory $route) + protected function populateRoutes(RouteCollection $routes, RouteHandlerFactory $route): void { $routes->get( '/{path:.*}', diff --git a/framework/core/src/User/Access/AbstractPolicy.php b/framework/core/src/User/Access/AbstractPolicy.php index c9d188085..e1166e006 100644 --- a/framework/core/src/User/Access/AbstractPolicy.php +++ b/framework/core/src/User/Access/AbstractPolicy.php @@ -19,29 +19,26 @@ abstract class AbstractPolicy public const FORCE_ALLOW = 'FORCE_ALLOW'; public const FORCE_DENY = 'FORCE_DENY'; - protected function allow() + protected function allow(): string { return static::ALLOW; } - protected function deny() + protected function deny(): string { return static::DENY; } - protected function forceAllow() + protected function forceAllow(): string { return static::FORCE_ALLOW; } - protected function forceDeny() + protected function forceDeny(): string { return static::FORCE_DENY; } - /** - * @return string|void - */ public function checkAbility(User $actor, string $ability, $instance) { // If a specific method for this ability is defined, @@ -69,11 +66,8 @@ abstract class AbstractPolicy * * WITH THIS: * `return SOME_BOOLEAN_LOGIC; - * - * @param mixed $result - * @return string|void|null */ - public function sanitizeResult($result) + public function sanitizeResult(string|bool|null $result): ?string { if ($result === true) { return $this->allow(); diff --git a/framework/core/src/User/Access/Gate.php b/framework/core/src/User/Access/Gate.php index e8eaab1a3..75f01a688 100644 --- a/framework/core/src/User/Access/Gate.php +++ b/framework/core/src/User/Access/Gate.php @@ -27,39 +27,23 @@ class Gate ]; /** - * @var Container + * @var AbstractPolicy[] */ - protected $container; + protected array $policies = []; - /** - * @var array - */ - protected $policyClasses; - - /** - * @var array - */ - protected $policies; - - /** - * @param Container $container - * @param array $policyClasses - */ - public function __construct(Container $container, array $policyClasses) - { - $this->container = $container; - $this->policyClasses = $policyClasses; + public function __construct( + protected Container $container, + /** @var class-string<AbstractPolicy>[] $policyClasses */ + protected array $policyClasses + ) { } /** * Determine if the given ability should be granted for the current user. * - * @param User $actor - * @param string $ability - * @param string|AbstractModel $model - * @return bool + * @param class-string<AbstractModel>|AbstractModel|null $model */ - public function allows(User $actor, string $ability, $model): bool + public function allows(User $actor, string $ability, string|AbstractModel|null $model): bool { $results = []; $appliedPolicies = []; @@ -97,9 +81,10 @@ class Gate /** * Get all policies for a given model and ability. */ - protected function getPolicies(string $model) + protected function getPolicies(string $model): array { $compiledPolicies = Arr::get($this->policies, $model); + if (is_null($compiledPolicies)) { $policyClasses = Arr::get($this->policyClasses, $model, []); $compiledPolicies = array_map(function ($policyClass) { diff --git a/framework/core/src/User/Access/ScopeUserVisibility.php b/framework/core/src/User/Access/ScopeUserVisibility.php index 4fb1ef929..9d119c134 100644 --- a/framework/core/src/User/Access/ScopeUserVisibility.php +++ b/framework/core/src/User/Access/ScopeUserVisibility.php @@ -14,11 +14,7 @@ use Illuminate\Database\Eloquent\Builder; class ScopeUserVisibility { - /** - * @param User $actor - * @param Builder $query - */ - public function __invoke(User $actor, $query) + public function __invoke(User $actor, Builder $query): void { if ($actor->cannot('viewForum')) { if ($actor->isGuest()) { diff --git a/framework/core/src/User/Access/UserPolicy.php b/framework/core/src/User/Access/UserPolicy.php index 274c9aaa5..2fd137df0 100644 --- a/framework/core/src/User/Access/UserPolicy.php +++ b/framework/core/src/User/Access/UserPolicy.php @@ -13,22 +13,13 @@ use Flarum\User\User; class UserPolicy extends AbstractPolicy { - /** - * @param User $actor - * @param string $ability - * @return bool|null - */ - public function can(User $actor, $ability) + public function can(User $actor, string $ability) { if ($actor->hasPermission('user.'.$ability)) { return $this->allow(); } } - /** - * @param User $actor - * @param User $user - */ public function editCredentials(User $actor, User $user) { if ($user->isAdmin() && ! $actor->isAdmin()) { diff --git a/framework/core/src/User/AccountActivationMailer.php b/framework/core/src/User/AccountActivationMailer.php index 958539143..4e1dc341e 100644 --- a/framework/core/src/User/AccountActivationMailer.php +++ b/framework/core/src/User/AccountActivationMailer.php @@ -10,50 +10,24 @@ namespace Flarum\User; use Flarum\Http\UrlGenerator; +use Flarum\Locale\TranslatorInterface; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\Event\Registered; use Illuminate\Contracts\Queue\Queue; -use Symfony\Contracts\Translation\TranslatorInterface; class AccountActivationMailer { use AccountActivationMailerTrait; - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Queue - */ - protected $queue; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @param \Flarum\Settings\SettingsRepositoryInterface $settings - * @param Queue $queue - * @param UrlGenerator $url - * @param TranslatorInterface $translator - */ - public function __construct(SettingsRepositoryInterface $settings, Queue $queue, UrlGenerator $url, TranslatorInterface $translator) - { - $this->settings = $settings; - $this->queue = $queue; - $this->url = $url; - $this->translator = $translator; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected Queue $queue, + protected UrlGenerator $url, + protected TranslatorInterface $translator + ) { } - public function handle(Registered $event) + public function handle(Registered $event): void { $user = $event->user; diff --git a/framework/core/src/User/AccountActivationMailerTrait.php b/framework/core/src/User/AccountActivationMailerTrait.php index 1077ca4cc..f7194e831 100644 --- a/framework/core/src/User/AccountActivationMailerTrait.php +++ b/framework/core/src/User/AccountActivationMailerTrait.php @@ -13,12 +13,7 @@ use Flarum\Mail\Job\SendRawEmailJob; trait AccountActivationMailerTrait { - /** - * @param User $user - * @param string $email - * @return EmailToken - */ - protected function generateToken(User $user, $email) + protected function generateToken(User $user, string $email): EmailToken { $token = EmailToken::generate($email, $user->id); $token->save(); @@ -28,12 +23,8 @@ trait AccountActivationMailerTrait /** * Get the data that should be made available to email templates. - * - * @param User $user - * @param EmailToken $token - * @return array */ - protected function getEmailData(User $user, EmailToken $token) + protected function getEmailData(User $user, EmailToken $token): array { return [ 'username' => $user->display_name, @@ -42,11 +33,7 @@ trait AccountActivationMailerTrait ]; } - /** - * @param User $user - * @param array $data - */ - protected function sendConfirmationEmail(User $user, $data) + protected function sendConfirmationEmail(User $user, array $data): void { $body = $this->translator->trans('core.email.activate_account.body', $data); $subject = $this->translator->trans('core.email.activate_account.subject'); diff --git a/framework/core/src/User/AvatarUploader.php b/framework/core/src/User/AvatarUploader.php index 26d6b03cc..443b9e69c 100644 --- a/framework/core/src/User/AvatarUploader.php +++ b/framework/core/src/User/AvatarUploader.php @@ -16,21 +16,14 @@ use Intervention\Image\Image; class AvatarUploader { - /** - * @var Filesystem - */ - protected $uploadDir; + protected Filesystem $uploadDir; public function __construct(Factory $filesystemFactory) { $this->uploadDir = $filesystemFactory->disk('flarum-avatars'); } - /** - * @param User $user - * @param Image $image - */ - public function upload(User $user, Image $image) + public function upload(User $user, Image $image): void { if (extension_loaded('exif')) { $image->orientate(); @@ -49,9 +42,8 @@ class AvatarUploader /** * Handle the removal of the old avatar file after a successful user save * We don't place this in remove() because otherwise we would call changeAvatarPath 2 times when uploading. - * @param User $user */ - protected function removeFileAfterSave(User $user) + protected function removeFileAfterSave(User $user): void { $avatarPath = $user->getRawOriginal('avatar_url'); @@ -67,10 +59,7 @@ class AvatarUploader }); } - /** - * @param User $user - */ - public function remove(User $user) + public function remove(User $user): void { $this->removeFileAfterSave($user); diff --git a/framework/core/src/User/AvatarValidator.php b/framework/core/src/User/AvatarValidator.php index cf42ef45c..15b237133 100644 --- a/framework/core/src/User/AvatarValidator.php +++ b/framework/core/src/User/AvatarValidator.php @@ -11,38 +11,27 @@ namespace Flarum\User; use Flarum\Foundation\AbstractValidator; use Flarum\Foundation\ValidationException; +use Flarum\Locale\TranslatorInterface; use Illuminate\Validation\Factory; +use Illuminate\Validation\Validator; use Intervention\Image\Exception\NotReadableException; use Intervention\Image\ImageManager; use Psr\Http\Message\UploadedFileInterface; use Symfony\Component\Mime\MimeTypes; -use Symfony\Contracts\Translation\TranslatorInterface; class AvatarValidator extends AbstractValidator { - /** - * @var \Illuminate\Validation\Validator - */ - protected $laravelValidator; + protected Validator $laravelValidator; - /** - * @var ImageManager - */ - protected $imageManager; - - public function __construct(Factory $validator, TranslatorInterface $translator, ImageManager $imageManager) - { + public function __construct( + Factory $validator, + TranslatorInterface $translator, + protected ImageManager $imageManager + ) { parent::__construct($validator, $translator); - - $this->imageManager = $imageManager; } - /** - * Throw an exception if a model is not valid. - * - * @param array $attributes - */ - public function assertValid(array $attributes) + public function assertValid(array $attributes): void { $this->laravelValidator = $this->makeValidator($attributes); @@ -51,7 +40,7 @@ class AvatarValidator extends AbstractValidator $this->assertFileSize($attributes['avatar']); } - protected function assertFileRequired(UploadedFileInterface $file) + protected function assertFileRequired(UploadedFileInterface $file): void { $error = $file->getError(); @@ -68,7 +57,7 @@ class AvatarValidator extends AbstractValidator } } - protected function assertFileMimes(UploadedFileInterface $file) + protected function assertFileMimes(UploadedFileInterface $file): void { $allowedTypes = $this->getAllowedTypes(); @@ -93,7 +82,7 @@ class AvatarValidator extends AbstractValidator } } - protected function assertFileSize(UploadedFileInterface $file) + protected function assertFileSize(UploadedFileInterface $file): void { $maxSize = $this->getMaxSize(); @@ -102,11 +91,11 @@ class AvatarValidator extends AbstractValidator } } - protected function raise($error, array $parameters = [], $rule = null) + protected function raise($error, array $parameters = [], $rule = null): void { // When we switched to intl ICU message format, the translation parameters // have become required to be in the format `{param}`. - // Therefore we cannot use the translator to replace the string params. + // Therefore, we cannot use the translator to replace the string params. // We use the laravel validator to make the replacements instead. $message = $this->laravelValidator->makeReplacements( $this->translator->trans("validation.$error"), @@ -118,12 +107,12 @@ class AvatarValidator extends AbstractValidator throw new ValidationException(['avatar' => $message]); } - protected function getMaxSize() + protected function getMaxSize(): int { return 2048; } - protected function getAllowedTypes() + protected function getAllowedTypes(): array { return ['jpeg', 'jpg', 'png', 'bmp', 'gif']; } diff --git a/framework/core/src/User/Command/ConfirmEmail.php b/framework/core/src/User/Command/ConfirmEmail.php index 76070636a..626653a46 100644 --- a/framework/core/src/User/Command/ConfirmEmail.php +++ b/framework/core/src/User/Command/ConfirmEmail.php @@ -11,18 +11,11 @@ namespace Flarum\User\Command; class ConfirmEmail { - /** - * The email confirmation token. - * - * @var string - */ - public $token; - - /** - * @param string $token The email confirmation token. - */ - public function __construct($token) - { - $this->token = $token; + public function __construct( + /** + * The email confirmation token. + */ + public string $token + ) { } } diff --git a/framework/core/src/User/Command/ConfirmEmailHandler.php b/framework/core/src/User/Command/ConfirmEmailHandler.php index 16a691409..1c2bd75fe 100644 --- a/framework/core/src/User/Command/ConfirmEmailHandler.php +++ b/framework/core/src/User/Command/ConfirmEmailHandler.php @@ -11,6 +11,7 @@ namespace Flarum\User\Command; use Flarum\Foundation\DispatchEventsTrait; use Flarum\User\EmailToken; +use Flarum\User\User; use Flarum\User\UserRepository; use Illuminate\Contracts\Events\Dispatcher; @@ -18,25 +19,13 @@ class ConfirmEmailHandler { use DispatchEventsTrait; - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @param \Flarum\User\UserRepository $users - */ - public function __construct(Dispatcher $events, UserRepository $users) - { - $this->events = $events; - $this->users = $users; + public function __construct( + protected Dispatcher $events, + protected UserRepository $users + ) { } - /** - * @param ConfirmEmail $command - * @return \Flarum\User\User - */ - public function handle(ConfirmEmail $command) + public function handle(ConfirmEmail $command): User { /** @var EmailToken $token */ $token = EmailToken::validOrFail($command->token); diff --git a/framework/core/src/User/Command/DeleteAvatar.php b/framework/core/src/User/Command/DeleteAvatar.php index fda803241..218fbb6e6 100644 --- a/framework/core/src/User/Command/DeleteAvatar.php +++ b/framework/core/src/User/Command/DeleteAvatar.php @@ -13,27 +13,9 @@ use Flarum\User\User; class DeleteAvatar { - /** - * The ID of the user to delete the avatar of. - * - * @var int - */ - public $userId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @param int $userId The ID of the user to delete the avatar of. - * @param User $actor The user performing the action. - */ - public function __construct($userId, User $actor) - { - $this->userId = $userId; - $this->actor = $actor; + public function __construct( + public int $userId, + public User $actor + ) { } } diff --git a/framework/core/src/User/Command/DeleteAvatarHandler.php b/framework/core/src/User/Command/DeleteAvatarHandler.php index f54954a4a..bbf2e9037 100644 --- a/framework/core/src/User/Command/DeleteAvatarHandler.php +++ b/framework/core/src/User/Command/DeleteAvatarHandler.php @@ -12,6 +12,7 @@ namespace Flarum\User\Command; use Flarum\Foundation\DispatchEventsTrait; use Flarum\User\AvatarUploader; use Flarum\User\Event\AvatarDeleting; +use Flarum\User\User; use Flarum\User\UserRepository; use Illuminate\Contracts\Events\Dispatcher; @@ -19,34 +20,14 @@ class DeleteAvatarHandler { use DispatchEventsTrait; - /** - * @var UserRepository - */ - protected $users; - - /** - * @var AvatarUploader - */ - protected $uploader; - - /** - * @param Dispatcher $events - * @param UserRepository $users - * @param AvatarUploader $uploader - */ - public function __construct(Dispatcher $events, UserRepository $users, AvatarUploader $uploader) - { - $this->events = $events; - $this->users = $users; - $this->uploader = $uploader; + public function __construct( + protected Dispatcher $events, + protected UserRepository $users, + protected AvatarUploader $uploader + ) { } - /** - * @param DeleteAvatar $command - * @return \Flarum\User\User - * @throws \Flarum\User\Exception\PermissionDeniedException - */ - public function handle(DeleteAvatar $command) + public function handle(DeleteAvatar $command): User { $actor = $command->actor; diff --git a/framework/core/src/User/Command/DeleteUser.php b/framework/core/src/User/Command/DeleteUser.php index 726ea58b9..0fad3270f 100644 --- a/framework/core/src/User/Command/DeleteUser.php +++ b/framework/core/src/User/Command/DeleteUser.php @@ -13,38 +13,10 @@ use Flarum\User\User; class DeleteUser { - /** - * The ID of the user to delete. - * - * @var int - */ - public $userId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * Any other user input associated with the action. This is unused by - * default, but may be used by extensions. - * - * @var array - */ - public $data; - - /** - * @param int $userId The ID of the user to delete. - * @param User $actor The user performing the action. - * @param array $data Any other user input associated with the action. This - * is unused by default, but may be used by extensions. - */ - public function __construct($userId, User $actor, array $data = []) - { - $this->userId = $userId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $userId, + public User $actor, + public array $data = [] + ) { } } diff --git a/framework/core/src/User/Command/DeleteUserHandler.php b/framework/core/src/User/Command/DeleteUserHandler.php index f6e0cec9a..e65baaa3c 100644 --- a/framework/core/src/User/Command/DeleteUserHandler.php +++ b/framework/core/src/User/Command/DeleteUserHandler.php @@ -12,6 +12,7 @@ namespace Flarum\User\Command; use Flarum\Foundation\DispatchEventsTrait; use Flarum\User\Event\Deleting; use Flarum\User\Exception\PermissionDeniedException; +use Flarum\User\User; use Flarum\User\UserRepository; use Illuminate\Contracts\Events\Dispatcher; @@ -19,27 +20,16 @@ class DeleteUserHandler { use DispatchEventsTrait; - /** - * @var UserRepository - */ - protected $users; - - /** - * @param Dispatcher $events - * @param UserRepository $users - */ - public function __construct(Dispatcher $events, UserRepository $users) - { - $this->events = $events; - $this->users = $users; + public function __construct( + protected Dispatcher $events, + protected UserRepository $users + ) { } /** - * @param DeleteUser $command - * @return \Flarum\User\User * @throws PermissionDeniedException */ - public function handle(DeleteUser $command) + public function handle(DeleteUser $command): User { $actor = $command->actor; $user = $this->users->findOrFail($command->userId, $actor); diff --git a/framework/core/src/User/Command/EditUser.php b/framework/core/src/User/Command/EditUser.php index f452c9c52..44cb8c176 100644 --- a/framework/core/src/User/Command/EditUser.php +++ b/framework/core/src/User/Command/EditUser.php @@ -13,36 +13,10 @@ use Flarum\User\User; class EditUser { - /** - * The ID of the user to edit. - * - * @var int - */ - public $userId; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the user. - * - * @var array - */ - public $data; - - /** - * @param int $userId The ID of the user to edit. - * @param User $actor The user performing the action. - * @param array $data The attributes to update on the user. - */ - public function __construct($userId, User $actor, array $data) - { - $this->userId = $userId; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public int $userId, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/User/Command/EditUserHandler.php b/framework/core/src/User/Command/EditUserHandler.php index 51cdd6264..7f43ea163 100644 --- a/framework/core/src/User/Command/EditUserHandler.php +++ b/framework/core/src/User/Command/EditUserHandler.php @@ -17,41 +17,19 @@ use Flarum\User\UserRepository; use Flarum\User\UserValidator; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Support\Arr; -use Illuminate\Validation\ValidationException; class EditUserHandler { use DispatchEventsTrait; - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @var UserValidator - */ - protected $validator; - - /** - * @param Dispatcher $events - * @param \Flarum\User\UserRepository $users - * @param UserValidator $validator - */ - public function __construct(Dispatcher $events, UserRepository $users, UserValidator $validator) - { - $this->events = $events; - $this->users = $users; - $this->validator = $validator; + public function __construct( + protected Dispatcher $events, + protected UserRepository $users, + protected UserValidator $validator + ) { } - /** - * @param EditUser $command - * @return User - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws ValidationException - */ - public function handle(EditUser $command) + public function handle(EditUser $command): User { $actor = $command->actor; $data = $command->data; diff --git a/framework/core/src/User/Command/RegisterUser.php b/framework/core/src/User/Command/RegisterUser.php index 24f7e8b74..a2c306782 100644 --- a/framework/core/src/User/Command/RegisterUser.php +++ b/framework/core/src/User/Command/RegisterUser.php @@ -13,27 +13,9 @@ use Flarum\User\User; class RegisterUser { - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes of the new user. - * - * @var array - */ - public $data; - - /** - * @param User $actor The user performing the action. - * @param array $data The attributes of the new user. - */ - public function __construct(User $actor, array $data) - { - $this->actor = $actor; - $this->data = $data; + public function __construct( + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/User/Command/RegisterUserHandler.php b/framework/core/src/User/Command/RegisterUserHandler.php index bde2e4490..4dc745bc7 100644 --- a/framework/core/src/User/Command/RegisterUserHandler.php +++ b/framework/core/src/User/Command/RegisterUserHandler.php @@ -30,48 +30,22 @@ class RegisterUserHandler { use DispatchEventsTrait; - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var UserValidator - */ - protected $userValidator; - - /** - * @var AvatarUploader - */ - protected $avatarUploader; - /** - * @var Factory - */ - private $validator; - - /** - * @var ImageManager - */ - protected $imageManager; - - public function __construct(Dispatcher $events, SettingsRepositoryInterface $settings, UserValidator $userValidator, AvatarUploader $avatarUploader, Factory $validator, ImageManager $imageManager) - { - $this->events = $events; - $this->settings = $settings; - $this->userValidator = $userValidator; - $this->avatarUploader = $avatarUploader; - $this->validator = $validator; - $this->imageManager = $imageManager; + public function __construct( + protected Dispatcher $events, + protected SettingsRepositoryInterface $settings, + protected UserValidator $userValidator, + protected AvatarUploader $avatarUploader, + private readonly Factory $validator, + protected ImageManager $imageManager + ) { } /** - * @param RegisterUser $command - * @return User * @throws PermissionDeniedException if signup is closed and the actor is * not an administrator. * @throws ValidationException */ - public function handle(RegisterUser $command) + public function handle(RegisterUser $command): User { $actor = $command->actor; $data = $command->data; @@ -145,7 +119,7 @@ class RegisterUserHandler /** * @throws InvalidArgumentException */ - private function uploadAvatarFromUrl(User $user, string $url) + private function uploadAvatarFromUrl(User $user, string $url): void { $urlValidator = $this->validator->make(compact('url'), [ 'url' => 'required|active_url', @@ -166,7 +140,7 @@ class RegisterUserHandler $this->avatarUploader->upload($user, $image); } - private function fulfillToken(User $user, RegistrationToken $token) + private function fulfillToken(User $user, RegistrationToken $token): void { $token->delete(); diff --git a/framework/core/src/User/Command/UploadAvatar.php b/framework/core/src/User/Command/UploadAvatar.php index 03954155b..cd41b2674 100644 --- a/framework/core/src/User/Command/UploadAvatar.php +++ b/framework/core/src/User/Command/UploadAvatar.php @@ -14,36 +14,10 @@ use Psr\Http\Message\UploadedFileInterface; class UploadAvatar { - /** - * The ID of the user to upload the avatar for. - * - * @var int - */ - public $userId; - - /** - * The avatar file to upload. - * - * @var UploadedFileInterface - */ - public $file; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @param int $userId The ID of the user to upload the avatar for. - * @param UploadedFileInterface $file The avatar file to upload. - * @param User $actor The user performing the action. - */ - public function __construct($userId, UploadedFileInterface $file, User $actor) - { - $this->userId = $userId; - $this->file = $file; - $this->actor = $actor; + public function __construct( + public int $userId, + public UploadedFileInterface $file, + public User $actor + ) { } } diff --git a/framework/core/src/User/Command/UploadAvatarHandler.php b/framework/core/src/User/Command/UploadAvatarHandler.php index ae8844230..b100a3d66 100644 --- a/framework/core/src/User/Command/UploadAvatarHandler.php +++ b/framework/core/src/User/Command/UploadAvatarHandler.php @@ -13,6 +13,7 @@ use Flarum\Foundation\DispatchEventsTrait; use Flarum\User\AvatarUploader; use Flarum\User\AvatarValidator; use Flarum\User\Event\AvatarSaving; +use Flarum\User\User; use Flarum\User\UserRepository; use Illuminate\Contracts\Events\Dispatcher; use Intervention\Image\ImageManager; @@ -21,48 +22,16 @@ class UploadAvatarHandler { use DispatchEventsTrait; - /** - * @var \Flarum\User\UserRepository - */ - protected $users; - - /** - * @var AvatarUploader - */ - protected $uploader; - - /** - * @var \Flarum\User\AvatarValidator - */ - protected $validator; - - /** - * @var ImageManager - */ - protected $imageManager; - - /** - * @param Dispatcher $events - * @param UserRepository $users - * @param AvatarUploader $uploader - * @param AvatarValidator $validator - */ - public function __construct(Dispatcher $events, UserRepository $users, AvatarUploader $uploader, AvatarValidator $validator, ImageManager $imageManager) - { - $this->events = $events; - $this->users = $users; - $this->uploader = $uploader; - $this->validator = $validator; - $this->imageManager = $imageManager; + public function __construct( + protected Dispatcher $events, + protected UserRepository $users, + protected AvatarUploader $uploader, + protected AvatarValidator $validator, + protected ImageManager $imageManager + ) { } - /** - * @param UploadAvatar $command - * @return \Flarum\User\User - * @throws \Flarum\User\Exception\PermissionDeniedException - * @throws \Flarum\Foundation\ValidationException - */ - public function handle(UploadAvatar $command) + public function handle(UploadAvatar $command): User { $actor = $command->actor; diff --git a/framework/core/src/User/EmailConfirmationMailer.php b/framework/core/src/User/EmailConfirmationMailer.php index 4e54c06d8..d33836248 100644 --- a/framework/core/src/User/EmailConfirmationMailer.php +++ b/framework/core/src/User/EmailConfirmationMailer.php @@ -10,43 +10,23 @@ namespace Flarum\User; use Flarum\Http\UrlGenerator; +use Flarum\Locale\TranslatorInterface; use Flarum\Mail\Job\SendRawEmailJob; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\Event\EmailChangeRequested; use Illuminate\Contracts\Queue\Queue; -use Symfony\Contracts\Translation\TranslatorInterface; class EmailConfirmationMailer { - /** - * @var SettingsRepositoryInterface - */ - protected $settings; - - /** - * @var Queue - */ - protected $queue; - - /** - * @var UrlGenerator - */ - protected $url; - - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(SettingsRepositoryInterface $settings, Queue $queue, UrlGenerator $url, TranslatorInterface $translator) - { - $this->settings = $settings; - $this->queue = $queue; - $this->url = $url; - $this->translator = $translator; + public function __construct( + protected SettingsRepositoryInterface $settings, + protected Queue $queue, + protected UrlGenerator $url, + protected TranslatorInterface $translator + ) { } - public function handle(EmailChangeRequested $event) + public function handle(EmailChangeRequested $event): void { $email = $event->email; $data = $this->getEmailData($event->user, $email); @@ -57,12 +37,7 @@ class EmailConfirmationMailer $this->queue->push(new SendRawEmailJob($email, $subject, $body)); } - /** - * @param User $user - * @param string $email - * @return EmailToken - */ - protected function generateToken(User $user, $email) + protected function generateToken(User $user, string $email): EmailToken { $token = EmailToken::generate($email, $user->id); $token->save(); @@ -70,14 +45,7 @@ class EmailConfirmationMailer return $token; } - /** - * Get the data that should be made available to email templates. - * - * @param User $user - * @param string $email - * @return array - */ - protected function getEmailData(User $user, $email) + protected function getEmailData(User $user, string $email): array { $token = $this->generateToken($user, $email); diff --git a/framework/core/src/User/EmailToken.php b/framework/core/src/User/EmailToken.php index 39313cb09..d123ffa94 100644 --- a/framework/core/src/User/EmailToken.php +++ b/framework/core/src/User/EmailToken.php @@ -12,6 +12,8 @@ namespace Flarum\User; use Carbon\Carbon; use Flarum\Database\AbstractModel; use Flarum\User\Exception\InvalidConfirmationTokenException; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Str; /** @@ -36,20 +38,9 @@ class EmailToken extends AbstractModel */ public $incrementing = false; - /** - * {@inheritdoc} - */ protected $primaryKey = 'token'; - /** - * Generate an email token for the specified user. - * - * @param string $email - * @param int $userId - * - * @return static - */ - public static function generate($email, $userId) + public static function generate(string $email, int $userId): static { $token = new static; @@ -61,12 +52,7 @@ class EmailToken extends AbstractModel return $token; } - /** - * Define the relationship with the owner of this email token. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } @@ -74,12 +60,9 @@ class EmailToken extends AbstractModel /** * Find the token with the given ID, and assert that it has not expired. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param string $id - * @return static * @throws InvalidConfirmationTokenException */ - public function scopeValidOrFail($query, $id) + public function scopeValidOrFail(Builder $query, string $id): static { /** @var static|null $token */ $token = $query->find($id); diff --git a/framework/core/src/User/Event/Activated.php b/framework/core/src/User/Event/Activated.php index f9613ca5a..6d043833d 100644 --- a/framework/core/src/User/Event/Activated.php +++ b/framework/core/src/User/Event/Activated.php @@ -13,23 +13,9 @@ use Flarum\User\User; class Activated { - /** - * @var User - */ - public $user; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param User $actor - */ - public function __construct(User $user, User $actor = null) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/AvatarChanged.php b/framework/core/src/User/Event/AvatarChanged.php index e194f3937..ae4338c49 100644 --- a/framework/core/src/User/Event/AvatarChanged.php +++ b/framework/core/src/User/Event/AvatarChanged.php @@ -13,23 +13,9 @@ use Flarum\User\User; class AvatarChanged { - /** - * @var User - */ - public $user; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param User $actor - */ - public function __construct(User $user, User $actor = null) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/AvatarDeleting.php b/framework/core/src/User/Event/AvatarDeleting.php index 1e5a40817..e2ba917af 100644 --- a/framework/core/src/User/Event/AvatarDeleting.php +++ b/framework/core/src/User/Event/AvatarDeleting.php @@ -13,27 +13,9 @@ use Flarum\User\User; class AvatarDeleting { - /** - * The user whose avatar will be deleted. - * - * @var User - */ - public $user; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * @param User $user The user whose avatar will be deleted. - * @param User $actor The user performing the action. - */ - public function __construct(User $user, User $actor) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public User $actor + ) { } } diff --git a/framework/core/src/User/Event/AvatarSaving.php b/framework/core/src/User/Event/AvatarSaving.php index b546286d9..5d20c8612 100644 --- a/framework/core/src/User/Event/AvatarSaving.php +++ b/framework/core/src/User/Event/AvatarSaving.php @@ -14,36 +14,10 @@ use Intervention\Image\Image; class AvatarSaving { - /** - * The user whose avatar will be saved. - * - * @var User - */ - public $user; - - /** - * The user performing the action. - * - * @var User - */ - public $actor; - - /** - * The image that will be saved. - * - * @var Image - */ - public $image; - - /** - * @param User $user The user whose avatar will be saved. - * @param User $actor The user performing the action. - * @param Image $image The image that will be saved. - */ - public function __construct(User $user, User $actor, Image $image) - { - $this->user = $user; - $this->actor = $actor; - $this->image = $image; + public function __construct( + public User $user, + public User $actor, + public Image $image + ) { } } diff --git a/framework/core/src/User/Event/Deleted.php b/framework/core/src/User/Event/Deleted.php index 3b464f1b0..aa0f612e5 100644 --- a/framework/core/src/User/Event/Deleted.php +++ b/framework/core/src/User/Event/Deleted.php @@ -13,23 +13,9 @@ use Flarum\User\User; class Deleted { - /** - * @var User - */ - public $user; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param User $actor - */ - public function __construct(User $user, User $actor = null) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/Deleting.php b/framework/core/src/User/Event/Deleting.php index 7116fcf06..98d39c01e 100644 --- a/framework/core/src/User/Event/Deleting.php +++ b/framework/core/src/User/Event/Deleting.php @@ -13,36 +13,10 @@ use Flarum\User\User; class Deleting { - /** - * The user who will be deleted. - * - * @var User - */ - public $user; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * Any user input associated with the command. - * - * @var array - */ - public $data; - - /** - * @param User $user The user who will be deleted. - * @param User $actor The user performing the action. - * @param array $data Any user input associated with the command. - */ - public function __construct(User $user, User $actor, array $data) - { - $this->user = $user; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public User $user, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/User/Event/EmailChangeRequested.php b/framework/core/src/User/Event/EmailChangeRequested.php index 57135bfe7..8157c6c5e 100644 --- a/framework/core/src/User/Event/EmailChangeRequested.php +++ b/framework/core/src/User/Event/EmailChangeRequested.php @@ -13,27 +13,9 @@ use Flarum\User\User; class EmailChangeRequested { - /** - * The user who requested the email change. - * - * @var User - */ - public $user; - - /** - * The email they requested to change to. - * - * @var string - */ - public $email; - - /** - * @param User $user The user who requested the email change. - * @param string $email The email they requested to change to. - */ - public function __construct(User $user, $email) - { - $this->user = $user; - $this->email = $email; + public function __construct( + public User $user, + public string $email + ) { } } diff --git a/framework/core/src/User/Event/EmailChanged.php b/framework/core/src/User/Event/EmailChanged.php index 57458ad2d..664dd609d 100644 --- a/framework/core/src/User/Event/EmailChanged.php +++ b/framework/core/src/User/Event/EmailChanged.php @@ -13,23 +13,9 @@ use Flarum\User\User; class EmailChanged { - /** - * @var User - */ - public $user; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param User $actor - */ - public function __construct(User $user, User $actor = null) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/GroupsChanged.php b/framework/core/src/User/Event/GroupsChanged.php index 02f846aae..1d13c6430 100644 --- a/framework/core/src/User/Event/GroupsChanged.php +++ b/framework/core/src/User/Event/GroupsChanged.php @@ -13,32 +13,11 @@ use Flarum\User\User; class GroupsChanged { - /** - * The user whose groups were changed. - * - * @var User - */ - public $user; - - /** - * @var \Flarum\Group\Group[] - */ - public $oldGroups; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user The user whose groups were changed. - * @param \Flarum\Group\Group[] $oldGroups - * @param User $actor - */ - public function __construct(User $user, array $oldGroups, User $actor = null) - { - $this->user = $user; - $this->oldGroups = $oldGroups; - $this->actor = $actor; + public function __construct( + public User $user, + /** @var \Flarum\Group\Group[] */ + public array $oldGroups, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/LoggedIn.php b/framework/core/src/User/Event/LoggedIn.php index 6a91fbe87..be4404cfd 100644 --- a/framework/core/src/User/Event/LoggedIn.php +++ b/framework/core/src/User/Event/LoggedIn.php @@ -14,13 +14,9 @@ use Flarum\User\User; class LoggedIn { - public $user; - - public $token; - - public function __construct(User $user, AccessToken $token) - { - $this->user = $user; - $this->token = $token; + public function __construct( + public User $user, + public AccessToken $token + ) { } } diff --git a/framework/core/src/User/Event/LoggedOut.php b/framework/core/src/User/Event/LoggedOut.php index 6beb2d4a6..62d167aae 100644 --- a/framework/core/src/User/Event/LoggedOut.php +++ b/framework/core/src/User/Event/LoggedOut.php @@ -13,19 +13,9 @@ use Flarum\User\User; class LoggedOut { - /** - * @var User - */ - public $user; - - /** - * @var bool - */ - public $isGlobal; - - public function __construct(User $user, bool $isGlobal = false) - { - $this->user = $user; - $this->isGlobal = $isGlobal; + public function __construct( + public User $user, + public bool $isGlobal = false + ) { } } diff --git a/framework/core/src/User/Event/PasswordChanged.php b/framework/core/src/User/Event/PasswordChanged.php index fb15c2c19..b16296f01 100644 --- a/framework/core/src/User/Event/PasswordChanged.php +++ b/framework/core/src/User/Event/PasswordChanged.php @@ -13,23 +13,9 @@ use Flarum\User\User; class PasswordChanged { - /** - * @var User - */ - public $user; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param User $actor - */ - public function __construct(User $user, User $actor = null) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/Registered.php b/framework/core/src/User/Event/Registered.php index c06357df1..40090d523 100644 --- a/framework/core/src/User/Event/Registered.php +++ b/framework/core/src/User/Event/Registered.php @@ -13,23 +13,9 @@ use Flarum\User\User; class Registered { - /** - * @var User - */ - public $user; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param User $actor - */ - public function __construct(User $user, User $actor = null) - { - $this->user = $user; - $this->actor = $actor; + public function __construct( + public User $user, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/RegisteringFromProvider.php b/framework/core/src/User/Event/RegisteringFromProvider.php index 8ebee757f..adb61ff95 100644 --- a/framework/core/src/User/Event/RegisteringFromProvider.php +++ b/framework/core/src/User/Event/RegisteringFromProvider.php @@ -13,30 +13,10 @@ use Flarum\User\User; class RegisteringFromProvider { - /** - * @var User - */ - public $user; - - /** - * @var string - */ - public $provider; - - /** - * @var array - */ - public $payload; - - /** - * @param User $user - * @param $provider - * @param $payload - */ - public function __construct(User $user, string $provider, array $payload) - { - $this->user = $user; - $this->provider = $provider; - $this->payload = $payload; + public function __construct( + public User $user, + public string $provider, + public array $payload + ) { } } diff --git a/framework/core/src/User/Event/Renamed.php b/framework/core/src/User/Event/Renamed.php index 80e8d0fbe..7370b3167 100644 --- a/framework/core/src/User/Event/Renamed.php +++ b/framework/core/src/User/Event/Renamed.php @@ -13,30 +13,10 @@ use Flarum\User\User; class Renamed { - /** - * @var User - */ - public $user; - - /** - * @var string - */ - public $oldUsername; - - /** - * @var User - */ - public $actor; - - /** - * @param User $user - * @param string $oldUsername - * @param User $actor - */ - public function __construct(User $user, string $oldUsername, User $actor = null) - { - $this->user = $user; - $this->oldUsername = $oldUsername; - $this->actor = $actor; + public function __construct( + public User $user, + public string $oldUsername, + public ?User $actor = null + ) { } } diff --git a/framework/core/src/User/Event/Saving.php b/framework/core/src/User/Event/Saving.php index 3f0710a4b..6f8eedc64 100644 --- a/framework/core/src/User/Event/Saving.php +++ b/framework/core/src/User/Event/Saving.php @@ -13,36 +13,10 @@ use Flarum\User\User; class Saving { - /** - * The user that will be saved. - * - * @var User - */ - public $user; - - /** - * The user who is performing the action. - * - * @var User - */ - public $actor; - - /** - * The attributes to update on the user. - * - * @var array - */ - public $data; - - /** - * @param User $user The user that will be saved. - * @param User $actor The user who is performing the action. - * @param array $data The attributes to update on the user. - */ - public function __construct(User $user, User $actor, array $data) - { - $this->user = $user; - $this->actor = $actor; - $this->data = $data; + public function __construct( + public User $user, + public User $actor, + public array $data + ) { } } diff --git a/framework/core/src/User/Filter/UserFilterer.php b/framework/core/src/User/Filter/UserFilterer.php index 418dca379..3af54ff76 100644 --- a/framework/core/src/User/Filter/UserFilterer.php +++ b/framework/core/src/User/Filter/UserFilterer.php @@ -16,21 +16,12 @@ use Illuminate\Database\Eloquent\Builder; class UserFilterer extends AbstractFilterer { - /** - * @var UserRepository - */ - protected $users; - - /** - * @param UserRepository $users - * @param array $filters - * @param array $filterMutators - */ - public function __construct(UserRepository $users, array $filters, array $filterMutators) - { + public function __construct( + protected UserRepository $users, + array $filters, + array $filterMutators + ) { parent::__construct($filters, $filterMutators); - - $this->users = $users; } protected function getQuery(User $actor): Builder diff --git a/framework/core/src/User/Guest.php b/framework/core/src/User/Guest.php index c9bcae246..bdaedde9c 100644 --- a/framework/core/src/User/Guest.php +++ b/framework/core/src/User/Guest.php @@ -10,6 +10,7 @@ namespace Flarum\User; use Flarum\Group\Group; +use Illuminate\Database\Eloquent\Collection; class Guest extends User { @@ -18,14 +19,12 @@ class Guest extends User * * @var int */ - public $id = 0; + public int $id = 0; /** * Get the guest's group, containing only the 'guests' group model. - * - * @return \Flarum\Group\Group */ - public function getGroupsAttribute() + public function getGroupsAttribute(): Collection { if (! isset($this->attributes['groups'])) { $this->attributes['groups'] = $this->relations['groups'] = Group::where('id', Group::GUEST_ID)->get(); @@ -34,10 +33,7 @@ class Guest extends User return $this->attributes['groups']; } - /** - * {@inheritdoc} - */ - public function isGuest() + public function isGuest(): bool { return true; } diff --git a/framework/core/src/User/IdSlugDriver.php b/framework/core/src/User/IdSlugDriver.php index 59fa73857..611f88c36 100644 --- a/framework/core/src/User/IdSlugDriver.php +++ b/framework/core/src/User/IdSlugDriver.php @@ -17,14 +17,9 @@ use Flarum\Http\SlugDriverInterface; */ class IdSlugDriver implements SlugDriverInterface { - /** - * @var UserRepository - */ - protected $users; - - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } /** diff --git a/framework/core/src/User/Job/RequestPasswordResetJob.php b/framework/core/src/User/Job/RequestPasswordResetJob.php index 5399532d7..d28d570d1 100644 --- a/framework/core/src/User/Job/RequestPasswordResetJob.php +++ b/framework/core/src/User/Job/RequestPasswordResetJob.php @@ -10,24 +10,19 @@ namespace Flarum\User\Job; use Flarum\Http\UrlGenerator; +use Flarum\Locale\TranslatorInterface; use Flarum\Mail\Job\SendRawEmailJob; use Flarum\Queue\AbstractJob; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\PasswordToken; use Flarum\User\UserRepository; use Illuminate\Contracts\Queue\Queue; -use Symfony\Contracts\Translation\TranslatorInterface; class RequestPasswordResetJob extends AbstractJob { - /** - * @var string - */ - protected $email; - - public function __construct(string $email) - { - $this->email = $email; + public function __construct( + protected string $email + ) { } public function handle( @@ -36,7 +31,7 @@ class RequestPasswordResetJob extends AbstractJob TranslatorInterface $translator, UserRepository $users, Queue $queue - ) { + ): void { $user = $users->findByEmail($this->email); if (! $user) { diff --git a/framework/core/src/User/LoginProvider.php b/framework/core/src/User/LoginProvider.php index d0c2f8dbb..91074284e 100644 --- a/framework/core/src/User/LoginProvider.php +++ b/framework/core/src/User/LoginProvider.php @@ -10,6 +10,7 @@ namespace Flarum\User; use Flarum\Database\AbstractModel; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * @property int $id @@ -30,20 +31,13 @@ class LoginProvider extends AbstractModel protected $fillable = ['provider', 'identifier']; - /** - * Get the user that the login provider belongs to. - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Get the user associated with the provider so that they can be logged in. - * - * @param string $provider - * @param string $identifier - * @return User|null */ public static function logIn(string $provider, string $identifier): ?User { diff --git a/framework/core/src/User/PasswordToken.php b/framework/core/src/User/PasswordToken.php index 09266e3bf..c79527eb1 100644 --- a/framework/core/src/User/PasswordToken.php +++ b/framework/core/src/User/PasswordToken.php @@ -11,6 +11,7 @@ namespace Flarum\User; use Carbon\Carbon; use Flarum\Database\AbstractModel; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Str; /** @@ -34,18 +35,12 @@ class PasswordToken extends AbstractModel */ public $incrementing = false; - /** - * {@inheritdoc} - */ protected $primaryKey = 'token'; /** * Generate a password token for the specified user. - * - * @param int $userId - * @return static */ - public static function generate(int $userId) + public static function generate(int $userId): static { $token = new static; @@ -56,12 +51,7 @@ class PasswordToken extends AbstractModel return $token; } - /** - * Define the relationship with the owner of this password token. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } diff --git a/framework/core/src/User/Query/EmailFilterGambit.php b/framework/core/src/User/Query/EmailFilterGambit.php index bf65f6b8a..2fa4bb58b 100644 --- a/framework/core/src/User/Query/EmailFilterGambit.php +++ b/framework/core/src/User/Query/EmailFilterGambit.php @@ -20,10 +20,7 @@ class EmailFilterGambit extends AbstractRegexGambit implements FilterInterface { use ValidateFilterTrait; - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $bit) + public function apply(SearchState $search, string $bit): bool { if (! $search->getActor()->hasPermission('user.edit')) { return false; @@ -32,18 +29,12 @@ class EmailFilterGambit extends AbstractRegexGambit implements FilterInterface return parent::apply($search, $bit); } - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'email:(.+)'; } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $matches[1], $negate); } @@ -53,7 +44,7 @@ class EmailFilterGambit extends AbstractRegexGambit implements FilterInterface return 'email'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { if (! $filterState->getActor()->hasPermission('user.edit')) { return; @@ -62,7 +53,7 @@ class EmailFilterGambit extends AbstractRegexGambit implements FilterInterface $this->constrain($filterState->getQuery(), $filterValue, $negate); } - protected function constrain(Builder $query, $rawEmail, bool $negate) + protected function constrain(Builder $query, $rawEmail, bool $negate): void { $email = $this->asString($rawEmail); diff --git a/framework/core/src/User/Query/GroupFilterGambit.php b/framework/core/src/User/Query/GroupFilterGambit.php index a511c2daa..39807fba2 100644 --- a/framework/core/src/User/Query/GroupFilterGambit.php +++ b/framework/core/src/User/Query/GroupFilterGambit.php @@ -22,18 +22,12 @@ class GroupFilterGambit extends AbstractRegexGambit implements FilterInterface { use ValidateFilterTrait; - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'group:(.+)'; } - /** - * {@inheritdoc} - */ - protected function conditions(SearchState $search, array $matches, $negate) + protected function conditions(SearchState $search, array $matches, bool $negate): void { $this->constrain($search->getQuery(), $search->getActor(), $matches[1], $negate); } @@ -43,12 +37,12 @@ class GroupFilterGambit extends AbstractRegexGambit implements FilterInterface return 'group'; } - public function filter(FilterState $filterState, $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { $this->constrain($filterState->getQuery(), $filterState->getActor(), $filterValue, $negate); } - protected function constrain(Builder $query, User $actor, $rawQuery, bool $negate) + protected function constrain(Builder $query, User $actor, $rawQuery, bool $negate): void { $groupIdentifiers = $this->asStringArray($rawQuery); $groupQuery = Group::whereVisibleTo($actor); diff --git a/framework/core/src/User/RegistrationToken.php b/framework/core/src/User/RegistrationToken.php index adf3ade9c..0f7ed3067 100644 --- a/framework/core/src/User/RegistrationToken.php +++ b/framework/core/src/User/RegistrationToken.php @@ -12,6 +12,7 @@ namespace Flarum\User; use Carbon\Carbon; use Flarum\Database\AbstractModel; use Flarum\User\Exception\InvalidConfirmationTokenException; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Str; /** @@ -45,21 +46,12 @@ class RegistrationToken extends AbstractModel */ public $incrementing = false; - /** - * {@inheritdoc} - */ protected $primaryKey = 'token'; /** * Generate an auth token for the specified user. - * - * @param string $provider - * @param string $identifier - * @param array $attributes - * @param array $payload - * @return static */ - public static function generate(string $provider, string $identifier, array $attributes, array $payload) + public static function generate(string $provider, string $identifier, array $attributes, array $payload): static { $token = new static; @@ -76,14 +68,9 @@ class RegistrationToken extends AbstractModel /** * Find the token with the given ID, and assert that it has not expired. * - * @param \Illuminate\Database\Eloquent\Builder<self> $query - * @param string $token - * * @throws InvalidConfirmationTokenException - * - * @return RegistrationToken */ - public function scopeValidOrFail($query, string $token) + public function scopeValidOrFail(Builder $query, string $token): ?RegistrationToken { /** @var RegistrationToken|null $token */ $token = $query->find($token); diff --git a/framework/core/src/User/Search/Gambit/FulltextGambit.php b/framework/core/src/User/Search/Gambit/FulltextGambit.php index 47180a043..f3eeeebe7 100644 --- a/framework/core/src/User/Search/Gambit/FulltextGambit.php +++ b/framework/core/src/User/Search/Gambit/FulltextGambit.php @@ -11,44 +11,34 @@ namespace Flarum\User\Search\Gambit; use Flarum\Search\GambitInterface; use Flarum\Search\SearchState; +use Flarum\User\User; use Flarum\User\UserRepository; +use Illuminate\Database\Eloquent\Builder; class FulltextGambit implements GambitInterface { - /** - * @var UserRepository - */ - protected $users; - - /** - * @param \Flarum\User\UserRepository $users - */ - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } /** - * @param $searchValue - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder<User> */ - private function getUserSearchSubQuery($searchValue) + private function getUserSearchSubQuery(string $searchValue): Builder { return $this->users ->query() ->select('id') - ->where('username', 'like', "{$searchValue}%"); + ->where('username', 'like', "$searchValue%"); } - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $searchValue) + public function apply(SearchState $search, string $bit): bool { $search->getQuery() ->whereIn( 'id', - $this->getUserSearchSubQuery($searchValue) + $this->getUserSearchSubQuery($bit) ); return true; diff --git a/framework/core/src/User/Search/UserSearcher.php b/framework/core/src/User/Search/UserSearcher.php index 2f95d5087..f6cbeab0b 100644 --- a/framework/core/src/User/Search/UserSearcher.php +++ b/framework/core/src/User/Search/UserSearcher.php @@ -18,28 +18,13 @@ use Illuminate\Database\Eloquent\Builder; class UserSearcher extends AbstractSearcher { - /** - * @var Dispatcher - */ - protected $events; - - /** - * @var UserRepository - */ - protected $users; - - /** - * @param UserRepository $users - * @param Dispatcher $events - * @param GambitManager $gambits - * @param array $searchMutators - */ - public function __construct(UserRepository $users, Dispatcher $events, GambitManager $gambits, array $searchMutators) - { + public function __construct( + protected UserRepository $users, + protected Dispatcher $events, + GambitManager $gambits, + array $searchMutators + ) { parent::__construct($gambits, $searchMutators); - - $this->events = $events; - $this->users = $users; } protected function getQuery(User $actor): Builder diff --git a/framework/core/src/User/SelfDemotionGuard.php b/framework/core/src/User/SelfDemotionGuard.php index 0842b5ab7..bc163b357 100644 --- a/framework/core/src/User/SelfDemotionGuard.php +++ b/framework/core/src/User/SelfDemotionGuard.php @@ -18,10 +18,10 @@ class SelfDemotionGuard { /** * Prevent an admin from removing their admin permission via the API. - * @param Saving $event + * * @throws PermissionDeniedException */ - public function handle(Saving $event) + public function handle(Saving $event): void { // Non-admin users pose no problem if (! $event->actor->isAdmin()) { diff --git a/framework/core/src/User/SessionServiceProvider.php b/framework/core/src/User/SessionServiceProvider.php index e0f8023a2..83b2aeba7 100644 --- a/framework/core/src/User/SessionServiceProvider.php +++ b/framework/core/src/User/SessionServiceProvider.php @@ -17,10 +17,7 @@ use SessionHandlerInterface; class SessionServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->container->singleton('flarum.session.drivers', function () { return []; diff --git a/framework/core/src/User/Throttler/EmailActivationThrottler.php b/framework/core/src/User/Throttler/EmailActivationThrottler.php index 21047ed97..01c7bba1c 100644 --- a/framework/core/src/User/Throttler/EmailActivationThrottler.php +++ b/framework/core/src/User/Throttler/EmailActivationThrottler.php @@ -20,15 +20,12 @@ use Psr\Http\Message\ServerRequestInterface; */ class EmailActivationThrottler { - public static $timeout = 300; + public static int $timeout = 300; - /** - * @return bool|void - */ - public function __invoke(ServerRequestInterface $request) + public function __invoke(ServerRequestInterface $request): ?bool { if ($request->getAttribute('routeName') !== 'users.confirmation.send') { - return; + return null; } $actor = RequestUtil::getActor($request); @@ -40,5 +37,7 @@ class EmailActivationThrottler ->exists()) { return true; } + + return null; } } diff --git a/framework/core/src/User/Throttler/EmailChangeThrottler.php b/framework/core/src/User/Throttler/EmailChangeThrottler.php index 53cd3be7d..cdb009bd6 100644 --- a/framework/core/src/User/Throttler/EmailChangeThrottler.php +++ b/framework/core/src/User/Throttler/EmailChangeThrottler.php @@ -21,19 +21,16 @@ use Psr\Http\Message\ServerRequestInterface; */ class EmailChangeThrottler { - public static $timeout = 300; + public static int $timeout = 300; - /** - * @return bool|void - */ - public function __invoke(ServerRequestInterface $request) + public function __invoke(ServerRequestInterface $request): ?bool { if ($request->getAttribute('routeName') !== 'users.update') { - return; + return null; } if (! Arr::has($request->getParsedBody(), 'data.attributes.email')) { - return; + return null; } $actor = RequestUtil::getActor($request); @@ -42,5 +39,7 @@ class EmailChangeThrottler if (EmailToken::query()->where('user_id', $actor->id)->where('created_at', '>=', Carbon::now()->subSeconds(self::$timeout))->exists()) { return true; } + + return null; } } diff --git a/framework/core/src/User/Throttler/PasswordResetThrottler.php b/framework/core/src/User/Throttler/PasswordResetThrottler.php index 1b36ff2a9..695e3f7d1 100644 --- a/framework/core/src/User/Throttler/PasswordResetThrottler.php +++ b/framework/core/src/User/Throttler/PasswordResetThrottler.php @@ -22,19 +22,16 @@ use Psr\Http\Message\ServerRequestInterface; */ class PasswordResetThrottler { - public static $timeout = 300; + public static int $timeout = 300; - /** - * @return bool|void - */ - public function __invoke(ServerRequestInterface $request) + public function __invoke(ServerRequestInterface $request): ?bool { if ($request->getAttribute('routeName') !== 'forgot') { - return; + return null; } if (! Arr::has($request->getParsedBody(), 'email')) { - return; + return null; } $actor = RequestUtil::getActor($request); @@ -42,5 +39,7 @@ class PasswordResetThrottler if (PasswordToken::query()->where('user_id', $actor->id)->where('created_at', '>=', Carbon::now()->subSeconds(self::$timeout))->exists()) { return true; } + + return null; } } diff --git a/framework/core/src/User/TokensClearer.php b/framework/core/src/User/TokensClearer.php index bb7fcb56c..d9701b599 100644 --- a/framework/core/src/User/TokensClearer.php +++ b/framework/core/src/User/TokensClearer.php @@ -17,22 +17,16 @@ class TokensClearer { public function subscribe(Dispatcher $events): void { - $events->listen([PasswordChanged::class, EmailChanged::class], [$this, 'clearPasswordTokens']); - $events->listen(PasswordChanged::class, [$this, 'clearEmailTokens']); + $events->listen([PasswordChanged::class, EmailChanged::class], $this->clearPasswordTokens(...)); + $events->listen(PasswordChanged::class, $this->clearEmailTokens(...)); } - /** - * @param PasswordChanged|EmailChanged $event - */ - public function clearPasswordTokens($event): void + public function clearPasswordTokens(EmailChanged|PasswordChanged $event): void { $event->user->passwordTokens()->delete(); } - /** - * @param PasswordChanged $event - */ - public function clearEmailTokens($event): void + public function clearEmailTokens(PasswordChanged $event): void { $event->user->emailTokens()->delete(); } diff --git a/framework/core/src/User/User.php b/framework/core/src/User/User.php index a15626d44..327ee60a5 100644 --- a/framework/core/src/User/User.php +++ b/framework/core/src/User/User.php @@ -33,6 +33,10 @@ use Flarum\User\Exception\NotAuthenticatedException; use Flarum\User\Exception\PermissionDeniedException; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Hashing\Hasher; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Arr; use Staudenmeir\EloquentEagerLimit\HasEagerLimit; @@ -80,8 +84,10 @@ class User extends AbstractModel /** * An array of callables, through each of which the user's list of groups is passed * before being returned. + * + * @var callable[] */ - protected static $groupProcessors = []; + protected static array $groupProcessors = []; /** * An array of registered user preferences. Each preference is defined with @@ -90,37 +96,31 @@ class User extends AbstractModel * - transformer: a callback that confines the value of the preference * - default: a default value if the preference isn't set * - * @var array + * @var array<string, array{transformer: callable(mixed): mixed, default: mixed}> */ - protected static $preferences = []; + protected static array $preferences = []; /** * A driver for getting display names. - * - * @var DriverInterface */ - protected static $displayNameDriver; + protected static DriverInterface $displayNameDriver; /** * The hasher with which to hash passwords. - * - * @var Hasher */ - protected static $hasher; + protected static Hasher $hasher; /** * The access gate. - * - * @var Access\Gate */ - protected static $gate; + protected static Access\Gate $gate; /** * Callbacks to check passwords. * - * @var array + * @var callable[] */ - protected static $passwordCheckers; + protected static array $passwordCheckers; /** * Difference from the current `last_seen` attribute value before `updateLastSeen()` @@ -128,11 +128,6 @@ class User extends AbstractModel */ private const LAST_SEEN_UPDATE_DIFF = 180; - /** - * Boot the model. - * - * @return void - */ public static function boot() { parent::boot(); @@ -151,15 +146,7 @@ class User extends AbstractModel }); } - /** - * Register a new user. - * - * @param string $username - * @param string $email - * @param string $password - * @return static - */ - public static function register($username, $email, $password) + public static function register(?string $username, ?string $email, ?string $password): static { $user = new static; @@ -173,36 +160,22 @@ class User extends AbstractModel return $user; } - /** - * @param Access\Gate $gate - */ - public static function setGate($gate) + public static function setGate(Access\Gate $gate): void { static::$gate = $gate; } - /** - * Set the display name driver. - * - * @param DriverInterface $driver - */ - public static function setDisplayNameDriver(DriverInterface $driver) + public static function setDisplayNameDriver(DriverInterface $driver): void { static::$displayNameDriver = $driver; } - public static function setPasswordCheckers(array $checkers) + public static function setPasswordCheckers(array $checkers): void { static::$passwordCheckers = $checkers; } - /** - * Rename the user. - * - * @param string $username - * @return $this - */ - public function rename($username) + public function rename(string $username): static { if ($username !== $this->username) { $oldUsername = $this->username; @@ -214,13 +187,7 @@ class User extends AbstractModel return $this; } - /** - * Change the user's email. - * - * @param string $email - * @return $this - */ - public function changeEmail($email) + public function changeEmail(string $email): static { if ($email !== $this->email) { $this->email = $email; @@ -231,13 +198,7 @@ class User extends AbstractModel return $this; } - /** - * Request that the user's email be changed. - * - * @param string $email - * @return $this - */ - public function requestEmailChange($email) + public function requestEmailChange(string $email): static { if ($email !== $this->email) { $this->raise(new EmailChangeRequested($this, $email)); @@ -246,13 +207,7 @@ class User extends AbstractModel return $this; } - /** - * Change the user's password. - * - * @param string $password - * @return $this - */ - public function changePassword($password) + public function changePassword(string $password): static { $this->password = $password; @@ -263,20 +218,16 @@ class User extends AbstractModel /** * Set the password attribute, storing it as a hash. - * - * @param string $value */ - public function setPasswordAttribute($value) + public function setPasswordAttribute(?string $value): void { $this->attributes['password'] = $value ? static::$hasher->make($value) : ''; } /** * Mark all discussions as read. - * - * @return $this */ - public function markAllAsRead() + public function markAllAsRead(): static { $this->marked_all_as_read_at = Carbon::now(); @@ -285,23 +236,15 @@ class User extends AbstractModel /** * Mark all notifications as read. - * - * @return $this */ - public function markNotificationsAsRead() + public function markNotificationsAsRead(): static { $this->read_notifications_at = Carbon::now(); return $this; } - /** - * Change the path of the user avatar. - * - * @param string|null $path - * @return $this - */ - public function changeAvatarPath($path) + public function changeAvatarPath(?string $path): static { $this->avatar_url = $path; @@ -310,38 +253,21 @@ class User extends AbstractModel return $this; } - /** - * Get the URL of the user's avatar. - * - * @param string|null $value - * @return string - */ - public function getAvatarUrlAttribute(string $value = null) + public function getAvatarUrlAttribute(?string $value = null): ?string { - if ($value && strpos($value, '://') === false) { + if ($value && ! str_contains($value, '://')) { return resolve(Factory::class)->disk('flarum-avatars')->url($value); } return $value; } - /** - * Get the user's display name. - * - * @return string - */ - public function getDisplayNameAttribute() + public function getDisplayNameAttribute(): string { return static::$displayNameDriver->displayName($this); } - /** - * Check if a given password matches the user's password. - * - * @param string $password - * @return bool - */ - public function checkPassword(string $password) + public function checkPassword(string $password): bool { $valid = false; @@ -358,12 +284,7 @@ class User extends AbstractModel return $valid; } - /** - * Activate the user's account. - * - * @return $this - */ - public function activate() + public function activate(): static { if (! $this->is_email_confirmed) { $this->is_email_confirmed = true; @@ -374,13 +295,7 @@ class User extends AbstractModel return $this; } - /** - * Check whether the user has a certain permission based on their groups. - * - * @param string $permission - * @return bool - */ - public function hasPermission($permission) + public function hasPermission(string $permission): bool { if ($this->isAdmin()) { return true; @@ -392,11 +307,8 @@ class User extends AbstractModel /** * Check whether the user has a permission that is like the given string, * based on their groups. - * - * @param string $match - * @return bool */ - public function hasPermissionLike($match) + public function hasPermissionLike(string $match): bool { if ($this->isAdmin()) { return true; @@ -414,32 +326,23 @@ class User extends AbstractModel /** * Get the notification types that should be alerted to this user, according * to their preferences. - * - * @return array */ - public function getAlertableNotificationTypes() + public function getAlertableNotificationTypes(): array { $types = array_keys(Notification::getSubjectModels()); return array_filter($types, [$this, 'shouldAlert']); } - /** - * Get the number of unread notifications for the user. - * - * @return int - */ - public function getUnreadNotificationCount() + public function getUnreadNotificationCount(): int { return $this->unreadNotifications()->count(); } /** - * Return query builder for all notifications that have not been read yet. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<Notification> */ - protected function unreadNotifications() + protected function unreadNotifications(): HasMany { return $this->notifications() ->whereIn('type', $this->getAlertableNotificationTypes()) @@ -449,21 +352,17 @@ class User extends AbstractModel } /** - * Get all notifications that have not been read yet. - * - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ - protected function getUnreadNotifications() + protected function getUnreadNotifications(): Collection { return $this->unreadNotifications()->get(); } /** * Get the number of new, unseen notifications for the user. - * - * @return int */ - public function getNewNotificationCount() + public function getNewNotificationCount(): int { return $this->unreadNotifications() ->where('created_at', '>', $this->read_notifications_at ?? 0) @@ -473,11 +372,8 @@ class User extends AbstractModel /** * Get the values of all registered preferences for this user, by * transforming their stored preferences and merging them with the defaults. - * - * @param string|null $value - * @return array */ - public function getPreferencesAttribute($value) + public function getPreferencesAttribute(?string $value): array { $defaults = array_map(function ($value) { return $value['default']; @@ -490,58 +386,36 @@ class User extends AbstractModel /** * Encode an array of preferences for storage in the database. - * - * @param mixed $value */ - public function setPreferencesAttribute($value) + public function setPreferencesAttribute(array $value): void { $this->attributes['preferences'] = json_encode($value); } /** - * Check whether or not the user should receive an alert for a notification + * Check whether the user should receive an alert for a notification * type. - * - * @param string $type - * @return bool */ - public function shouldAlert($type) + public function shouldAlert(string $type): bool { return (bool) $this->getPreference(static::getNotificationPreferenceKey($type, 'alert')); } /** - * Check whether or not the user should receive an email for a notification + * Check whether the user should receive an email for a notification * type. - * - * @param string $type - * @return bool */ - public function shouldEmail($type) + public function shouldEmail(string $type): bool { return (bool) $this->getPreference(static::getNotificationPreferenceKey($type, 'email')); } - /** - * Get the value of a preference for this user. - * - * @param string $key - * @param mixed $default - * @return mixed - */ - public function getPreference($key, $default = null) + public function getPreference(string $key, mixed $default = null): mixed { return Arr::get($this->preferences, $key, $default); } - /** - * Set the value of a preference for this user. - * - * @param string $key - * @param mixed $value - * @return $this - */ - public function setPreference($key, $value) + public function setPreference(string $key, mixed $value): static { if (isset(static::$preferences[$key])) { $preferences = $this->preferences; @@ -558,12 +432,7 @@ class User extends AbstractModel return $this; } - /** - * Set the user as being last seen just now. - * - * @return $this - */ - public function updateLastSeen() + public function updateLastSeen(): static { $now = Carbon::now(); @@ -574,22 +443,15 @@ class User extends AbstractModel return $this; } - /** - * Check whether or not the user is an administrator. - * - * @return bool - */ - public function isAdmin() + public function isAdmin(): bool { return $this->groups->contains(Group::ADMINISTRATOR_ID); } /** - * Check whether or not the user is a guest. - * - * @return bool + * Check whether the user is a guest. */ - public function isGuest() + public function isGuest(): bool { return false; } @@ -602,10 +464,9 @@ class User extends AbstractModel * request / operation without a change in permissions (or using another * user account) is pointless. * - * @param bool $condition * @throws PermissionDeniedException */ - public function assertPermission($condition) + public function assertPermission(bool $condition): void { if (! $condition) { throw new PermissionDeniedException; @@ -621,7 +482,7 @@ class User extends AbstractModel * * @throws NotAuthenticatedException */ - public function assertRegistered() + public function assertRegistered(): void { if ($this->isGuest()) { throw new NotAuthenticatedException; @@ -629,11 +490,9 @@ class User extends AbstractModel } /** - * @param string $ability - * @param mixed $arguments * @throws PermissionDeniedException */ - public function assertCan($ability, $arguments = null) + public function assertCan(string $ability, mixed $arguments = null): void { $this->assertPermission( $this->can($ability, $arguments) @@ -643,93 +502,79 @@ class User extends AbstractModel /** * @throws PermissionDeniedException */ - public function assertAdmin() + public function assertAdmin(): void { $this->assertCan('administrate'); } /** - * Define the relationship with the user's posts. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<Post> */ - public function posts() + public function posts(): HasMany { return $this->hasMany(Post::class); } /** - * Define the relationship with the user's discussions. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<Discussion> */ - public function discussions() + public function discussions(): HasMany { return $this->hasMany(Discussion::class); } /** - * Define the relationship with the user's read discussions. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<Discussion> + * @return BelongsToMany<Discussion> */ - public function read() + public function read(): BelongsToMany { return $this->belongsToMany(Discussion::class); } /** - * Define the relationship with the user's groups. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return BelongsToMany<Group> */ - public function groups() + public function groups(): BelongsToMany { return $this->belongsToMany(Group::class); } - public function visibleGroups() + public function visibleGroups(): BelongsToMany { return $this->belongsToMany(Group::class)->where('is_hidden', false); } /** - * Define the relationship with the user's notifications. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<Notification> */ - public function notifications() + public function notifications(): HasMany { return $this->hasMany(Notification::class); } /** - * Define the relationship with the user's email tokens. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<EmailToken> */ - public function emailTokens() + public function emailTokens(): HasMany { return $this->hasMany(EmailToken::class); } /** - * Define the relationship with the user's email tokens. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<PasswordToken> */ - public function passwordTokens() + public function passwordTokens(): HasMany { return $this->hasMany(PasswordToken::class); } /** - * Define the relationship with the permissions of all of the groups that + * Define the relationship with the permissions of all the groups that * the user is in. * - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function permissions() + public function permissions(): Builder { $groupIds = [Group::GUEST_ID]; @@ -745,7 +590,7 @@ class User extends AbstractModel $groupIds = $processor($this, $groupIds); } - return Permission::whereIn('group_id', $groupIds); + return Permission::query()->whereIn('group_id', $groupIds); } /** @@ -753,7 +598,7 @@ class User extends AbstractModel * * @return string[] */ - public function getPermissions() + public function getPermissions(): array { if (is_null($this->permissions)) { $this->permissions = $this->permissions()->pluck('permission')->all(); @@ -763,39 +608,27 @@ class User extends AbstractModel } /** - * Define the relationship with the user's access tokens. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany<AccessToken> */ - public function accessTokens() + public function accessTokens(): HasMany { return $this->hasMany(AccessToken::class); } /** - * Get the user's login providers. + * @return HasMany<LoginProvider> */ - public function loginProviders() + public function loginProviders(): HasMany { return $this->hasMany(LoginProvider::class); } - /** - * @param string $ability - * @param array|mixed $arguments - * @return bool - */ - public function can($ability, $arguments = null) + public function can(string $ability, mixed $arguments = null): bool { return static::$gate->allows($this, $ability, $arguments); } - /** - * @param string $ability - * @param array|mixed $arguments - * @return bool - */ - public function cannot($ability, $arguments = null) + public function cannot(string $ability, mixed $arguments = null): bool { return ! $this->can($ability, $arguments); } @@ -803,11 +636,9 @@ class User extends AbstractModel /** * Set the hasher with which to hash passwords. * - * @param Hasher $hasher - * * @internal */ - public static function setHasher(Hasher $hasher) + public static function setHasher(Hasher $hasher): void { static::$hasher = $hasher; } @@ -815,13 +646,9 @@ class User extends AbstractModel /** * Register a preference with a transformer and a default value. * - * @param string $key - * @param callable $transformer - * @param mixed $default - * * @internal */ - public static function registerPreference($key, callable $transformer = null, $default = null) + public static function registerPreference(string $key, callable $transformer = null, mixed $default = null): void { static::$preferences[$key] = compact('transformer', 'default'); } @@ -829,35 +656,23 @@ class User extends AbstractModel /** * Register a callback that processes a user's list of groups. * - * @param callable $callback - * @return void - * * @internal */ - public static function addGroupProcessor($callback) + public static function addGroupProcessor(callable $callback): void { static::$groupProcessors[] = $callback; } /** - * Get the key for a preference which flags whether or not the user will + * Get the key for a preference which flags whether the user will * receive a notification for $type via $method. - * - * @param string $type - * @param string $method - * @return string */ - public static function getNotificationPreferenceKey($type, $method) + public static function getNotificationPreferenceKey(string $type, string $method): string { return 'notify_'.$type.'_'.$method; } - /** - * Refresh the user's comments count. - * - * @return $this - */ - public function refreshCommentCount() + public function refreshCommentCount(): static { $this->comment_count = $this->posts() ->where('type', 'comment') @@ -867,12 +682,7 @@ class User extends AbstractModel return $this; } - /** - * Refresh the user's comments count. - * - * @return $this - */ - public function refreshDiscussionCount() + public function refreshDiscussionCount(): static { $this->discussion_count = $this->discussions() ->where('is_private', false) diff --git a/framework/core/src/User/UserMetadataUpdater.php b/framework/core/src/User/UserMetadataUpdater.php index 5e0252e58..3f9290b73 100644 --- a/framework/core/src/User/UserMetadataUpdater.php +++ b/framework/core/src/User/UserMetadataUpdater.php @@ -18,61 +18,43 @@ use Illuminate\Contracts\Events\Dispatcher; class UserMetadataUpdater { - /** - * @param Dispatcher $events - */ - public function subscribe(Dispatcher $events) + public function subscribe(Dispatcher $events): void { - $events->listen(Posted::class, [$this, 'whenPostWasPosted']); - $events->listen(PostDeleted::class, [$this, 'whenPostWasDeleted']); - $events->listen(Started::class, [$this, 'whenDiscussionWasStarted']); - $events->listen(DiscussionDeleted::class, [$this, 'whenDiscussionWasDeleted']); + $events->listen(Posted::class, $this->whenPostWasPosted(...)); + $events->listen(PostDeleted::class, $this->whenPostWasDeleted(...)); + $events->listen(Started::class, $this->whenDiscussionWasStarted(...)); + $events->listen(DiscussionDeleted::class, $this->whenDiscussionWasDeleted(...)); } - /** - * @param \Flarum\Post\Event\Posted $event - */ - public function whenPostWasPosted(Posted $event) + public function whenPostWasPosted(Posted $event): void { $this->updateCommentsCount($event->post->user); } - /** - * @param \Flarum\Post\Event\Deleted $event - */ - public function whenPostWasDeleted(PostDeleted $event) + public function whenPostWasDeleted(PostDeleted $event): void { $this->updateCommentsCount($event->post->user); } - /** - * @param \Flarum\Discussion\Event\Started $event - */ - public function whenDiscussionWasStarted(Started $event) + public function whenDiscussionWasStarted(Started $event): void { $this->updateDiscussionsCount($event->discussion); } - /** - * @param \Flarum\Discussion\Event\Deleted $event - */ - public function whenDiscussionWasDeleted(DiscussionDeleted $event) + public function whenDiscussionWasDeleted(DiscussionDeleted $event): void { $this->updateDiscussionsCount($event->discussion); $this->updateCommentsCount($event->discussion->user); } - /** - * @param \Flarum\User\User $user - */ - private function updateCommentsCount(?User $user) + private function updateCommentsCount(?User $user): void { if ($user && $user->exists) { $user->refreshCommentCount()->save(); } } - private function updateDiscussionsCount(Discussion $discussion) + private function updateDiscussionsCount(Discussion $discussion): void { $user = $discussion->user; diff --git a/framework/core/src/User/UserRepository.php b/framework/core/src/User/UserRepository.php index b0c1e965e..ca45483ae 100644 --- a/framework/core/src/User/UserRepository.php +++ b/framework/core/src/User/UserRepository.php @@ -10,15 +10,17 @@ namespace Flarum\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Model; +/** + * @template T of User + */ class UserRepository { /** - * Get a new query builder for the users table. - * * @return Builder<User> */ - public function query() + public function query(): Builder { return User::query(); } @@ -27,13 +29,11 @@ class UserRepository * Find a user by ID, optionally making sure it is visible to a certain * user, or throw an exception. * - * @param int|string $id - * @param User|null $actor - * @return User + * @return T * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ - public function findOrFail($id, User $actor = null) + public function findOrFail(int|string $id, User $actor = null): Model { $query = $this->query()->where('id', $id); @@ -44,13 +44,11 @@ class UserRepository * Find a user by username, optionally making sure it is visible to a certain * user, or throw an exception. * - * @param string $username - * @param User|null $actor - * @return User + * @return T * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ - public function findOrFailByUsername($username, User $actor = null) + public function findOrFailByUsername(string $username, User $actor = null): Model { $query = $this->query()->where('username', $username); @@ -60,10 +58,9 @@ class UserRepository /** * Find a user by an identification (username or email). * - * @param string $identification - * @return User|null + * @return ?T */ - public function findByIdentification($identification) + public function findByIdentification(string $identification): ?Model { $field = filter_var($identification, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; @@ -71,24 +68,14 @@ class UserRepository } /** - * Find a user by email. - * - * @param string $email - * @return User|null + * @return ?T */ - public function findByEmail($email) + public function findByEmail(string $email): ?Model { return $this->query()->where('email', $email)->first(); } - /** - * Get the ID of a user with the given username. - * - * @param string $username - * @param User|null $actor - * @return int|null - */ - public function getIdForUsername($username, User $actor = null) + public function getIdForUsername(string $username, User $actor = null): ?int { $query = $this->query()->where('username', $username); @@ -105,12 +92,8 @@ class UserRepository /** * Find users by matching a string of words against their username, * optionally making sure they are visible to a certain user. - * - * @param string $string - * @param User|null $actor - * @return array */ - public function getIdsForUsername($string, User $actor = null) + public function getIdsForUsername(string $string, User $actor = null): array { $string = $this->escapeLikeString($string); @@ -122,13 +105,9 @@ class UserRepository } /** - * Scope a query to only include records that are visible to a user. - * - * @param Builder<User> $query - * @param User|null $actor * @return Builder<User> */ - protected function scopeVisibleTo(Builder $query, User $actor = null) + protected function scopeVisibleTo(Builder $query, User $actor = null): Builder { if ($actor !== null) { $query->whereVisibleTo($actor); @@ -139,11 +118,8 @@ class UserRepository /** * Escape special characters that can be used as wildcards in a LIKE query. - * - * @param string $string - * @return string */ - private function escapeLikeString($string) + private function escapeLikeString(string $string): string { return str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $string); } diff --git a/framework/core/src/User/UserServiceProvider.php b/framework/core/src/User/UserServiceProvider.php index abe37efb3..7334cd5c5 100644 --- a/framework/core/src/User/UserServiceProvider.php +++ b/framework/core/src/User/UserServiceProvider.php @@ -35,10 +35,7 @@ use Illuminate\Support\Arr; class UserServiceProvider extends AbstractServiceProvider { - /** - * {@inheritdoc} - */ - public function register() + public function register(): void { $this->registerDisplayNameDrivers(); $this->registerPasswordCheckers(); @@ -67,7 +64,7 @@ class UserServiceProvider extends AbstractServiceProvider }); } - protected function registerDisplayNameDrivers() + protected function registerDisplayNameDrivers(): void { $this->container->singleton('flarum.user.display_name.supported_drivers', function () { return [ @@ -90,7 +87,7 @@ class UserServiceProvider extends AbstractServiceProvider $this->container->alias('flarum.user.display_name.driver', DriverInterface::class); } - protected function registerPasswordCheckers() + protected function registerPasswordCheckers(): void { $this->container->singleton('flarum.user.password_checkers', function (Container $container) { return [ @@ -103,10 +100,7 @@ class UserServiceProvider extends AbstractServiceProvider }); } - /** - * {@inheritdoc} - */ - public function boot(Container $container, Dispatcher $events) + public function boot(Container $container, Dispatcher $events): void { foreach ($container->make('flarum.user.group_processors') as $callback) { User::addGroupProcessor(ContainerUtil::wrapCallback($callback, $container)); diff --git a/framework/core/src/User/UserValidator.php b/framework/core/src/User/UserValidator.php index bd24ec34d..9027fb3d3 100644 --- a/framework/core/src/User/UserValidator.php +++ b/framework/core/src/User/UserValidator.php @@ -13,31 +13,19 @@ use Flarum\Foundation\AbstractValidator; class UserValidator extends AbstractValidator { - /** - * @var User|null - */ - protected $user; + protected ?User $user = null; - /** - * @return User - */ - public function getUser() + public function getUser(): ?User { return $this->user; } - /** - * @param User $user - */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; } - /** - * {@inheritdoc} - */ - protected function getRules() + protected function getRules(): array { $idSuffix = $this->user ? ','.$this->user->id : ''; @@ -61,10 +49,7 @@ class UserValidator extends AbstractValidator ]; } - /** - * {@inheritdoc} - */ - protected function getMessages() + protected function getMessages(): array { return [ 'username.regex' => $this->translator->trans('core.api.invalid_username_message') diff --git a/framework/core/src/User/UsernameSlugDriver.php b/framework/core/src/User/UsernameSlugDriver.php index ad18a1118..c14f5a1e6 100644 --- a/framework/core/src/User/UsernameSlugDriver.php +++ b/framework/core/src/User/UsernameSlugDriver.php @@ -17,14 +17,9 @@ use Flarum\Http\SlugDriverInterface; */ class UsernameSlugDriver implements SlugDriverInterface { - /** - * @var UserRepository - */ - protected $users; - - public function __construct(UserRepository $users) - { - $this->users = $users; + public function __construct( + protected UserRepository $users + ) { } /** diff --git a/framework/core/tests/integration/api/AbstractSerializeControllerTest.php b/framework/core/tests/integration/api/AbstractSerializeControllerTest.php index af009f134..9b98cc487 100644 --- a/framework/core/tests/integration/api/AbstractSerializeControllerTest.php +++ b/framework/core/tests/integration/api/AbstractSerializeControllerTest.php @@ -14,6 +14,7 @@ use Flarum\Extend; use Flarum\Testing\integration\TestCase; use Psr\Http\Message\ServerRequestInterface; use Tobscure\JsonApi\Document; +use Tobscure\JsonApi\ElementInterface; use Tobscure\JsonApi\SerializerInterface; class AbstractSerializeControllerTest extends TestCase @@ -38,14 +39,14 @@ class AbstractSerializeControllerTest extends TestCase class DummySerializeController extends AbstractSerializeController { - public $serializer = null; + public ?string $serializer = null; - protected function data(ServerRequestInterface $request, Document $document) + protected function data(ServerRequestInterface $request, Document $document): mixed { return []; } - protected function createElement($data, SerializerInterface $serializer) + protected function createElement(mixed $data, SerializerInterface $serializer): ElementInterface { return $data; } diff --git a/framework/core/tests/integration/api/discussions/ShowTest.php b/framework/core/tests/integration/api/discussions/ShowTest.php index 3354d24ee..acdfccaac 100644 --- a/framework/core/tests/integration/api/discussions/ShowTest.php +++ b/framework/core/tests/integration/api/discussions/ShowTest.php @@ -97,7 +97,7 @@ class ShowTest extends TestCase $json = json_decode($response->getBody()->getContents(), true); - $this->assertNull(Arr::get($json, 'data.relationships.posts')); + $this->assertEmpty(Arr::get($json, 'data.relationships.posts.data')); } /** diff --git a/framework/core/tests/integration/extenders/ApiControllerTest.php b/framework/core/tests/integration/extenders/ApiControllerTest.php index de0e4daa4..0bcb3cac9 100644 --- a/framework/core/tests/integration/extenders/ApiControllerTest.php +++ b/framework/core/tests/integration/extenders/ApiControllerTest.php @@ -927,9 +927,9 @@ class ApiControllerTest extends TestCase class CustomDiscussionSerializer extends DiscussionSerializer { - protected function getDefaultAttributes($discussion) + protected function getDefaultAttributes(object|array $model): array { - return parent::getDefaultAttributes($discussion) + [ + return parent::getDefaultAttributes($model) + [ 'customSerializer' => true ]; } @@ -937,9 +937,9 @@ class CustomDiscussionSerializer extends DiscussionSerializer class CustomDiscussionSerializer2 extends DiscussionSerializer { - protected function getDefaultAttributes($discussion) + protected function getDefaultAttributes(object|array $model): array { - return parent::getDefaultAttributes($discussion) + [ + return parent::getDefaultAttributes($model) + [ 'customSerializer2' => true ]; } @@ -947,9 +947,9 @@ class CustomDiscussionSerializer2 extends DiscussionSerializer class CustomUserSerializer extends UserSerializer { - protected function getDefaultAttributes($user) + protected function getDefaultAttributes(object|array $model): array { - return parent::getDefaultAttributes($user) + [ + return parent::getDefaultAttributes($model) + [ 'customSerializer' => true ]; } @@ -957,9 +957,9 @@ class CustomUserSerializer extends UserSerializer class CustomPostSerializer extends PostSerializer { - protected function getDefaultAttributes($post) + protected function getDefaultAttributes(object|array $model): array { - return parent::getDefaultAttributes($post) + [ + return parent::getDefaultAttributes($model) + [ 'customSerializer' => true ]; } diff --git a/framework/core/tests/integration/extenders/ConsoleTest.php b/framework/core/tests/integration/extenders/ConsoleTest.php index 8241118fb..c7d1257b2 100644 --- a/framework/core/tests/integration/extenders/ConsoleTest.php +++ b/framework/core/tests/integration/extenders/ConsoleTest.php @@ -13,6 +13,7 @@ use Flarum\Console\AbstractCommand; use Flarum\Extend; use Flarum\Testing\integration\ConsoleTestCase; use Illuminate\Console\Scheduling\Event; +use Symfony\Component\Console\Command\Command; class ConsoleTest extends ConsoleTestCase { @@ -79,19 +80,15 @@ class ConsoleTest extends ConsoleTestCase class CustomCommand extends AbstractCommand { - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this->setName('customTestCommand'); } - /** - * {@inheritdoc} - */ - protected function fire() + protected function fire(): int { $this->info('Custom Command.'); + + return Command::SUCCESS; } } diff --git a/framework/core/tests/integration/extenders/EventTest.php b/framework/core/tests/integration/extenders/EventTest.php index 9f4cf9d95..e79b51af4 100644 --- a/framework/core/tests/integration/extenders/EventTest.php +++ b/framework/core/tests/integration/extenders/EventTest.php @@ -13,12 +13,12 @@ use Flarum\Extend; use Flarum\Foundation\Application; use Flarum\Group\Command\CreateGroup; use Flarum\Group\Event\Created; +use Flarum\Locale\TranslatorInterface; use Flarum\Testing\integration\RetrievesAuthorizedUsers; use Flarum\Testing\integration\TestCase; use Flarum\User\User; use Illuminate\Contracts\Bus\Dispatcher as BusDispatcher; use Illuminate\Contracts\Events\Dispatcher; -use Symfony\Contracts\Translation\TranslatorInterface; class EventTest extends TestCase { diff --git a/framework/core/tests/integration/extenders/FilterTest.php b/framework/core/tests/integration/extenders/FilterTest.php index 07f94e873..b2e790f12 100644 --- a/framework/core/tests/integration/extenders/FilterTest.php +++ b/framework/core/tests/integration/extenders/FilterTest.php @@ -113,10 +113,7 @@ class NoResultFilter implements FilterInterface return 'noResult'; } - /** - * {@inheritdoc} - */ - public function filter(FilterState $filterState, string $filterValue, bool $negate) + public function filter(FilterState $filterState, string|array $filterValue, bool $negate): void { if ($filterValue) { $filterState->getQuery() diff --git a/framework/core/tests/integration/extenders/ModelTest.php b/framework/core/tests/integration/extenders/ModelTest.php index a0580e6f7..af90dcfcf 100644 --- a/framework/core/tests/integration/extenders/ModelTest.php +++ b/framework/core/tests/integration/extenders/ModelTest.php @@ -438,10 +438,7 @@ class ModelTest extends TestCase class ModelTestCustomPost extends AbstractEventPost { - /** - * {@inheritdoc} - */ - public static $type = 'customPost'; + public static string $type = 'customPost'; } class CustomRelationClass diff --git a/framework/core/tests/integration/extenders/NotificationTest.php b/framework/core/tests/integration/extenders/NotificationTest.php index d1f9e90b2..b2603c49e 100644 --- a/framework/core/tests/integration/extenders/NotificationTest.php +++ b/framework/core/tests/integration/extenders/NotificationTest.php @@ -9,6 +9,7 @@ namespace Flarum\Tests\integration\extenders; +use Flarum\Database\AbstractModel; use Flarum\Extend; use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\Driver\NotificationDriverInterface; @@ -164,27 +165,27 @@ class NotificationTest extends TestCase class CustomNotificationType implements BlueprintInterface { - public function getFromUser() + public function getFromUser(): ?User { return null; } - public function getSubject() + public function getSubject(): ?AbstractModel { return null; } - public function getData() + public function getData(): array { return []; } - public static function getType() + public static function getType(): string { return 'customNotificationType'; } - public static function getSubjectModel() + public static function getSubjectModel(): string { return 'customNotificationTypeSubjectModel'; } @@ -192,7 +193,7 @@ class CustomNotificationType implements BlueprintInterface class SecondCustomNotificationType extends CustomNotificationType { - public static function getType() + public static function getType(): string { return 'secondCustomNotificationType'; } @@ -200,7 +201,7 @@ class SecondCustomNotificationType extends CustomNotificationType class ThirdCustomNotificationType extends CustomNotificationType { - public static function getType() + public static function getType(): string { return 'thirdCustomNotificationType'; } diff --git a/framework/core/tests/integration/extenders/PostTest.php b/framework/core/tests/integration/extenders/PostTest.php index d9323dbcc..8effab49c 100644 --- a/framework/core/tests/integration/extenders/PostTest.php +++ b/framework/core/tests/integration/extenders/PostTest.php @@ -41,15 +41,9 @@ class PostTest extends TestCase class PostTestCustomPost extends AbstractEventPost implements MergeableInterface { - /** - * {@inheritdoc} - */ - public static $type = 'customPost'; + public static string $type = 'customPost'; - /** - * {@inheritdoc} - */ - public function saveAfter(Post $previous = null) + public function saveAfter(Post $previous = null): static { $this->save(); diff --git a/framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php b/framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php index c582ec24a..ae129d28f 100644 --- a/framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php +++ b/framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php @@ -173,30 +173,23 @@ class SimpleFlarumSearchTest extends TestCase class NoResultFullTextGambit implements GambitInterface { - /** - * {@inheritdoc} - */ - public function apply(SearchState $search, $searchValue) + public function apply(SearchState $search, string $bit): bool { $search->getQuery() ->whereRaw('0=1'); + + return true; } } class NoResultFilterGambit extends AbstractRegexGambit { - /** - * {@inheritdoc} - */ - public function getGambitPattern() + public function getGambitPattern(): string { return 'noResult:(.+)'; } - /** - * {@inheritdoc} - */ - public function conditions(SearchState $search, array $matches, $negate) + public function conditions(SearchState $search, array $matches, bool $negate): void { $noResults = trim($matches[1], ' '); if ($noResults == '1') { @@ -225,7 +218,8 @@ class CustomSearcher extends AbstractSearcher class CustomFullTextGambit implements GambitInterface { - public function apply(SearchState $search, $bit) + public function apply(SearchState $search, string $bit): bool { + return true; } } diff --git a/framework/core/tests/integration/notification/NotificationSyncerTest.php b/framework/core/tests/integration/notification/NotificationSyncerTest.php index fdcbdfcfa..fd5a7c103 100644 --- a/framework/core/tests/integration/notification/NotificationSyncerTest.php +++ b/framework/core/tests/integration/notification/NotificationSyncerTest.php @@ -91,27 +91,27 @@ class CustomNotificationType implements BlueprintInterface $this->subject = $subject; } - public function getFromUser() + public function getFromUser(): ?User { return null; } - public function getSubject() + public function getSubject(): ?AbstractModel { return $this->subject; } - public function getData() + public function getData(): array { return []; } - public static function getType() + public static function getType(): string { return 'customNotificationType'; } - public static function getSubjectModel() + public static function getSubjectModel(): string { return self::$subjectModel; } diff --git a/php-packages/phpstan/phpstan-baseline.neon b/php-packages/phpstan/phpstan-baseline.neon index c6fbed8ed..3a50f8b4f 100644 --- a/php-packages/phpstan/phpstan-baseline.neon +++ b/php-packages/phpstan/phpstan-baseline.neon @@ -21,3 +21,10 @@ parameters: # yet we don't want to inject the implementation. - message: '#^Call to an undefined method Illuminate\\Database\\ConnectionInterface\:\:[A-z0-9_]+\(\)\.$#' reportUnmatched: false + + # By default when a callable parameter is typed with for example 3 parameters, + # and the implementation only accepts two of them, PHPStan complains. + # At the time of adding this error, there are no configuration values to make it + # 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 diff --git a/php-packages/testing/src/integration/Extend/BeginTransactionAndSetDatabase.php b/php-packages/testing/src/integration/Extend/BeginTransactionAndSetDatabase.php index 193c49672..565164bdb 100644 --- a/php-packages/testing/src/integration/Extend/BeginTransactionAndSetDatabase.php +++ b/php-packages/testing/src/integration/Extend/BeginTransactionAndSetDatabase.php @@ -26,7 +26,7 @@ class BeginTransactionAndSetDatabase implements ExtenderInterface $this->setDbOnTestCase = $setDbOnTestCase; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $db = $container->make(ConnectionInterface::class); diff --git a/php-packages/testing/src/integration/Extend/OverrideExtensionManagerForTests.php b/php-packages/testing/src/integration/Extend/OverrideExtensionManagerForTests.php index a11dee961..8d477a2eb 100644 --- a/php-packages/testing/src/integration/Extend/OverrideExtensionManagerForTests.php +++ b/php-packages/testing/src/integration/Extend/OverrideExtensionManagerForTests.php @@ -27,7 +27,7 @@ class OverrideExtensionManagerForTests implements ExtenderInterface $this->extensions = $extensions; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { $container->when(ExtensionManagerIncludeCurrent::class)->needs('$enabledIds')->give($this->extensions); if (count($this->extensions)) { diff --git a/php-packages/testing/src/integration/Extend/SetSettingsBeforeBoot.php b/php-packages/testing/src/integration/Extend/SetSettingsBeforeBoot.php index 170ce3edf..bbf604488 100644 --- a/php-packages/testing/src/integration/Extend/SetSettingsBeforeBoot.php +++ b/php-packages/testing/src/integration/Extend/SetSettingsBeforeBoot.php @@ -26,7 +26,7 @@ class SetSettingsBeforeBoot implements ExtenderInterface $this->settings = $settings; } - public function extend(Container $container, Extension $extension = null) + public function extend(Container $container, Extension $extension = null): void { if (count($this->settings)) { $settings = $container->make(SettingsRepositoryInterface::class); diff --git a/php-packages/testing/src/integration/Extension/ExtensionManagerIncludeCurrent.php b/php-packages/testing/src/integration/Extension/ExtensionManagerIncludeCurrent.php index 3bbd5b649..afaeaa479 100644 --- a/php-packages/testing/src/integration/Extension/ExtensionManagerIncludeCurrent.php +++ b/php-packages/testing/src/integration/Extension/ExtensionManagerIncludeCurrent.php @@ -20,6 +20,7 @@ use Illuminate\Contracts\Filesystem\Cloud; use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\FilesystemAdapter; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use League\Flysystem\Adapter\Local; use League\Flysystem\Filesystem as FlysystemFilesystem; @@ -49,10 +50,7 @@ class ExtensionManagerIncludeCurrent extends ExtensionManager $this->enabledIds = $enabledIds; } - /** - * @{@inheritDoc} - */ - public function getExtensions() + public function getExtensions(): Collection { $extensions = parent::getExtensions(); @@ -61,12 +59,12 @@ class ExtensionManagerIncludeCurrent extends ExtensionManager if (Arr::get($package, 'type') === 'flarum-extension') { $current = new Extension($this->paths->vendor.'/../', $package); $current->setInstalled(true); - $current->setVersion(Arr::get($package, 'version')); - $current->calculateDependencies([], []); + $current->setVersion(Arr::get($package, 'version', '0.0')); + $current->calculateDependencies([]); $extensions->put($current->getId(), $current); - $this->extensions = $extensions->sortBy(function ($extension, $name) { + $this->extensions = $extensions->sortBy(function ($extension) { return $extension->composerJsonAttribute('extra.flarum-extension.title'); }); } @@ -79,7 +77,7 @@ class ExtensionManagerIncludeCurrent extends ExtensionManager * However, since some logic needs this, as soon as we enable extensions * we'll switch booted to on. */ - public function isEnabled($extension) + public function isEnabled($extension): bool { if (! $this->booted) { return false; @@ -91,7 +89,7 @@ class ExtensionManagerIncludeCurrent extends ExtensionManager /** * In test cases, enabled extensions are determined by the test case, not the database. */ - public function getEnabled() + public function getEnabled(): array { return $this->enabledIds; } @@ -99,7 +97,7 @@ class ExtensionManagerIncludeCurrent extends ExtensionManager /** * Enabled extensions must be specified by the test case, so this should do nothing. */ - protected function setEnabledExtensions(array $enabledExtensions) + protected function setEnabledExtensions(array $enabledExtensions): void { }