feat(phpstan): enable checkImplicitMixed#331
Conversation
📝 WalkthroughWalkthroughEnables Possibly related issues
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app-modules/bot-discord/src/Actions/VoiceChannel/JoiningChannelAction.php`:
- Around line 12-13: The type annotations for the $activeChannels parameter have
a mismatch between the declared contract and actual usage. At line 12-13 and
line 30-31, the annotations declare array<string, VoiceChannelDTO> with string
keys, but the producer code appends elements using [] syntax which creates
integer keys. Update both annotation locations (line 12-13 and line 30-31) to
use list<VoiceChannelDTO> or array<int, VoiceChannelDTO> instead to accurately
reflect that the array uses sequential integer keys, keeping the PHPStan type
contract truthful and consistent with the actual array usage pattern.
In `@app-modules/bot-discord/src/Actions/VoiceChannel/LeftChannelAction.php`:
- Around line 18-19: In the LeftChannelAction class, the in_array check at line
18 is missing the strict comparison flag. Modify the in_array function call that
checks if $user is in $channel->users to include true as the third argument,
changing it from in_array($user, $channel->users) to in_array($user,
$channel->users, true). This ensures Discord user IDs are compared using strict
equality (===) rather than loose comparison (==), preventing potential
type-coercion issues.
In `@app-modules/bot-discord/src/SlashCommands/DontAskCommand.php`:
- Around line 61-63: The `$targetUser` variable retrieved via the `get()` method
call on line 62 can be null if the user is not found in resolved users. Add a
null check immediately after the assignment to guard against this, and return an
appropriate error response (using interaction reply or similar) if `$targetUser`
is null. This will prevent the unconditional dereference of
`$targetUser->avatar` from crashing the handler when the target user cannot be
resolved.
In `@app-modules/bot-discord/src/SlashCommands/ProfileCommand.php`:
- Around line 76-77: The get() method call on
$interaction->data->resolved->users in the ProfileCommand class can return null,
but there is no null check before $mentionedUser is dereferenced at lines 85 and
99 where $mentionedUser->username is accessed. Add a null guard after the get()
assignment to verify that $mentionedUser is not null, and return the appropriate
"not introduced/no profile" response if it is null, preventing the potential
property access error.
In `@app-modules/integration-discord/src/ETL/DTOs/DiscordMessageDTO.php`:
- Around line 31-33: The code does not validate that the `author` value is an
array before accessing it with offset operators. When `$message['author']` is
not an array at runtime, accessing offsets like `$author['username']` and
`$author['id']` will cause a TypeError. Add a type guard to ensure `$author` is
an array before attempting any offset access. This check needs to be applied at
the assignment of `$author` from `$message['author']` (line 31-33 area) to
validate the type, and also apply the same guard pattern at line 53 where a
similar issue occurs with offset access on array data.
In
`@app-modules/panel-admin/src/Filament/Resources/ExternalIdentities/RelationManagers/MessagesRelationManager.php`:
- Around line 281-291: Replace the simple assignment of $reason with explicit
enum casting to ensure the correct type is passed to SubmitReport::handle.
Instead of `$reason = $data['reason'];`, use `$reason =
ViolationType::from($data['reason']);` or `$reason =
ViolationType::tryFrom($data['reason']);` to convert the scalar value returned
by Filament 5.6's Select into the proper ViolationType enum instance before
passing it as the reason parameter to the SubmitReport::handle method call.
In `@app-modules/panel-admin/src/Marketing/Pages/MeetingShowcasePage.php`:
- Around line 81-84: The assignment of $stat->total_messages to $totalMessages
lacks an explicit integer cast, relying only on the PHPStan ignore comment for
type safety. If the database COUNT(*) query returns a string instead of an
integer, the call to extractDiscordData() will throw a TypeError since it
expects an int parameter. Restore the explicit integer cast by wrapping
$stat->total_messages with (int) when assigning it to $totalMessages to ensure
runtime type coercion.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 7180a358-57f9-4ca0-aa2b-b5874abe928a
📒 Files selected for processing (64)
app-modules/bot-discord/phpstan.ignore.neonapp-modules/bot-discord/phpstan.neonapp-modules/bot-discord/src/Actions/VoiceChannel/JoiningChannelAction.phpapp-modules/bot-discord/src/Actions/VoiceChannel/LeftChannelAction.phpapp-modules/bot-discord/src/Commands/PingCommand.phpapp-modules/bot-discord/src/DTO/VoiceChannelDTO.phpapp-modules/bot-discord/src/Events/RawGatewayEvent.phpapp-modules/bot-discord/src/Events/WelcomeMember.phpapp-modules/bot-discord/src/SlashCommands/AbstractSlashCommand.phpapp-modules/bot-discord/src/SlashCommands/CargoDelasCommand.phpapp-modules/bot-discord/src/SlashCommands/DontAskCommand.phpapp-modules/bot-discord/src/SlashCommands/DynamicVoiceCommand.phpapp-modules/bot-discord/src/SlashCommands/EditProfileCommand.phpapp-modules/bot-discord/src/SlashCommands/EditVoiceChannelLimitCommand.phpapp-modules/bot-discord/src/SlashCommands/IntroductionCommand.phpapp-modules/bot-discord/src/SlashCommands/ProfileCommand.phpapp-modules/bot-discord/stubs/discord-php.stubapp-modules/community/src/Feedback/Exceptions/FeedbackException.phpapp-modules/docs/src/Discovery/Actions/ParseDocumentMetadataAction.phpapp-modules/docs/src/DocsServiceProvider.phpapp-modules/integration-discord/src/ETL/Actions/ImportDiscordMessageAction.phpapp-modules/integration-discord/src/ETL/Adapters/DiscordMessageAdapter.phpapp-modules/integration-discord/src/ETL/Console/ImportDiscordMessagesCommand.phpapp-modules/integration-discord/src/ETL/Console/ImportDiscordProfilesCommand.phpapp-modules/integration-discord/src/ETL/Console/MergeDuplicateDiscordProfilesCommand.phpapp-modules/integration-discord/src/ETL/DTOs/DiscordMessageDTO.phpapp-modules/integration-discord/src/ETL/DTOs/DiscordProfileDTO.phpapp-modules/integration-discord/src/OAuth/DiscordOAuthClient.phpapp-modules/integration-discord/src/Sync/Actions/SyncDiscordGuildAction.phpapp-modules/integration-github/src/Backfill/BackfillRepository.phpapp-modules/integration-github/src/OAuth/GitHubOAuthClient.phpapp-modules/integration-github/src/Webhook/ProjectGithubEvent.phpapp-modules/integration-github/src/Webhook/VerifyGithubSignature.phpapp-modules/integration-twitch/src/Console/SubscribeTwitchEventsCommand.phpapp-modules/integration-twitch/src/Http/Controllers/TwitchWebhookController.phpapp-modules/integration-twitch/src/Http/Middleware/VerifyTwitchSignature.phpapp-modules/integration-twitch/src/OAuth/TwitchOAuthClient.phpapp-modules/integration-whatsapp/src/Ingest/Http/Middleware/VerifyWhatsAppSignature.phpapp-modules/moderation/src/Platform/PlatformRegistry.phpapp-modules/panel-admin/src/Filament/Resources/ExternalIdentities/RelationManagers/MessagesRelationManager.phpapp-modules/panel-admin/src/Http/Middleware/ApplyTenantScopes.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/ActivityPerDay.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/MessageHeatmap.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/PeriodStats.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/TopChannels.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoiceHeatmap.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoicePerDay.phpapp-modules/panel-admin/src/Marketing/Pages/MeetingShowcasePage.phpapp-modules/panel-admin/src/Moderation/Livewire/AppealQueue.phpapp-modules/panel-admin/src/Moderation/Livewire/ModerationDashboardLivewire.phpapp-modules/panel-admin/src/Moderation/Resources/ModerationAppealResource.phpapp-modules/panel-admin/src/Moderation/Resources/ModerationRuleResource.phpapp-modules/panel-admin/src/Moderation/Widgets/ModeratorPerformanceWidget.phpapp-modules/panel-app/phpstan.ignore.neonapp-modules/panel-app/src/Livewire/Timeline/Composer.phpapp-modules/panel-app/src/Livewire/Timeline/PostShow.phpapp-modules/panel-app/src/Livewire/Timeline/ReplyComposer.phpapp-modules/panel-app/src/Pages/ProfilePage.phpapp-modules/portal/src/Livewire/HeroSection.phpapp/Console/Commands/AnalyzeDiscordProfiles.phpapp/Console/Commands/CommunityReport.phpapp/Console/Commands/FixPostSwitchTimestampsCommand.phpphpstan.ignore.neonphpstan.neon
type annotations Add PHPStan stubs for Discord PHP library magic properties and @method annotations for Laracord's message() return type. Fixes 73 implicit mixed errors and removes 11 now-resolved ignoreErrors.
errors Fix parameter types, Discord collection return types, modal component values, and Promise await calls. Resolves all 106 bot-discord implicit mixed errors.
Add @var object shape annotations to all DB::table() and DB::selectOne() results. Resolves 68 implicit mixed errors from raw query stdClass properties.
widgets Add @var object shape annotations to DB query results, type closure parameters, and narrow form data in Filament resources and moderation widgets.
Add form property PHPDoc, type-narrow getState() results, and type eager-load closure parameters in Timeline and Profile components.
payloads Type OAuth response payloads, webhook body access, middleware next() returns, and ETL command options across Discord, Twitch, GitHub, and WhatsApp modules.
Fix implicit mixed in docs, community, moderation, portal, and console commands via @var annotations, type guards, and closure parameter typing.
All 287 implicit mixed errors resolved without a baseline. New code must properly type variables that would otherwise be inferred as mixed.
type annotation Use early return + @var to survive pint formatting.
Stub find()/get() with generic return types on CollectionInterface and Resolved, removing 6 ignoreErrors for Role/User collection access.
array<string, VoiceChannelDTO> → list<VoiceChannelDTO> to match actual int-keyed append pattern. Add strict in_array comparison for user ID lookups.
Use getAttribute() for dynamic aggregate columns instead of magic property access. Use Attribute::make(set:) with typed closure param to resolve Larastan generic mismatch.
a6f505c to
7047058
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app-modules/bot-discord/src/SlashCommands/IntroductionCommand.php`:
- Around line 138-147: The type annotations for nameComponent,
nicknameComponent, and aboutComponent claim non-null values, but the get()
method calls that populate them can return null (as acknowledged by the
null-safe operators used elsewhere in the code at lines 103-105). Fix the
inconsistency by adding nullable type annotations to these three variables and
using null coalescing operators when accessing their value properties, similar
to the pattern used in EditProfileCommand. This ensures the code safely handles
cases where the get() method returns null rather than crashing on direct
property access.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 3553b9a0-04a9-4757-aa2b-5ccad2f94f82
📒 Files selected for processing (65)
app-modules/bot-discord/phpstan.ignore.neonapp-modules/bot-discord/phpstan.neonapp-modules/bot-discord/src/Actions/VoiceChannel/JoiningChannelAction.phpapp-modules/bot-discord/src/Actions/VoiceChannel/LeftChannelAction.phpapp-modules/bot-discord/src/Commands/PingCommand.phpapp-modules/bot-discord/src/DTO/VoiceChannelDTO.phpapp-modules/bot-discord/src/Events/RawGatewayEvent.phpapp-modules/bot-discord/src/Events/WelcomeMember.phpapp-modules/bot-discord/src/SlashCommands/AbstractSlashCommand.phpapp-modules/bot-discord/src/SlashCommands/CargoDelasCommand.phpapp-modules/bot-discord/src/SlashCommands/DontAskCommand.phpapp-modules/bot-discord/src/SlashCommands/DynamicVoiceCommand.phpapp-modules/bot-discord/src/SlashCommands/EditProfileCommand.phpapp-modules/bot-discord/src/SlashCommands/EditVoiceChannelLimitCommand.phpapp-modules/bot-discord/src/SlashCommands/IntroductionCommand.phpapp-modules/bot-discord/src/SlashCommands/ProfileCommand.phpapp-modules/bot-discord/stubs/discord-php.stubapp-modules/community/src/Feedback/Exceptions/FeedbackException.phpapp-modules/docs/src/Discovery/Actions/ParseDocumentMetadataAction.phpapp-modules/docs/src/DocsServiceProvider.phpapp-modules/integration-discord/src/ETL/Actions/ImportDiscordMessageAction.phpapp-modules/integration-discord/src/ETL/Adapters/DiscordMessageAdapter.phpapp-modules/integration-discord/src/ETL/Console/ImportDiscordMessagesCommand.phpapp-modules/integration-discord/src/ETL/Console/ImportDiscordProfilesCommand.phpapp-modules/integration-discord/src/ETL/Console/MergeDuplicateDiscordProfilesCommand.phpapp-modules/integration-discord/src/ETL/DTOs/DiscordMessageDTO.phpapp-modules/integration-discord/src/ETL/DTOs/DiscordProfileDTO.phpapp-modules/integration-discord/src/OAuth/DiscordOAuthClient.phpapp-modules/integration-discord/src/Sync/Actions/SyncDiscordGuildAction.phpapp-modules/integration-github/src/Backfill/BackfillRepository.phpapp-modules/integration-github/src/OAuth/GitHubOAuthClient.phpapp-modules/integration-github/src/Webhook/ProjectGithubEvent.phpapp-modules/integration-github/src/Webhook/VerifyGithubSignature.phpapp-modules/integration-twitch/src/Console/SubscribeTwitchEventsCommand.phpapp-modules/integration-twitch/src/Http/Controllers/TwitchWebhookController.phpapp-modules/integration-twitch/src/Http/Middleware/VerifyTwitchSignature.phpapp-modules/integration-twitch/src/OAuth/TwitchOAuthClient.phpapp-modules/integration-whatsapp/src/Ingest/Http/Middleware/VerifyWhatsAppSignature.phpapp-modules/moderation/src/Platform/PlatformRegistry.phpapp-modules/panel-admin/src/Filament/Resources/ExternalIdentities/RelationManagers/MessagesRelationManager.phpapp-modules/panel-admin/src/Http/Middleware/ApplyTenantScopes.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/ActivityPerDay.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/MessageHeatmap.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/PeriodStats.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/TopChannels.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoiceHeatmap.phpapp-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoicePerDay.phpapp-modules/panel-admin/src/Marketing/Pages/MeetingShowcasePage.phpapp-modules/panel-admin/src/Moderation/Livewire/AppealQueue.phpapp-modules/panel-admin/src/Moderation/Livewire/ModerationDashboardLivewire.phpapp-modules/panel-admin/src/Moderation/Resources/ModerationAppealResource.phpapp-modules/panel-admin/src/Moderation/Resources/ModerationRuleResource.phpapp-modules/panel-admin/src/Moderation/Widgets/ModeratorPerformanceWidget.phpapp-modules/panel-app/phpstan.ignore.neonapp-modules/panel-app/src/Livewire/Timeline/Composer.phpapp-modules/panel-app/src/Livewire/Timeline/PostShow.phpapp-modules/panel-app/src/Livewire/Timeline/ReplyComposer.phpapp-modules/panel-app/src/Pages/ProfilePage.phpapp-modules/portal/src/Livewire/HeroSection.phpapp-modules/profile/src/Models/Profile.phpapp/Console/Commands/AnalyzeDiscordProfiles.phpapp/Console/Commands/CommunityReport.phpapp/Console/Commands/FixPostSwitchTimestampsCommand.phpphpstan.ignore.neonphpstan.neon
✅ Files skipped from review due to trivial changes (16)
- app-modules/bot-discord/src/SlashCommands/CargoDelasCommand.php
- app-modules/bot-discord/src/Commands/PingCommand.php
- app-modules/integration-discord/src/ETL/Console/ImportDiscordProfilesCommand.php
- app-modules/integration-github/src/Backfill/BackfillRepository.php
- app-modules/bot-discord/phpstan.neon
- app-modules/panel-admin/src/Moderation/Resources/ModerationRuleResource.php
- app-modules/panel-admin/src/Moderation/Widgets/ModeratorPerformanceWidget.php
- app-modules/integration-discord/src/ETL/Actions/ImportDiscordMessageAction.php
- app-modules/integration-github/src/Webhook/ProjectGithubEvent.php
- app-modules/integration-discord/src/OAuth/DiscordOAuthClient.php
- app-modules/bot-discord/src/DTO/VoiceChannelDTO.php
- app-modules/bot-discord/src/SlashCommands/AbstractSlashCommand.php
- app-modules/docs/src/Discovery/Actions/ParseDocumentMetadataAction.php
- app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoiceHeatmap.php
- app-modules/bot-discord/src/Actions/VoiceChannel/JoiningChannelAction.php
- app-modules/integration-twitch/src/Http/Middleware/VerifyTwitchSignature.php
🚧 Files skipped from review as they are similar to previous changes (45)
- phpstan.neon
- app-modules/integration-whatsapp/src/Ingest/Http/Middleware/VerifyWhatsAppSignature.php
- app-modules/bot-discord/src/Events/RawGatewayEvent.php
- app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/ActivityPerDay.php
- app-modules/integration-discord/src/ETL/Console/MergeDuplicateDiscordProfilesCommand.php
- app-modules/integration-twitch/src/Console/SubscribeTwitchEventsCommand.php
- app-modules/integration-discord/src/ETL/Adapters/DiscordMessageAdapter.php
- phpstan.ignore.neon
- app-modules/integration-discord/src/Sync/Actions/SyncDiscordGuildAction.php
- app-modules/bot-discord/src/SlashCommands/DontAskCommand.php
- app-modules/panel-app/src/Livewire/Timeline/ReplyComposer.php
- app-modules/panel-app/src/Livewire/Timeline/PostShow.php
- app-modules/panel-admin/src/Filament/Resources/ExternalIdentities/RelationManagers/MessagesRelationManager.php
- app-modules/docs/src/DocsServiceProvider.php
- app-modules/bot-discord/src/SlashCommands/ProfileCommand.php
- app-modules/community/src/Feedback/Exceptions/FeedbackException.php
- app/Console/Commands/AnalyzeDiscordProfiles.php
- app-modules/integration-discord/src/ETL/Console/ImportDiscordMessagesCommand.php
- app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/PeriodStats.php
- app-modules/portal/src/Livewire/HeroSection.php
- app-modules/integration-discord/src/ETL/DTOs/DiscordMessageDTO.php
- app-modules/profile/src/Models/Profile.php
- app-modules/panel-app/src/Pages/ProfilePage.php
- app-modules/bot-discord/src/SlashCommands/EditVoiceChannelLimitCommand.php
- app-modules/moderation/src/Platform/PlatformRegistry.php
- app-modules/panel-admin/src/Marketing/Pages/MeetingShowcasePage.php
- app-modules/integration-discord/src/ETL/DTOs/DiscordProfileDTO.php
- app-modules/panel-admin/src/Moderation/Resources/ModerationAppealResource.php
- app/Console/Commands/FixPostSwitchTimestampsCommand.php
- app-modules/panel-app/src/Livewire/Timeline/Composer.php
- app-modules/integration-twitch/src/Http/Controllers/TwitchWebhookController.php
- app-modules/bot-discord/src/SlashCommands/EditProfileCommand.php
- app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoicePerDay.php
- app-modules/bot-discord/src/Actions/VoiceChannel/LeftChannelAction.php
- app-modules/panel-admin/src/Moderation/Livewire/AppealQueue.php
- app-modules/panel-admin/src/Http/Middleware/ApplyTenantScopes.php
- app-modules/integration-twitch/src/OAuth/TwitchOAuthClient.php
- app-modules/panel-app/phpstan.ignore.neon
- app-modules/bot-discord/phpstan.ignore.neon
- app-modules/bot-discord/src/SlashCommands/DynamicVoiceCommand.php
- app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/MessageHeatmap.php
- app-modules/bot-discord/stubs/discord-php.stub
- app-modules/panel-admin/src/Moderation/Livewire/ModerationDashboardLivewire.php
- app-modules/integration-github/src/OAuth/GitHubOAuthClient.php
- app/Console/Commands/CommunityReport.php
Note
No logic or behavior changes. All modifications are type annotations, PHPStan stubs, and type-narrowing guards.
Summary
checkImplicitMixed: trueat PHPStan level 7 — a level-10 rule applied standalone, enforcing proper typing for all variables that would otherwise be inferred asmixedapp-modules/bot-discord/stubs/) for magic Part properties (Member::$user,Guild::$icon,VoiceStateUpdate::$channel_id, etc.)@methodannotations for Laracord'smessage()return type onAbstractSlashCommand,WelcomeMember, andPingCommandDB::table()->first()/DB::selectOne()results with@var object{...}shapes (CommunityReport, panel-admin queries, FixPostSwitchTimestamps)getState()returns, OAuth->json()payloads, webhook bodies, and middleware$next()callsignoreErrorsentries inbot-discord/phpstan.ignore.neonVisual Overview
287 → 0 errors — PR summary card
Closes #324