fix: resolve PHPStan errors, missing imports, and sync Pint config#191
fix: resolve PHPStan errors, missing imports, and sync Pint config#191danielhe4rt merged 4 commits into4.xfrom
Conversation
…ll modules Add the missing `use` import for LinkExternalIdentity in ResolveUserContext, which was causing runtime failures on Discord message processing, welcome member events, and the /introduction slash command. Also adds phpstan.neon and phpstan.ignore.neon configs to all app-modules (except panel-admin) so they are included in static analysis via the existing phpstan.modules.php auto-discovery mechanism.
📝 WalkthroughWalkthroughAdded per-module PHPStan configurations: each module received Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 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: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app-modules/bot-discord/phpstan.ignore.neon`:
- Around line 1-2: The NEON config currently leaves parameters.ignoreErrors
without a value (null); change parameters.ignoreErrors to an explicit empty list
so PHPStan sees an array — update the NEON so the key parameters.ignoreErrors is
defined as an empty sequence (e.g., parameters.ignoreErrors: []) to satisfy
PHPStan’s requirement.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4aa98821-5a12-4317-bff7-3236b0720f9b
📒 Files selected for processing (23)
app-modules/activity/phpstan.ignore.neonapp-modules/activity/phpstan.neonapp-modules/bot-discord/phpstan.ignore.neonapp-modules/bot-discord/phpstan.neonapp-modules/community/phpstan.ignore.neonapp-modules/community/phpstan.neonapp-modules/docs/phpstan.ignore.neonapp-modules/docs/phpstan.neonapp-modules/economy/phpstan.ignore.neonapp-modules/economy/phpstan.neonapp-modules/gamification/phpstan.ignore.neonapp-modules/gamification/phpstan.neonapp-modules/he4rt/phpstan.ignore.neonapp-modules/he4rt/phpstan.neonapp-modules/identity/phpstan.ignore.neonapp-modules/identity/phpstan.neonapp-modules/identity/src/User/Actions/ResolveUserContext.phpapp-modules/integration-discord/phpstan.ignore.neonapp-modules/integration-discord/phpstan.neonapp-modules/integration-twitch/phpstan.ignore.neonapp-modules/integration-twitch/phpstan.neonapp-modules/portal/phpstan.ignore.neonapp-modules/portal/phpstan.neon
- Fix real bugs: remove dead Character::wallet() HasOne (conflicts with HasWallet trait), wrap MessagesController with NewMessageDTO::make(), add default arms to match expressions, narrow IdentityProvider return type - Add type annotations: PHPDoc @param/@return for DTOs, Requests, Actions, Eloquent Attributes, HasFactory generics, and model @Property declarations - Suppress PHPStan limitations: Discord PHP dynamic properties, Filament magic methods, and library type compatibility in ignore files PHPStan now passes with 0 errors across all modules.
- Remove spaces after the not (!) operator across all files - Ensure code style aligns with PHPStan and Pint configuration - Update Pint config to enforce new rules: - 'not_operator_with_successor_space' - 'unary_operator_spaces'
Empty `ignoreErrors:` parses as null in NEON format. PHPStan requires it to be an array. Changed to `ignoreErrors: []` in modules with no suppressed errors.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
app-modules/community/src/Meeting/Models/MeetingType.php (1)
52-61:⚠️ Potential issue | 🟡 MinorAvoid silent empty fallback for invalid weekday values.
On Line 60,
default => ''can hide invalidweek_daydata and produce blank labels in the UI. Prefer an explicit fallback value (or fail fast) so bad data is visible.Suggested adjustment
return Attribute::get(fn () => match ($this->week_day) { 0 => 'Domingo', 1 => 'Segunda Feira', 2 => 'Terça Feira', 3 => 'Quarta Feira', 4 => 'Quinta Feira', 5 => 'Sexta Feira', 6 => 'Sábado', - default => '', + default => 'Dia inválido', });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app-modules/community/src/Meeting/Models/MeetingType.php` around lines 52 - 61, The Attribute accessor in MeetingType (the anonymous accessor returned by Attribute::get) currently uses default => '' which hides invalid week_day values; change the fallback to an explicit indicator (for example return 'Invalid weekday' or similar) or throw a clear exception (e.g., InvalidArgumentException) so invalid data is visible; update the match default arm in the MeetingType week_day Attribute getter to return that explicit message or throw, ensuring any UI or logging surfaces bad data instead of a blank string.app-modules/identity/src/ExternalIdentity/Enums/IdentityProvider.php (1)
59-69:⚠️ Potential issue | 🟡 MinorFix empty-string handling in
getScopes().When Twitch scopes are not configured (empty string default),
explode(' ', '')returns['']instead of[]. This violates the semantic expectation that an empty scope list should be empty.💡 Suggested fix
/** * `@return` array<int, string> */ public function getScopes(): array { $scopes = match ($this) { self::Discord => config('services.discord.scopes'), self::Twitch => config('services.twitch.scopes'), }; - return explode(' ', $scopes); + return array_filter(explode(' ', $scopes), fn (string $scope): bool => $scope !== ''); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app-modules/identity/src/ExternalIdentity/Enums/IdentityProvider.php` around lines 59 - 69, The getScopes() method in the IdentityProvider enum returns explode(' ', $scopes) which yields [''] when $scopes is an empty string; change getScopes() to normalize the retrieved $scopes (e.g., trim and check for empty) and return an empty array for empty or whitespace-only scope strings, otherwise split on space and filter out any empty entries (ensure this logic is applied for the cases self::Discord and self::Twitch in the getScopes() function).app-modules/gamification/src/Character/Models/Character.php (2)
149-157:⚠️ Potential issue | 🟡 MinorClamp remaining XP to prevent negative progress values.
Line 156 can become negative when experience is above the highest threshold. Returning a non-negative value keeps downstream UI/API consumers stable.
Proposed fix
- return $nextThreshold - $this->experience; + return max(0, $nextThreshold - $this->experience);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app-modules/gamification/src/Character/Models/Character.php` around lines 149 - 157, The experienceProgress accessor can return a negative number when experience exceeds the highest threshold; update the Attribute::get closure in experienceProgress() to compute remaining XP as max(0, $nextThreshold - $this->experience) (i.e., clamp negative values to zero) so downstream UI/API consumers always get a non-negative progress value, referencing the existing experienceProgress() method and LEVEL_THRESHOLDS constants.
197-197:⚠️ Potential issue | 🟡 MinorUse absolute difference for daily-bonus time checks.
Line 197 uses
diffInHours(now()), which returns a signed difference in Carbon 3+. Sincedaily_bonus_claimed_atis a past date, the result will be negative, causing the eligibility check>= 24to always fail. UsediffInHours(now(), true)to get the absolute difference instead.Proposed fix
- return Date::parse($this->daily_bonus_claimed_at)->diffInHours(now()) >= 24; + return Date::parse($this->daily_bonus_claimed_at)->diffInHours(now(), true) >= 24;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app-modules/gamification/src/Character/Models/Character.php` at line 197, The daily-bonus eligibility check in Character.php uses Date::parse($this->daily_bonus_claimed_at)->diffInHours(now()) which with Carbon 3 can return a negative value; change the call to use an absolute difference by passing true as the second argument (i.e., diffInHours(now(), true)) so the expression in the method that checks daily bonus eligibility returns the absolute hours difference and correctly evaluates >= 24.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app-modules/bot-discord/src/Actions/VoiceChannel/JoiningChannelAction.php`:
- Line 14: Handle the type mismatch by casting the user ID to string before
calling JoiningChannelAction::execute: in HandleStateChannelAction where you
call resolve(JoiningChannelAction::class)->execute(... user: $userId ...),
change the argument to user: (string)$userId so the execute(string $user)
signature is satisfied at runtime; update both call sites in
HandleStateChannelAction that pass $userId to JoiningChannelAction::execute.
In `@app-modules/bot-discord/src/Actions/VoiceChannel/LeftChannelAction.php`:
- Line 14: LeftChannelAction::execute currently expects string $user but
HandleStateChannelAction passes int|string $userId causing a TypeError; update
HandleStateChannelAction to cast $userId to string at every call to
LeftChannelAction::execute and JoiningChannelAction::execute (i.e. pass user:
(string) $userId) so both call sites consistently provide a string, ensuring
type compatibility with LeftChannelAction::execute and
JoiningChannelAction::execute.
In `@app-modules/identity/src/User/Http/Controllers/UsersController.php`:
- Around line 58-60: In UsersController update the response fields that access
the nullable HasOne relation `character` — specifically the 'badges' and
'pastSeasons' entries — to use PHP's nullsafe access so they don't throw when
`$user->character` is null; replace direct property traversal of
`$user->character->badges` and `$user->character->pastSeasons` with nullsafe
access and keep the current fallback to an empty array so the profile response
remains valid for users without a Character.
---
Outside diff comments:
In `@app-modules/community/src/Meeting/Models/MeetingType.php`:
- Around line 52-61: The Attribute accessor in MeetingType (the anonymous
accessor returned by Attribute::get) currently uses default => '' which hides
invalid week_day values; change the fallback to an explicit indicator (for
example return 'Invalid weekday' or similar) or throw a clear exception (e.g.,
InvalidArgumentException) so invalid data is visible; update the match default
arm in the MeetingType week_day Attribute getter to return that explicit message
or throw, ensuring any UI or logging surfaces bad data instead of a blank
string.
In `@app-modules/gamification/src/Character/Models/Character.php`:
- Around line 149-157: The experienceProgress accessor can return a negative
number when experience exceeds the highest threshold; update the Attribute::get
closure in experienceProgress() to compute remaining XP as max(0, $nextThreshold
- $this->experience) (i.e., clamp negative values to zero) so downstream UI/API
consumers always get a non-negative progress value, referencing the existing
experienceProgress() method and LEVEL_THRESHOLDS constants.
- Line 197: The daily-bonus eligibility check in Character.php uses
Date::parse($this->daily_bonus_claimed_at)->diffInHours(now()) which with Carbon
3 can return a negative value; change the call to use an absolute difference by
passing true as the second argument (i.e., diffInHours(now(), true)) so the
expression in the method that checks daily bonus eligibility returns the
absolute hours difference and correctly evaluates >= 24.
In `@app-modules/identity/src/ExternalIdentity/Enums/IdentityProvider.php`:
- Around line 59-69: The getScopes() method in the IdentityProvider enum returns
explode(' ', $scopes) which yields [''] when $scopes is an empty string; change
getScopes() to normalize the retrieved $scopes (e.g., trim and check for empty)
and return an empty array for empty or whitespace-only scope strings, otherwise
split on space and filter out any empty entries (ensure this logic is applied
for the cases self::Discord and self::Twitch in the getScopes() function).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f327184b-b34e-4b88-84e2-9a3beaf8fc3c
📒 Files selected for processing (115)
app-modules/activity/database/migrations/2023_01_18_211845_create_messages_table.phpapp-modules/activity/database/migrations/2023_02_10_224951_create_voice_messages_table.phpapp-modules/activity/phpstan.ignore.neonapp-modules/activity/src/Actions/NewVoiceMessage.phpapp-modules/activity/src/DTOs/NewMessageDTO.phpapp-modules/activity/src/DTOs/NewVoiceMessageDTO.phpapp-modules/activity/src/Http/Controllers/MessagesController.phpapp-modules/activity/src/Http/Requests/CreateMessageRequest.phpapp-modules/activity/src/Http/Requests/CreateVoiceMessageRequest.phpapp-modules/activity/src/Models/Message.phpapp-modules/bot-discord/phpstan.ignore.neonapp-modules/bot-discord/src/Actions/VoiceChannel/HandleStateChannelAction.phpapp-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/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/community/database/migrations/2022_12_07_005119_create_meeting_types_table.phpapp-modules/community/database/migrations/2022_12_07_005347_create_meetings_table.phpapp-modules/community/database/migrations/2022_12_07_005627_create_meeting_participants_table.phpapp-modules/community/phpstan.ignore.neonapp-modules/community/src/Feedback/Actions/CreateFeedback.phpapp-modules/community/src/Feedback/DTOs/FeedbackReviewDTO.phpapp-modules/community/src/Feedback/DTOs/NewFeedbackDTO.phpapp-modules/community/src/Feedback/Enums/ReviewTypeEnum.phpapp-modules/community/src/Feedback/Exceptions/FeedbackException.phpapp-modules/community/src/Feedback/Http/Requests/CreateFeedbackRequest.phpapp-modules/community/src/Feedback/Http/Requests/FeedbackReviewRequest.phpapp-modules/community/src/Feedback/Models/Feedback.phpapp-modules/community/src/Feedback/Models/Review.phpapp-modules/community/src/Meeting/Http/Requests/MeetingRequest.phpapp-modules/community/src/Meeting/Models/Meeting.phpapp-modules/community/src/Meeting/Models/MeetingType.phpapp-modules/docs/phpstan.ignore.neonapp-modules/docs/routes/docs-routes.phpapp-modules/docs/src/DocsController.phpapp-modules/docs/src/Documentation.phpapp-modules/economy/phpstan.ignore.neonapp-modules/economy/src/Models/Transaction.phpapp-modules/economy/src/Models/Wallet.phpapp-modules/events/src/Filament/Shared/EventLogin.phpapp-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.phpapp-modules/events/src/Models/EventModel.phpapp-modules/gamification/database/migrations/2023_01_14_053138_create_characters_table.phpapp-modules/gamification/database/migrations/2023_01_20_193234_create_badges_table.phpapp-modules/gamification/database/migrations/2023_01_22_152940_create_characters_badges_table.phpapp-modules/gamification/database/migrations/2023_01_30_174411_create_seasons_table.phpapp-modules/gamification/phpstan.ignore.neonapp-modules/gamification/src/Badge/Actions/CreateBadge.phpapp-modules/gamification/src/Badge/DTOs/NewBadgeDTO.phpapp-modules/gamification/src/Badge/Http/Requests/CreateBadgeRequest.phpapp-modules/gamification/src/Badge/Models/Badge.phpapp-modules/gamification/src/Character/Actions/ManageReputation.phpapp-modules/gamification/src/Character/Http/Requests/ClaimBadgeRequest.phpapp-modules/gamification/src/Character/Models/Character.phpapp-modules/gamification/src/Character/Models/PastSeason.phpapp-modules/gamification/src/Season/Models/Season.phpapp-modules/he4rt/phpstan.ignore.neonapp-modules/identity/database/migrations/2014_10_12_000000_create_users_table.phpapp-modules/identity/database/migrations/2014_10_12_100000_create_password_resets_table.phpapp-modules/identity/database/migrations/2023_01_18_210724_create_providers_table.phpapp-modules/identity/database/migrations/2025_11_07_162624_create_providers_tokens_table.phpapp-modules/identity/phpstan.ignore.neonapp-modules/identity/src/Auth/Actions/AuthenticateAction.phpapp-modules/identity/src/Auth/DTOs/OAuthAccessDTO.phpapp-modules/identity/src/Auth/DTOs/OAuthStateDTO.phpapp-modules/identity/src/Auth/DTOs/OAuthUserDTO.phpapp-modules/identity/src/ExternalIdentity/DTOs/NewProviderDTO.phpapp-modules/identity/src/ExternalIdentity/DTOs/ResolveUserProviderDTO.phpapp-modules/identity/src/ExternalIdentity/Enums/IdentityProvider.phpapp-modules/identity/src/ExternalIdentity/Http/Requests/CreateProviderRequest.phpapp-modules/identity/src/ExternalIdentity/Models/ExternalIdentity.phpapp-modules/identity/src/Filament/User/Pages/Dashboard.phpapp-modules/identity/src/Filament/User/Pages/UserProfile.phpapp-modules/identity/src/Tenant/Concerns/InteractsWithTenants.phpapp-modules/identity/src/Tenant/Models/Tenant.phpapp-modules/identity/src/User/DTOs/UpdateProfileDTO.phpapp-modules/identity/src/User/DTOs/UpsertInformationDTO.phpapp-modules/identity/src/User/Http/Controllers/UsersController.phpapp-modules/identity/src/User/Http/Requests/UpdateProfileRequest.phpapp-modules/identity/src/User/Models/Address.phpapp-modules/identity/src/User/Models/Information.phpapp-modules/identity/src/User/Models/User.phpapp-modules/integration-discord/phpstan.ignore.neonapp-modules/integration-discord/src/OAuth/DiscordOAuthAccessDTO.phpapp-modules/integration-discord/src/OAuth/DiscordOAuthUser.phpapp-modules/integration-twitch/phpstan.ignore.neonapp-modules/integration-twitch/src/OAuth/DTO/TwitchOAuthAccessDTO.phpapp-modules/integration-twitch/src/OAuth/DTO/TwitchOAuthDTO.phpapp-modules/integration-twitch/src/Subscriber/Contracts/TwitchSubscribersService.phpapp-modules/integration-twitch/src/Subscriber/DTO/TwitchSubscriberDTO.phpapp-modules/panel-admin/src/Filament/Resources/ExternalIdentities/Schemas/ExternalIdentityForm.phpapp-modules/panel-admin/src/Filament/Resources/Feedback/Tables/FeedbackTable.phpapp-modules/portal/phpstan.ignore.neonapp/Http/Middleware/BotAuthentication.phpapp/Http/Middleware/GuestTenantIdentifier.phpapp/Http/Middleware/VerifyIfHasTenantProviderMiddleware.phpapp/Providers/FilamentServiceProvider.phpapp/Providers/Tools/DebugbarServiceProvider.phpapp/Providers/Tools/TelescopeServiceProvider.phpapp/Rules/AvailableTalkSchedule.phpbootstrap/helpers.phpdatabase/migrations/2019_08_19_000000_create_failed_jobs_table.phpdatabase/migrations/2019_12_14_000001_create_personal_access_tokens_table.phpdatabase/migrations/2026_03_21_192333_convert_morph_types_to_aliases.phpdatabase/migrations/2026_03_21_200000_cleanup_orphan_users.phpdatabase/migrations/2026_03_22_000001_normalize_linkedin_urls.phppint.json
✅ Files skipped from review due to trivial changes (104)
- app-modules/events/src/Models/EventModel.php
- app-modules/community/database/migrations/2022_12_07_005347_create_meetings_table.php
- app-modules/community/src/Feedback/Http/Requests/CreateFeedbackRequest.php
- app-modules/community/database/migrations/2022_12_07_005119_create_meeting_types_table.php
- app-modules/activity/src/Models/Message.php
- app-modules/community/src/Feedback/Http/Requests/FeedbackReviewRequest.php
- app-modules/activity/src/DTOs/NewMessageDTO.php
- app-modules/community/src/Feedback/Models/Review.php
- app-modules/identity/src/User/DTOs/UpsertInformationDTO.php
- database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php
- app-modules/gamification/database/migrations/2023_01_22_152940_create_characters_badges_table.php
- app-modules/gamification/src/Character/Models/PastSeason.php
- database/migrations/2026_03_22_000001_normalize_linkedin_urls.php
- app-modules/integration-twitch/src/OAuth/DTO/TwitchOAuthDTO.php
- app-modules/identity/src/Filament/User/Pages/Dashboard.php
- app-modules/identity/src/ExternalIdentity/Models/ExternalIdentity.php
- app-modules/community/src/Feedback/Actions/CreateFeedback.php
- app-modules/identity/src/Tenant/Models/Tenant.php
- app-modules/integration-discord/src/OAuth/DiscordOAuthUser.php
- bootstrap/helpers.php
- app/Http/Middleware/VerifyIfHasTenantProviderMiddleware.php
- app-modules/bot-discord/src/SlashCommands/AbstractSlashCommand.php
- app-modules/economy/phpstan.ignore.neon
- app-modules/community/phpstan.ignore.neon
- app-modules/activity/src/Actions/NewVoiceMessage.php
- app-modules/bot-discord/src/SlashCommands/DontAskCommand.php
- app-modules/gamification/phpstan.ignore.neon
- app-modules/activity/src/Http/Requests/CreateVoiceMessageRequest.php
- app-modules/activity/database/migrations/2023_02_10_224951_create_voice_messages_table.php
- app-modules/identity/src/User/Models/Information.php
- app-modules/activity/src/DTOs/NewVoiceMessageDTO.php
- app-modules/community/src/Feedback/DTOs/FeedbackReviewDTO.php
- app-modules/identity/src/Auth/DTOs/OAuthStateDTO.php
- app-modules/integration-discord/phpstan.ignore.neon
- app-modules/activity/database/migrations/2023_01_18_211845_create_messages_table.php
- app-modules/community/src/Meeting/Models/Meeting.php
- app-modules/activity/src/Http/Requests/CreateMessageRequest.php
- app-modules/community/src/Meeting/Http/Requests/MeetingRequest.php
- app-modules/he4rt/phpstan.ignore.neon
- app/Http/Middleware/BotAuthentication.php
- app-modules/identity/database/migrations/2014_10_12_100000_create_password_resets_table.php
- app-modules/community/src/Feedback/Enums/ReviewTypeEnum.php
- app-modules/identity/database/migrations/2014_10_12_000000_create_users_table.php
- app-modules/bot-discord/src/Commands/PingCommand.php
- app-modules/integration-twitch/phpstan.ignore.neon
- app-modules/identity/database/migrations/2023_01_18_210724_create_providers_table.php
- app-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.php
- app-modules/gamification/src/Season/Models/Season.php
- app-modules/identity/src/Auth/Actions/AuthenticateAction.php
- app-modules/portal/phpstan.ignore.neon
- app-modules/identity/src/ExternalIdentity/DTOs/ResolveUserProviderDTO.php
- app-modules/community/src/Feedback/Models/Feedback.php
- app-modules/bot-discord/src/SlashCommands/EditVoiceChannelLimitCommand.php
- app-modules/docs/routes/docs-routes.php
- app-modules/gamification/src/Badge/Actions/CreateBadge.php
- app-modules/gamification/database/migrations/2023_01_14_053138_create_characters_table.php
- app-modules/gamification/src/Badge/Models/Badge.php
- app/Providers/Tools/DebugbarServiceProvider.php
- app-modules/bot-discord/phpstan.ignore.neon
- app/Providers/FilamentServiceProvider.php
- app-modules/activity/phpstan.ignore.neon
- app-modules/panel-admin/src/Filament/Resources/Feedback/Tables/FeedbackTable.php
- app-modules/economy/src/Models/Transaction.php
- app-modules/identity/src/ExternalIdentity/Http/Requests/CreateProviderRequest.php
- app-modules/identity/src/ExternalIdentity/DTOs/NewProviderDTO.php
- app-modules/bot-discord/src/SlashCommands/ProfileCommand.php
- app-modules/identity/database/migrations/2025_11_07_162624_create_providers_tokens_table.php
- app-modules/identity/src/User/Http/Requests/UpdateProfileRequest.php
- database/migrations/2019_08_19_000000_create_failed_jobs_table.php
- app-modules/integration-twitch/src/Subscriber/DTO/TwitchSubscriberDTO.php
- app-modules/integration-twitch/src/OAuth/DTO/TwitchOAuthAccessDTO.php
- app-modules/bot-discord/src/Actions/VoiceChannel/HandleStateChannelAction.php
- app-modules/panel-admin/src/Filament/Resources/ExternalIdentities/Schemas/ExternalIdentityForm.php
- app-modules/bot-discord/src/DTO/VoiceChannelDTO.php
- app-modules/integration-discord/src/OAuth/DiscordOAuthAccessDTO.php
- app-modules/bot-discord/src/SlashCommands/EditProfileCommand.php
- app-modules/identity/phpstan.ignore.neon
- app-modules/docs/phpstan.ignore.neon
- app/Http/Middleware/GuestTenantIdentifier.php
- app-modules/gamification/database/migrations/2023_01_20_193234_create_badges_table.php
- app-modules/identity/src/Auth/DTOs/OAuthAccessDTO.php
- app-modules/identity/src/Auth/DTOs/OAuthUserDTO.php
- app-modules/gamification/src/Badge/Http/Requests/CreateBadgeRequest.php
- database/migrations/2026_03_21_192333_convert_morph_types_to_aliases.php
- app-modules/community/src/Feedback/DTOs/NewFeedbackDTO.php
- app-modules/gamification/src/Badge/DTOs/NewBadgeDTO.php
- database/migrations/2026_03_21_200000_cleanup_orphan_users.php
- app-modules/events/src/Filament/Shared/EventLogin.php
- app-modules/identity/src/User/DTOs/UpdateProfileDTO.php
- app-modules/gamification/src/Character/Http/Requests/ClaimBadgeRequest.php
- app-modules/docs/src/DocsController.php
- app-modules/bot-discord/src/SlashCommands/IntroductionCommand.php
- app-modules/bot-discord/src/SlashCommands/CargoDelasCommand.php
- app-modules/bot-discord/src/SlashCommands/DynamicVoiceCommand.php
- app-modules/identity/src/User/Models/User.php
- app-modules/docs/src/Documentation.php
- app/Providers/Tools/TelescopeServiceProvider.php
- app-modules/gamification/database/migrations/2023_01_30_174411_create_seasons_table.php
- app-modules/community/database/migrations/2022_12_07_005627_create_meeting_participants_table.php
- app-modules/identity/src/Tenant/Concerns/InteractsWithTenants.php
- app-modules/identity/src/User/Models/Address.php
- app/Rules/AvailableTalkSchedule.php
- app-modules/economy/src/Models/Wallet.php
- pint.json
Summary
use LinkExternalIdentityimport inResolveUserContext.php, which was causingTarget class does not existerrors on Discord message processing, welcome member events, and the/introductionslash commandphpstan.neonandphpstan.ignore.neonto 11 modules (all exceptpanel-adminandevents), leveraging the existingphpstan.modules.phpauto-discoveryCharacter::wallet()HasOne,MessagesControllerDTO wrapping, incompletematchexpressions, narrowed return types), and suppressions for PHPStan limitations (Discord PHP dynamic properties, Filament magic methods)pint.jsonand reformatted codebase accordinglyTest plan
./vendor/bin/phpstan analysepasses with 0 errorsphp artisan test— 119 passed, 0 failures/introductionslash command worksSummary by CodeRabbit
Chores
Bug Fixes
Refactor