diff --git a/extensions/akismet/extend.php b/extensions/akismet/extend.php index 0e9a96d37..d233931b4 100644 --- a/extensions/akismet/extend.php +++ b/extensions/akismet/extend.php @@ -13,6 +13,7 @@ use Flarum\Approval\Event\PostWasApproved; use Flarum\Extend; use Flarum\Post\Event\Hidden; use Flarum\Post\Event\Saving; +use Flarum\Post\Post; return [ (new Extend\Frontend('forum')) @@ -30,4 +31,7 @@ return [ (new Extend\ServiceProvider()) ->register(AkismetProvider::class), + + (new Extend\Model(Post::class)) + ->cast('is_spam', 'bool'), ]; diff --git a/extensions/akismet/src/Listener/ValidatePost.php b/extensions/akismet/src/Listener/ValidatePost.php index ef5aa5ff3..d0855b1cc 100644 --- a/extensions/akismet/src/Listener/ValidatePost.php +++ b/extensions/akismet/src/Listener/ValidatePost.php @@ -50,7 +50,7 @@ class ValidatePost ->withContent($post->content) ->withAuthorName($post->user->username) ->withAuthorEmail($post->user->email) - ->withType($post->number == 1 ? 'forum-post' : 'reply') + ->withType($post->number === 1 ? 'forum-post' : 'reply') ->withIp($post->ip_address) ->withUserAgent($_SERVER['HTTP_USER_AGENT']) ->checkSpam(); diff --git a/extensions/approval/extend.php b/extensions/approval/extend.php index edc5b61d3..c18e612a8 100644 --- a/extensions/approval/extend.php +++ b/extensions/approval/extend.php @@ -28,15 +28,17 @@ return [ // Discussions should be approved by default (new Extend\Model(Discussion::class)) - ->default('is_approved', true), + ->default('is_approved', true) + ->cast('is_approved', 'bool'), // Posts should be approved by default (new Extend\Model(Post::class)) - ->default('is_approved', true), + ->default('is_approved', true) + ->cast('is_approved', 'bool'), (new Extend\ApiSerializer(BasicDiscussionSerializer::class)) ->attribute('isApproved', function ($serializer, Discussion $discussion) { - return (bool) $discussion->is_approved; + return $discussion->is_approved; }), (new Extend\ApiSerializer(PostSerializer::class)) diff --git a/extensions/approval/src/Listener/UnapproveNewContent.php b/extensions/approval/src/Listener/UnapproveNewContent.php index e35d62a0b..d53965ba9 100644 --- a/extensions/approval/src/Listener/UnapproveNewContent.php +++ b/extensions/approval/src/Listener/UnapproveNewContent.php @@ -9,6 +9,7 @@ namespace Flarum\Approval\Listener; +use Carbon\Carbon; use Flarum\Discussion\Discussion; use Flarum\Flags\Flag; use Flarum\Post\CommentPost; @@ -55,7 +56,7 @@ class UnapproveNewContent $flag->post_id = $post->id; $flag->type = 'approval'; - $flag->created_at = time(); + $flag->created_at = Carbon::now(); $flag->save(); }); diff --git a/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php b/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php index 2a62b533c..bcba77b19 100644 --- a/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php +++ b/extensions/approval/src/Listener/UpdateDiscussionAfterPostApproval.php @@ -22,7 +22,7 @@ class UpdateDiscussionAfterPostApproval $discussion->refreshCommentCount(); $discussion->refreshLastPost(); - if ($post->number == 1) { + if ($post->number === 1) { $discussion->is_approved = true; $discussion->afterSave(function () use ($user) { diff --git a/extensions/flags/extend.php b/extensions/flags/extend.php index 3bb468454..3bc6db108 100644 --- a/extensions/flags/extend.php +++ b/extensions/flags/extend.php @@ -46,7 +46,7 @@ return [ ->delete('/posts/{id}/flags', 'flags.delete', DeleteFlagsController::class), (new Extend\Model(User::class)) - ->dateAttribute('read_flags_at'), + ->cast('read_flags_at', 'datetime'), (new Extend\Model(Post::class)) ->hasMany('flags', Flag::class, 'post_id'), diff --git a/extensions/flags/src/Api/Controller/ListFlagsController.php b/extensions/flags/src/Api/Controller/ListFlagsController.php index 2b0af8491..edbeac38f 100644 --- a/extensions/flags/src/Api/Controller/ListFlagsController.php +++ b/extensions/flags/src/Api/Controller/ListFlagsController.php @@ -9,6 +9,7 @@ namespace Flarum\Flags\Api\Controller; +use Carbon\Carbon; use Flarum\Api\Controller\AbstractListController; use Flarum\Flags\Api\Serializer\FlagSerializer; use Flarum\Flags\Flag; @@ -43,7 +44,7 @@ class ListFlagsController extends AbstractListController $actor->assertRegistered(); - $actor->read_flags_at = time(); + $actor->read_flags_at = Carbon::now(); $actor->save(); $flags = Flag::whereVisibleTo($actor) diff --git a/extensions/flags/src/Api/Serializer/FlagSerializer.php b/extensions/flags/src/Api/Serializer/FlagSerializer.php index 91ce26c1c..f307e3d7a 100644 --- a/extensions/flags/src/Api/Serializer/FlagSerializer.php +++ b/extensions/flags/src/Api/Serializer/FlagSerializer.php @@ -12,6 +12,8 @@ namespace Flarum\Flags\Api\Serializer; use Flarum\Api\Serializer\AbstractSerializer; use Flarum\Api\Serializer\BasicUserSerializer; use Flarum\Api\Serializer\PostSerializer; +use Flarum\Flags\Flag; +use InvalidArgumentException; class FlagSerializer extends AbstractSerializer { @@ -20,11 +22,14 @@ class FlagSerializer extends AbstractSerializer */ protected $type = 'flags'; - /** - * {@inheritdoc} - */ protected function getDefaultAttributes($flag) { + if (! ($flag instanceof Flag)) { + throw new InvalidArgumentException( + get_class($this).' can only serialize instances of '.Flag::class + ); + } + return [ 'type' => $flag->type, 'reason' => $flag->reason, diff --git a/extensions/flags/src/Command/CreateFlagHandler.php b/extensions/flags/src/Command/CreateFlagHandler.php index abea0a7d6..1798ef95d 100644 --- a/extensions/flags/src/Command/CreateFlagHandler.php +++ b/extensions/flags/src/Command/CreateFlagHandler.php @@ -9,6 +9,7 @@ namespace Flarum\Flags\Command; +use Carbon\Carbon; use Flarum\Flags\Event\Created; use Flarum\Flags\Flag; use Flarum\Foundation\ValidationException; @@ -99,7 +100,7 @@ class CreateFlagHandler $flag->type = 'user'; $flag->reason = Arr::get($data, 'attributes.reason'); $flag->reason_detail = Arr::get($data, 'attributes.reasonDetail'); - $flag->created_at = time(); + $flag->created_at = Carbon::now(); $flag->save(); diff --git a/extensions/flags/src/Command/DeleteFlagsHandler.php b/extensions/flags/src/Command/DeleteFlagsHandler.php index 1061a5e50..18173b8ad 100644 --- a/extensions/flags/src/Command/DeleteFlagsHandler.php +++ b/extensions/flags/src/Command/DeleteFlagsHandler.php @@ -11,7 +11,7 @@ namespace Flarum\Flags\Command; use Flarum\Flags\Event\Deleting; use Flarum\Flags\Event\FlagsWillBeDeleted; -use Flarum\Flags\Flag; +use Flarum\Post\Post; use Flarum\Post\PostRepository; use Illuminate\Events\Dispatcher; @@ -39,7 +39,7 @@ class DeleteFlagsHandler /** * @param DeleteFlags $command - * @return Flag + * @return Post */ public function handle(DeleteFlags $command) { diff --git a/extensions/flags/src/Flag.php b/extensions/flags/src/Flag.php index ee91f8035..6f056469d 100644 --- a/extensions/flags/src/Flag.php +++ b/extensions/flags/src/Flag.php @@ -9,11 +9,23 @@ namespace Flarum\Flags; +use Carbon\Carbon; use Flarum\Database\AbstractModel; use Flarum\Database\ScopeVisibilityTrait; use Flarum\Post\Post; use Flarum\User\User; +/** + * @property int $post_id + * @property int $user_id + * @property string $type + * @property string $reason + * @property string $reason_detail + * @property Carbon $created_at + * + * @property-read Post $post + * @property-read User $user + */ class Flag extends AbstractModel { use ScopeVisibilityTrait; diff --git a/extensions/lock/extend.php b/extensions/lock/extend.php index 100be10f6..9cf4429c6 100644 --- a/extensions/lock/extend.php +++ b/extensions/lock/extend.php @@ -35,12 +35,15 @@ return [ (new Extend\Notification()) ->type(DiscussionLockedBlueprint::class, BasicDiscussionSerializer::class, ['alert']), + (new Extend\Model(Discussion::class)) + ->cast('is_locked', 'bool'), + (new Extend\ApiSerializer(DiscussionSerializer::class)) ->attribute('isLocked', function (DiscussionSerializer $serializer, Discussion $discussion) { - return (bool) $discussion->is_locked; + return $discussion->is_locked; }) ->attribute('canLock', function (DiscussionSerializer $serializer, Discussion $discussion) { - return (bool) $serializer->getActor()->can('lock', $discussion); + return $serializer->getActor()->can('lock', $discussion); }), (new Extend\Post()) diff --git a/extensions/lock/src/Access/DiscussionPolicy.php b/extensions/lock/src/Access/DiscussionPolicy.php index 643136a15..86a0e3571 100755 --- a/extensions/lock/src/Access/DiscussionPolicy.php +++ b/extensions/lock/src/Access/DiscussionPolicy.php @@ -18,7 +18,7 @@ class DiscussionPolicy extends AbstractPolicy /** * @param User $actor * @param Discussion $discussion - * @return bool + * @return string|void */ public function reply(User $actor, Discussion $discussion) { diff --git a/extensions/lock/src/Post/DiscussionLockedPost.php b/extensions/lock/src/Post/DiscussionLockedPost.php index a13c7f7e2..a379fe642 100755 --- a/extensions/lock/src/Post/DiscussionLockedPost.php +++ b/extensions/lock/src/Post/DiscussionLockedPost.php @@ -9,6 +9,7 @@ namespace Flarum\Lock\Post; +use Carbon\Carbon; use Flarum\Post\AbstractEventPost; use Flarum\Post\MergeableInterface; use Flarum\Post\Post; @@ -59,7 +60,7 @@ class DiscussionLockedPost extends AbstractEventPost implements MergeableInterfa $post = new static; $post->content = static::buildContent($isLocked); - $post->created_at = time(); + $post->created_at = Carbon::now(); $post->discussion_id = $discussionId; $post->user_id = $userId; diff --git a/extensions/mentions/src/ConfigureMentions.php b/extensions/mentions/src/ConfigureMentions.php index 8378e3285..296291c20 100644 --- a/extensions/mentions/src/ConfigureMentions.php +++ b/extensions/mentions/src/ConfigureMentions.php @@ -16,6 +16,7 @@ use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\User; use Illuminate\Support\Str; use s9e\TextFormatter\Configurator; +use s9e\TextFormatter\Parser\Tag; class ConfigureMentions { @@ -39,7 +40,7 @@ class ConfigureMentions $this->configureGroupMentions($config); } - private function configureUserMentions(Configurator $config) + private function configureUserMentions(Configurator $config): void { $config->rendering->parameters['PROFILE_URL'] = $this->url->to('forum')->route('user', ['username' => '']); @@ -66,9 +67,8 @@ class ConfigureMentions } /** - * @param $tag - * - * @return bool + * @param Tag $tag + * @return bool|void */ public static function addUserId($tag) { @@ -81,7 +81,7 @@ class ConfigureMentions } if (isset($user)) { - $tag->setAttribute('id', $user->id); + $tag->setAttribute('id', (string) $user->id); $tag->setAttribute('displayname', $user->display_name); return true; @@ -90,7 +90,7 @@ class ConfigureMentions $tag->invalidate(); } - private function configurePostMentions(Configurator $config) + private function configurePostMentions(Configurator $config): void { $config->rendering->parameters['DISCUSSION_URL'] = $this->url->to('forum')->route('discussion', ['id' => '']); @@ -122,8 +122,8 @@ class ConfigureMentions } /** - * @param $tag - * @return bool + * @param Tag $tag + * @return bool|void */ public static function addPostId($tag, User $actor) { @@ -132,8 +132,8 @@ class ConfigureMentions ->find($tag->getAttribute('id')); if ($post) { - $tag->setAttribute('discussionid', (int) $post->discussion_id); - $tag->setAttribute('number', (int) $post->number); + $tag->setAttribute('discussionid', (string) $post->discussion_id); + $tag->setAttribute('number', (string) $post->number); if ($post->user) { $tag->setAttribute('displayname', $post->user->display_name); @@ -171,7 +171,7 @@ class ConfigureMentions /** * @param $tag - * @return bool + * @return bool|void */ public static function addGroupId($tag) { @@ -208,7 +208,7 @@ class ConfigureMentions $hexNumbers = Str::replace('#', '', $hexColor); if (Str::length($hexNumbers) === 3) { - $hexNumbers += $hexNumbers; + $hexNumbers .= $hexNumbers; } $r = hexdec(Str::substr($hexNumbers, 0, 2)); diff --git a/extensions/mentions/src/Formatter/FormatPostMentions.php b/extensions/mentions/src/Formatter/FormatPostMentions.php index 289376a7e..45a485e57 100644 --- a/extensions/mentions/src/Formatter/FormatPostMentions.php +++ b/extensions/mentions/src/Formatter/FormatPostMentions.php @@ -29,11 +29,11 @@ class FormatPostMentions /** * Configure rendering for post mentions. * - * @param s9e\TextFormatter\Renderer $renderer + * @param \s9e\TextFormatter\Renderer $renderer * @param mixed $context * @param string|null $xml - * @param Psr\Http\Message\ServerRequestInterface $request - * @return void + * @param \Psr\Http\Message\ServerRequestInterface $request + * @return string */ public function __invoke(Renderer $renderer, $context, $xml, Request $request = null) { diff --git a/extensions/mentions/src/Formatter/FormatUserMentions.php b/extensions/mentions/src/Formatter/FormatUserMentions.php index f0e6fdbb6..5625ac957 100644 --- a/extensions/mentions/src/Formatter/FormatUserMentions.php +++ b/extensions/mentions/src/Formatter/FormatUserMentions.php @@ -37,9 +37,9 @@ class FormatUserMentions /** * Configure rendering for user mentions. * - * @param s9e\TextFormatter\Renderer $renderer + * @param \s9e\TextFormatter\Renderer $renderer * @param mixed $context - * @param string|null $xml + * @param string $xml * @return string $xml to be rendered */ public function __invoke(Renderer $renderer, $context, string $xml) diff --git a/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php b/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php index 231f6cfd7..366445984 100755 --- a/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php +++ b/extensions/mentions/src/Listener/UpdateMentionsMetadataWhenVisible.php @@ -40,7 +40,7 @@ class UpdateMentionsMetadataWhenVisible */ public function handle($event) { - $content = $event->post->parsedContent; + $content = $event->post->parsed_content; $this->syncUserMentions( $event->post, diff --git a/extensions/nicknames/extend.php b/extensions/nicknames/extend.php index 535b5cc12..99fb7ab7b 100644 --- a/extensions/nicknames/extend.php +++ b/extensions/nicknames/extend.php @@ -26,6 +26,9 @@ return [ new Extend\Locales(__DIR__.'/locale'), + (new Extend\Model(User::class)) + ->cast('nickname', 'string'), + (new Extend\User()) ->displayNameDriver('nickname', NicknameDriver::class), diff --git a/extensions/nicknames/src/NicknameFullTextGambit.php b/extensions/nicknames/src/NicknameFullTextGambit.php index e80e9f0dd..84cec8035 100644 --- a/extensions/nicknames/src/NicknameFullTextGambit.php +++ b/extensions/nicknames/src/NicknameFullTextGambit.php @@ -58,5 +58,7 @@ class NicknameFullTextGambit implements GambitInterface 'id', $this->getUserSearchSubQuery($searchValue) ); + + return true; } } diff --git a/extensions/package-manager/src/Api/Controller/ListTasksController.php b/extensions/package-manager/src/Api/Controller/ListTasksController.php index 666e179f9..115888500 100644 --- a/extensions/package-manager/src/Api/Controller/ListTasksController.php +++ b/extensions/package-manager/src/Api/Controller/ListTasksController.php @@ -58,7 +58,7 @@ class ListTasksController extends AbstractListController $total = $this->repository->query()->count(); - $document->addMeta('total', $total); + $document->addMeta('total', (string) $total); $document->addPaginationLinks( $this->url->to('api')->route('package-manager.tasks.index'), diff --git a/extensions/package-manager/src/Command/BusinessCommandInterface.php b/extensions/package-manager/src/Command/AbstractActionCommand.php similarity index 53% rename from extensions/package-manager/src/Command/BusinessCommandInterface.php rename to extensions/package-manager/src/Command/AbstractActionCommand.php index 6b13f3b39..45ce09320 100644 --- a/extensions/package-manager/src/Command/BusinessCommandInterface.php +++ b/extensions/package-manager/src/Command/AbstractActionCommand.php @@ -9,7 +9,14 @@ namespace Flarum\PackageManager\Command; -interface BusinessCommandInterface +use Flarum\PackageManager\Task\Task; + +abstract class AbstractActionCommand { - public function getOperationName(): string; + /** + * @var Task|null + */ + public $task = 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 62280c23f..2ca6efcb4 100755 --- a/extensions/package-manager/src/Command/CheckForUpdates.php +++ b/extensions/package-manager/src/Command/CheckForUpdates.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class CheckForUpdates implements BusinessCommandInterface +class CheckForUpdates extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var \Flarum\User\User */ diff --git a/extensions/package-manager/src/Command/GlobalUpdate.php b/extensions/package-manager/src/Command/GlobalUpdate.php index 5dfa5219b..a2fb69f34 100644 --- a/extensions/package-manager/src/Command/GlobalUpdate.php +++ b/extensions/package-manager/src/Command/GlobalUpdate.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class GlobalUpdate implements BusinessCommandInterface +class GlobalUpdate extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var \Flarum\User\User */ diff --git a/extensions/package-manager/src/Command/MajorUpdate.php b/extensions/package-manager/src/Command/MajorUpdate.php index d2c3d3462..97bae589b 100644 --- a/extensions/package-manager/src/Command/MajorUpdate.php +++ b/extensions/package-manager/src/Command/MajorUpdate.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class MajorUpdate implements BusinessCommandInterface +class MajorUpdate extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var \Flarum\User\User */ diff --git a/extensions/package-manager/src/Command/MinorUpdate.php b/extensions/package-manager/src/Command/MinorUpdate.php index 536f88339..e1cb08101 100755 --- a/extensions/package-manager/src/Command/MinorUpdate.php +++ b/extensions/package-manager/src/Command/MinorUpdate.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class MinorUpdate implements BusinessCommandInterface +class MinorUpdate extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var \Flarum\User\User */ diff --git a/extensions/package-manager/src/Command/RemoveExtension.php b/extensions/package-manager/src/Command/RemoveExtension.php index 8f2677adf..853585dad 100755 --- a/extensions/package-manager/src/Command/RemoveExtension.php +++ b/extensions/package-manager/src/Command/RemoveExtension.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class RemoveExtension implements BusinessCommandInterface +class RemoveExtension extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var User */ diff --git a/extensions/package-manager/src/Command/RequireExtension.php b/extensions/package-manager/src/Command/RequireExtension.php index 2741cb9fd..88bc1b975 100755 --- a/extensions/package-manager/src/Command/RequireExtension.php +++ b/extensions/package-manager/src/Command/RequireExtension.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class RequireExtension implements BusinessCommandInterface +class RequireExtension extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var User */ diff --git a/extensions/package-manager/src/Command/UpdateExtension.php b/extensions/package-manager/src/Command/UpdateExtension.php index 7b4344ad7..cf74c484c 100755 --- a/extensions/package-manager/src/Command/UpdateExtension.php +++ b/extensions/package-manager/src/Command/UpdateExtension.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class UpdateExtension implements BusinessCommandInterface +class UpdateExtension extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var User */ diff --git a/extensions/package-manager/src/Command/WhyNot.php b/extensions/package-manager/src/Command/WhyNot.php index 5c0b4fecc..4e2d0fc2a 100755 --- a/extensions/package-manager/src/Command/WhyNot.php +++ b/extensions/package-manager/src/Command/WhyNot.php @@ -12,13 +12,8 @@ namespace Flarum\PackageManager\Command; use Flarum\PackageManager\Task\Task; use Flarum\User\User; -class WhyNot implements BusinessCommandInterface +class WhyNot extends AbstractActionCommand { - /** - * @var Task - */ - public $task = null; - /** * @var User */ diff --git a/extensions/package-manager/src/Composer/ComposerAdapter.php b/extensions/package-manager/src/Composer/ComposerAdapter.php index a678435f4..1902735ce 100644 --- a/extensions/package-manager/src/Composer/ComposerAdapter.php +++ b/extensions/package-manager/src/Composer/ComposerAdapter.php @@ -60,6 +60,7 @@ class ComposerAdapter $exitCode = $this->application->run($input, $this->output); chdir($currDir); + // @phpstan-ignore-next-line $command = $input->__toString(); $output = $this->output->fetch(); diff --git a/extensions/package-manager/src/Job/ComposerCommandJob.php b/extensions/package-manager/src/Job/ComposerCommandJob.php index 4fb6fe8a4..be9e2140f 100644 --- a/extensions/package-manager/src/Job/ComposerCommandJob.php +++ b/extensions/package-manager/src/Job/ComposerCommandJob.php @@ -10,7 +10,7 @@ namespace Flarum\PackageManager\Job; use Flarum\Bus\Dispatcher; -use Flarum\PackageManager\Command\BusinessCommandInterface; +use Flarum\PackageManager\Command\AbstractActionCommand; use Flarum\PackageManager\Composer\ComposerAdapter; use Flarum\Queue\AbstractJob; use Illuminate\Queue\Middleware\WithoutOverlapping; @@ -19,7 +19,7 @@ use Throwable; class ComposerCommandJob extends AbstractJob { /** - * @var BusinessCommandInterface + * @var AbstractActionCommand */ protected $command; @@ -28,7 +28,7 @@ class ComposerCommandJob extends AbstractJob */ protected $phpVersion; - public function __construct(BusinessCommandInterface $command, string $phpVersion) + public function __construct(AbstractActionCommand $command, string $phpVersion) { $this->command = $command; $this->phpVersion = $phpVersion; diff --git a/extensions/package-manager/src/Job/Dispatcher.php b/extensions/package-manager/src/Job/Dispatcher.php index e5dd37864..20026dc07 100644 --- a/extensions/package-manager/src/Job/Dispatcher.php +++ b/extensions/package-manager/src/Job/Dispatcher.php @@ -10,7 +10,7 @@ namespace Flarum\PackageManager\Job; use Flarum\Bus\Dispatcher as Bus; -use Flarum\PackageManager\Command\BusinessCommandInterface; +use Flarum\PackageManager\Command\AbstractActionCommand; use Flarum\PackageManager\Task\Task; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Queue\Queue; @@ -63,7 +63,7 @@ class Dispatcher return $this; } - public function dispatch(BusinessCommandInterface $command): DispatcherResponse + public function dispatch(AbstractActionCommand $command): DispatcherResponse { $queueJobs = ($this->runSyncOverride === false) || ($this->runSyncOverride !== true && $this->settings->get('flarum-package-manager.queue_jobs')); diff --git a/extensions/package-manager/src/Settings/LastUpdateRun.php b/extensions/package-manager/src/Settings/LastUpdateRun.php index e37b8d9c1..4a21f9f14 100644 --- a/extensions/package-manager/src/Settings/LastUpdateRun.php +++ b/extensions/package-manager/src/Settings/LastUpdateRun.php @@ -26,7 +26,7 @@ class LastUpdateRun implements JsonSetting protected $data; /** - * @var {'major'|'minor'|'global'} + * @var string|null */ protected $activeUpdate; diff --git a/extensions/package-manager/src/Task/Task.php b/extensions/package-manager/src/Task/Task.php index ec4bc3e66..9ce2f16d7 100644 --- a/extensions/package-manager/src/Task/Task.php +++ b/extensions/package-manager/src/Task/Task.php @@ -13,16 +13,16 @@ use Carbon\Carbon; use Flarum\Database\AbstractModel; /** - * @property int id - * @property int status - * @property string operation - * @property string command - * @property string package - * @property string output - * @property Carbon created_at - * @property Carbon started_at - * @property Carbon finished_at - * @property int peak_memory_used + * @property int $id + * @property int $status + * @property string $operation + * @property string $command + * @property string $package + * @property string $output + * @property Carbon $created_at + * @property Carbon $started_at + * @property Carbon $finished_at + * @property float $peak_memory_used */ class Task extends AbstractModel { diff --git a/extensions/pusher/src/Api/Controller/AuthController.php b/extensions/pusher/src/Api/Controller/AuthController.php index 8fac2c880..fa95c6d8f 100644 --- a/extensions/pusher/src/Api/Controller/AuthController.php +++ b/extensions/pusher/src/Api/Controller/AuthController.php @@ -48,6 +48,7 @@ class AuthController implements RequestHandlerInterface $this->settings->get('flarum-pusher.app_key'), $this->settings->get('flarum-pusher.app_secret'), $this->settings->get('flarum-pusher.app_id'), + // @phpstan-ignore-next-line ['cluster' => $this->settings->get('flarum-pusher.app_cluster')] ); diff --git a/extensions/pusher/src/Listener/PushNewPost.php b/extensions/pusher/src/Listener/PushNewPost.php index 851b14251..390946c25 100644 --- a/extensions/pusher/src/Listener/PushNewPost.php +++ b/extensions/pusher/src/Listener/PushNewPost.php @@ -9,6 +9,7 @@ namespace Flarum\Pusher\Listener; +use Flarum\Extension\ExtensionManager; use Flarum\Post\Event\Posted; use Flarum\User\Guest; use Flarum\User\User; @@ -22,9 +23,15 @@ class PushNewPost */ protected $pusher; - public function __construct(Pusher $pusher) + /** + * @var ExtensionManager + */ + protected $extensions; + + public function __construct(Pusher $pusher, ExtensionManager $extensions) { $this->pusher = $pusher; + $this->extensions = $extensions; } public function handle(Posted $event) @@ -43,6 +50,7 @@ class PushNewPost return; } + // @phpstan-ignore-next-line foreach ($response->channels as $name => $channel) { $userId = Str::after($name, 'private-user'); @@ -53,7 +61,7 @@ class PushNewPost } if (count($channels)) { - $tags = $event->post->discussion->tags; + $tags = $this->extensions->isEnabled('flarum-tags') ? $event->post->discussion->tags : null; $this->pusher->trigger($channels, 'newPost', [ 'postId' => $event->post->id, diff --git a/extensions/pusher/src/Provider/PusherProvider.php b/extensions/pusher/src/Provider/PusherProvider.php index 11efb7f23..18129516b 100644 --- a/extensions/pusher/src/Provider/PusherProvider.php +++ b/extensions/pusher/src/Provider/PusherProvider.php @@ -29,6 +29,7 @@ class PusherProvider extends AbstractServiceProvider $settings->get('flarum-pusher.app_key'), $settings->get('flarum-pusher.app_secret'), $settings->get('flarum-pusher.app_id'), + // @phpstan-ignore-next-line $options ); }); diff --git a/extensions/sticky/extend.php b/extensions/sticky/extend.php index 3e952c99c..5e08a4a08 100644 --- a/extensions/sticky/extend.php +++ b/extensions/sticky/extend.php @@ -9,6 +9,7 @@ use Flarum\Api\Controller\ListDiscussionsController; use Flarum\Api\Serializer\DiscussionSerializer; +use Flarum\Discussion\Discussion; use Flarum\Discussion\Event\Saving; use Flarum\Discussion\Filter\DiscussionFilterer; use Flarum\Discussion\Search\DiscussionSearcher; @@ -26,6 +27,9 @@ return [ ->js(__DIR__.'/js/dist/forum.js') ->css(__DIR__.'/less/forum.less'), + (new Extend\Model(Discussion::class)) + ->cast('is_sticky', 'bool'), + (new Extend\Post()) ->type(DiscussionStickiedPost::class), diff --git a/extensions/sticky/src/PinStickiedDiscussionsToTop.php b/extensions/sticky/src/PinStickiedDiscussionsToTop.php index 22757dfa4..44e956204 100755 --- a/extensions/sticky/src/PinStickiedDiscussionsToTop.php +++ b/extensions/sticky/src/PinStickiedDiscussionsToTop.php @@ -43,12 +43,12 @@ class PinStickiedDiscussionsToTop // reorder the unread ones up to the top. $sticky = clone $query; $sticky->where('is_sticky', true); - $sticky->orders = null; + unset($sticky->orders); $query->union($sticky); $read = $query->newQuery() - ->selectRaw(1) + ->selectRaw('1') ->from('discussion_user as sticky') ->whereColumn('sticky.discussion_id', 'id') ->where('sticky.user_id', '=', $filterState->getActor()->id) @@ -58,14 +58,14 @@ class PinStickiedDiscussionsToTop // argument in orderByRaw) for now due to a bug in Laravel which // would add the bindings in the wrong order. $query->orderByRaw('is_sticky and not exists ('.$read->toSql().') and last_posted_at > ? desc') - ->addBinding(array_merge($read->getBindings(), [$filterState->getActor()->read_time ?: 0]), 'union'); + ->addBinding(array_merge($read->getBindings(), [$filterState->getActor()->marked_all_as_read_at ?: 0]), 'union'); $query->unionOrders = array_merge($query->unionOrders, $query->orders); $query->unionLimit = $query->limit; $query->unionOffset = $query->offset; $query->limit = $sticky->limit = $query->offset + $query->limit; - $query->offset = $sticky->offset = null; + unset($query->offset, $sticky->offset); } } } diff --git a/extensions/sticky/src/Post/DiscussionStickiedPost.php b/extensions/sticky/src/Post/DiscussionStickiedPost.php index c9204b1e0..c6a1c1f0c 100755 --- a/extensions/sticky/src/Post/DiscussionStickiedPost.php +++ b/extensions/sticky/src/Post/DiscussionStickiedPost.php @@ -9,6 +9,7 @@ namespace Flarum\Sticky\Post; +use Carbon\Carbon; use Flarum\Post\AbstractEventPost; use Flarum\Post\MergeableInterface; use Flarum\Post\Post; @@ -59,7 +60,7 @@ class DiscussionStickiedPost extends AbstractEventPost implements MergeableInter $post = new static; $post->content = static::buildContent($isSticky); - $post->created_at = time(); + $post->created_at = Carbon::now(); $post->discussion_id = $discussionId; $post->user_id = $userId; diff --git a/extensions/subscriptions/extend.php b/extensions/subscriptions/extend.php index e39da0de5..468265cc1 100644 --- a/extensions/subscriptions/extend.php +++ b/extensions/subscriptions/extend.php @@ -14,6 +14,7 @@ use Flarum\Discussion\Discussion; use Flarum\Discussion\Event\Saving; use Flarum\Discussion\Filter\DiscussionFilterer; use Flarum\Discussion\Search\DiscussionSearcher; +use Flarum\Discussion\UserState; use Flarum\Extend; use Flarum\Post\Event\Deleted; use Flarum\Post\Event\Hidden; @@ -24,6 +25,7 @@ use Flarum\Subscriptions\Listener; use Flarum\Subscriptions\Notification\FilterVisiblePostsBeforeSending; use Flarum\Subscriptions\Notification\NewPostBlueprint; use Flarum\Subscriptions\Query\SubscriptionFilterGambit; +use Flarum\User\User; return [ (new Extend\Frontend('forum')) @@ -33,6 +35,12 @@ return [ new Extend\Locales(__DIR__.'/locale'), + (new Extend\Model(User::class)) + ->cast('last_read_post_number', 'integer'), + + (new Extend\Model(UserState::class)) + ->cast('subscription', 'string'), + (new Extend\View) ->namespace('flarum-subscriptions', __DIR__.'/views'), diff --git a/extensions/suspend/extend.php b/extensions/suspend/extend.php index 7e66e7609..fe924d00b 100644 --- a/extensions/suspend/extend.php +++ b/extensions/suspend/extend.php @@ -34,7 +34,9 @@ return [ ->css(__DIR__.'/less/admin.less'), (new Extend\Model(User::class)) - ->dateAttribute('suspended_until'), + ->cast('suspended_until', 'datetime') + ->cast('suspend_reason', 'string') + ->cast('suspend_message', 'string'), (new Extend\ApiSerializer(UserSerializer::class)) ->attributes(AddUserSuspendAttributes::class), diff --git a/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php b/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php index 59f4d452e..a516398d9 100755 --- a/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php +++ b/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php @@ -9,6 +9,7 @@ namespace Flarum\Suspend\Listener; +use Carbon\Carbon; use DateTime; use Flarum\Suspend\Event\Suspended; use Flarum\Suspend\Event\Unsuspended; @@ -54,7 +55,7 @@ class SaveSuspensionToDatabase $actor->assertCan('suspend', $user); if ($attributes['suspendedUntil']) { - $user->suspended_until = new DateTime($attributes['suspendedUntil']); + $user->suspended_until = Carbon::createFromTimestamp((new DateTime($attributes['suspendedUntil']))->getTimestamp()); $user->suspend_reason = empty($attributes['suspendReason']) ? null : $attributes['suspendReason']; $user->suspend_message = empty($attributes['suspendMessage']) ? null : $attributes['suspendMessage']; } else { diff --git a/extensions/tags/src/Access/DiscussionPolicy.php b/extensions/tags/src/Access/DiscussionPolicy.php index 70fb9400d..a4cfccc64 100755 --- a/extensions/tags/src/Access/DiscussionPolicy.php +++ b/extensions/tags/src/Access/DiscussionPolicy.php @@ -34,7 +34,7 @@ class DiscussionPolicy extends AbstractPolicy * @param User $actor * @param string $ability * @param Discussion $discussion - * @return bool + * @return string|void */ public function can(User $actor, $ability, Discussion $discussion) { @@ -68,7 +68,7 @@ class DiscussionPolicy extends AbstractPolicy * * @param User $actor * @param Discussion $discussion - * @return bool + * @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 5c3a27c52..feb05432a 100644 --- a/extensions/tags/src/Access/GlobalPolicy.php +++ b/extensions/tags/src/Access/GlobalPolicy.php @@ -27,9 +27,9 @@ class GlobalPolicy extends AbstractPolicy } /** - * @param Flarum\User\User $actor + * @param User $actor * @param string $ability - * @return bool|void + * @return string|void */ public function can(User $actor, string $ability) { diff --git a/extensions/tags/src/Api/Serializer/TagSerializer.php b/extensions/tags/src/Api/Serializer/TagSerializer.php index 7316ae511..a989061cb 100644 --- a/extensions/tags/src/Api/Serializer/TagSerializer.php +++ b/extensions/tags/src/Api/Serializer/TagSerializer.php @@ -13,6 +13,7 @@ use Flarum\Api\Serializer\AbstractSerializer; use Flarum\Api\Serializer\DiscussionSerializer; use Flarum\Http\SlugManager; use Flarum\Tags\Tag; +use InvalidArgumentException; class TagSerializer extends AbstractSerializer { @@ -39,6 +40,12 @@ class TagSerializer extends AbstractSerializer */ protected function getDefaultAttributes($tag) { + if (! ($tag instanceof Tag)) { + throw new InvalidArgumentException( + get_class($this).' can only serialize instances of '.Tag::class + ); + } + $attributes = [ 'name' => $tag->name, 'description' => $tag->description, diff --git a/extensions/tags/src/Listener/UpdateTagMetadata.php b/extensions/tags/src/Listener/UpdateTagMetadata.php index 9fac2d079..f0f0132ed 100755 --- a/extensions/tags/src/Listener/UpdateTagMetadata.php +++ b/extensions/tags/src/Listener/UpdateTagMetadata.php @@ -18,9 +18,11 @@ use Flarum\Post\Event\Deleted as PostDeleted; use Flarum\Post\Event\Hidden as PostHidden; use Flarum\Post\Event\Posted; use Flarum\Post\Event\Restored as PostRestored; +use Flarum\Post\Post; use Flarum\Tags\Event\DiscussionWasTagged; use Flarum\Tags\Tag; use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Arr; class UpdateTagMetadata @@ -124,9 +126,9 @@ class UpdateTagMetadata } /** - * @param \Flarum\Discussion\Discussion $discussion + * @param Discussion $discussion * @param int $delta - * @param Tag[]|null $tags + * @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) diff --git a/extensions/tags/src/Post/DiscussionTaggedPost.php b/extensions/tags/src/Post/DiscussionTaggedPost.php index 043697a4c..0dd458703 100755 --- a/extensions/tags/src/Post/DiscussionTaggedPost.php +++ b/extensions/tags/src/Post/DiscussionTaggedPost.php @@ -9,6 +9,7 @@ namespace Flarum\Tags\Post; +use Carbon\Carbon; use Flarum\Post\AbstractEventPost; use Flarum\Post\MergeableInterface; use Flarum\Post\Post; @@ -61,7 +62,7 @@ class DiscussionTaggedPost extends AbstractEventPost implements MergeableInterfa $post = new static; $post->content = static::buildContent($oldTagIds, $newTagIds); - $post->created_at = time(); + $post->created_at = Carbon::now(); $post->discussion_id = $discussionId; $post->user_id = $userId; diff --git a/extensions/tags/src/Query/TagFilterGambit.php b/extensions/tags/src/Query/TagFilterGambit.php index 1dea31f16..6d8a6719e 100644 --- a/extensions/tags/src/Query/TagFilterGambit.php +++ b/extensions/tags/src/Query/TagFilterGambit.php @@ -38,7 +38,7 @@ class TagFilterGambit extends AbstractRegexGambit implements FilterInterface protected function conditions(SearchState $search, array $matches, $negate) { - $this->constrain($search->getQuery(), $matches[1], $negate); + $this->constrain($search->getQuery(), $matches[1], $negate, $search->getActor()); } public function getFilterKey(): string diff --git a/extensions/tags/src/Tag.php b/extensions/tags/src/Tag.php index 202a54a1b..2bcbab5c1 100644 --- a/extensions/tags/src/Tag.php +++ b/extensions/tags/src/Tag.php @@ -15,6 +15,7 @@ use Flarum\Discussion\Discussion; use Flarum\Group\Permission; use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; /** * @property int $id @@ -34,7 +35,13 @@ use Illuminate\Database\Eloquent\Builder; * @property int $last_posted_discussion_id * @property int $last_posted_user_id * @property string $icon - * @property TagState + * + * @property TagState $state + * @property Tag|null $parent + * @property-read Collection $children + * @property-read Collection $discussions + * @property Discussion|null $lastPostedDiscussion + * @property User|null $lastPostedUser */ class Tag extends AbstractModel { diff --git a/extensions/tags/src/TagRepository.php b/extensions/tags/src/TagRepository.php index 0ae910eaf..3997d2850 100644 --- a/extensions/tags/src/TagRepository.php +++ b/extensions/tags/src/TagRepository.php @@ -29,7 +29,7 @@ class TagRepository /** * @param array|string $relations * @param User $actor - * @return Builder + * @return Builder */ public function with($relations, User $actor): Builder { @@ -64,9 +64,8 @@ class TagRepository * user, or throw an exception. * * @param int $id - * @param User $actor + * @param User|null $actor * @return Tag - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ public function findOrFail($id, User $actor = null) { @@ -80,7 +79,7 @@ class TagRepository * certain user. * * @param User|null $user - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection */ public function all(User $user = null) { @@ -106,9 +105,9 @@ class TagRepository /** * Scope a query to only include records that are visible to a user. * - * @param Builder $query - * @param User $user - * @return Builder + * @param Builder $query + * @param User|null $user + * @return Builder */ protected function scopeVisibleTo(Builder $query, User $user = null) { diff --git a/extensions/tags/src/Utf8SlugDriver.php b/extensions/tags/src/Utf8SlugDriver.php index aef92f4fe..36df9c9e4 100644 --- a/extensions/tags/src/Utf8SlugDriver.php +++ b/extensions/tags/src/Utf8SlugDriver.php @@ -44,10 +44,13 @@ class Utf8SlugDriver implements SlugDriverInterface */ public function fromSlug(string $slug, User $actor): AbstractModel { - return $this->repository + /** @var Tag $tag */ + $tag = $this->repository ->query() ->where('slug', urldecode($slug)) ->whereVisibleTo($actor) ->firstOrFail(); + + return $tag; } } diff --git a/framework/core/src/Extend/Validator.php b/framework/core/src/Extend/Validator.php index 817367c00..0420b0e2b 100644 --- a/framework/core/src/Extend/Validator.php +++ b/framework/core/src/Extend/Validator.php @@ -31,7 +31,7 @@ class Validator implements ExtenderInterface * 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 $callback + * @param callable|class-string $callback * * The callback can be a closure or invokable class, and should accept: * - \Flarum\Foundation\AbstractValidator $flarumValidator: The Flarum validator wrapper diff --git a/framework/core/src/Extension/Extension.php b/framework/core/src/Extension/Extension.php index 6856d9214..15892470e 100644 --- a/framework/core/src/Extension/Extension.php +++ b/framework/core/src/Extension/Extension.php @@ -236,7 +236,7 @@ class Extension implements Arrayable } /** - * @return string + * @return string|null */ public function getVersion() { diff --git a/framework/core/src/Notification/Blueprint/BlueprintInterface.php b/framework/core/src/Notification/Blueprint/BlueprintInterface.php index 38f5ed060..caae87e41 100644 --- a/framework/core/src/Notification/Blueprint/BlueprintInterface.php +++ b/framework/core/src/Notification/Blueprint/BlueprintInterface.php @@ -36,7 +36,7 @@ interface BlueprintInterface /** * Get the data to be stored in the notification. * - * @return array|null + * @return mixed */ public function getData(); diff --git a/framework/core/src/Notification/MailableInterface.php b/framework/core/src/Notification/MailableInterface.php index 2804e0704..f95b17a9b 100644 --- a/framework/core/src/Notification/MailableInterface.php +++ b/framework/core/src/Notification/MailableInterface.php @@ -16,7 +16,7 @@ interface MailableInterface /** * Get the name of the view to construct a notification email with. * - * @return string + * @return string|array */ public function getEmailView(); diff --git a/framework/core/src/Post/Event/Posted.php b/framework/core/src/Post/Event/Posted.php index 104fbff1f..158e6a55b 100644 --- a/framework/core/src/Post/Event/Posted.php +++ b/framework/core/src/Post/Event/Posted.php @@ -9,25 +9,26 @@ namespace Flarum\Post\Event; -use Flarum\Post\Post; +use Flarum\Post\CommentPost; use Flarum\User\User; class Posted { /** - * @var \Flarum\Post\Post + * @var CommentPost */ public $post; /** - * @var User + * @var User|null */ public $actor; /** - * @param \Flarum\Post\Post $post + * @param CommentPost $post + * @param User|null $actor */ - public function __construct(Post $post, User $actor = null) + public function __construct(CommentPost $post, User $actor = null) { $this->post = $post; $this->actor = $actor; diff --git a/phpstan.neon b/phpstan.neon index 5c5b81eb4..5081c1bac 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,6 +5,34 @@ parameters: level: 5 paths: - framework/core/src + - extensions/akismet/src + - extensions/akismet/extend.php + - extensions/approval/src + - extensions/approval/extend.php + - extensions/flags/src + - extensions/flags/extend.php + - extensions/likes/src + - extensions/likes/extend.php + - extensions/lock/src + - extensions/lock/extend.php + - extensions/mentions/src + - extensions/mentions/extend.php + - extensions/nicknames/src + - extensions/nicknames/extend.php + - extensions/package-manager/src + - extensions/package-manager/extend.php + - extensions/pusher/src + - extensions/pusher/extend.php + - extensions/statistics/src + - extensions/statistics/extend.php + - extensions/sticky/src + - extensions/sticky/extend.php + - extensions/subscriptions/src + - extensions/subscriptions/extend.php + - extensions/suspend/src + - extensions/suspend/extend.php + - extensions/tags/src + - extensions/tags/extend.php excludePaths: - *.blade.php checkMissingIterableValueType: false