From 07c058cf68e8878151fb273a915dce93a97e5840 Mon Sep 17 00:00:00 2001 From: danielhe4rt Date: Sun, 22 Mar 2026 21:51:40 -0300 Subject: [PATCH 1/5] chore(phpstan): upgrade to level 6 --- phpstan.neon | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 0e49276a..ff657aee 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,9 +5,7 @@ includes: parameters: reportUnmatchedIgnoredErrors: false - level: 1 + level: 6 paths: - app/ - - database/ - - routes/ From 5985b941fbe8a06404388fada6958057044a3f61 Mon Sep 17 00:00:00 2001 From: danielhe4rt Date: Sun, 22 Mar 2026 21:51:43 -0300 Subject: [PATCH 2/5] refactor(events): add proper PHPDoc annotations and type hints --- app-modules/events/src/Models/EventAgenda.php | 11 +++++ app-modules/events/src/Models/EventModel.php | 48 +++++++++++++------ .../events/src/Models/EventSegment.php | 1 + .../events/src/Models/EventSubmission.php | 14 ++++-- .../events/src/Models/Pivot/EventAttend.php | 4 ++ .../Models/Pivot/EventSubmissionSpeaker.php | 7 +++ app-modules/events/src/Models/Sponsor.php | 4 +- 7 files changed, 68 insertions(+), 21 deletions(-) diff --git a/app-modules/events/src/Models/EventAgenda.php b/app-modules/events/src/Models/EventAgenda.php index e4eb5a43..491bccfc 100644 --- a/app-modules/events/src/Models/EventAgenda.php +++ b/app-modules/events/src/Models/EventAgenda.php @@ -4,6 +4,7 @@ namespace He4rt\Events\Models; +use Carbon\Carbon; use He4rt\Events\Database\Factories\EventAgendaFactory; use He4rt\Events\Enums\SchedulableTypeEnum; use He4rt\Identity\Tenant\Models\Tenant; @@ -17,10 +18,14 @@ /** * @property string $schedulable_type + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at */ #[UseFactory(EventAgendaFactory::class)] class EventAgenda extends Model { + /** @use HasFactory */ use HasFactory; use SoftDeletes; @@ -51,11 +56,17 @@ public function event(): BelongsTo return $this->belongsTo(EventModel::class, 'event_id'); } + /** + * @return MorphTo + */ public function schedulable(): MorphTo { return $this->morphTo(); } + /** + * @return Attribute + */ protected function scheduleType(): Attribute { return Attribute::get(fn () => SchedulableTypeEnum::from($this->schedulable_type)); diff --git a/app-modules/events/src/Models/EventModel.php b/app-modules/events/src/Models/EventModel.php index c7dfc1d0..920bbdf1 100644 --- a/app-modules/events/src/Models/EventModel.php +++ b/app-modules/events/src/Models/EventModel.php @@ -4,7 +4,7 @@ namespace He4rt\Events\Models; -use Carbon\Traits\Date; +use Carbon\Carbon; use Exception; use He4rt\Events\Database\Factories\EventFactory; use He4rt\Events\Enums\AttendingStatusEnum; @@ -23,7 +23,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; -use Illuminate\Database\Eloquent\Relations\Pivot; /** * @property bool $active @@ -36,13 +35,14 @@ * @property int $attendees_count * @property int $waitlist_count * @property int $tenant_id - * @property Date $end_at - * @property Date $start_at - * @property Date $event_at + * @property Carbon $end_at + * @property Carbon $start_at + * @property Carbon $event_at */ #[UseFactory(EventFactory::class)] class EventModel extends Model { + /** @use HasFactory */ use HasFactory; protected $table = 'events'; @@ -64,7 +64,7 @@ class EventModel extends Model ]; /** - * @return BelongsToMany + * @return BelongsToMany */ public function attendees(): BelongsToMany { @@ -113,7 +113,9 @@ public function leave(mixed $userId): bool return false; } - match ($eventAttend->pivot->status) { + /** @var EventAttend $pivot */ + $pivot = $eventAttend->pivot; + match ($pivot->status) { AttendingStatusEnum::Attending => $this->decrement('attendees_count'), AttendingStatusEnum::Waitlist => $this->decrement('waitlist_count'), default => null, @@ -124,19 +126,23 @@ public function leave(mixed $userId): bool return true; } - public function isParticipating($userId): bool + public function isParticipating(mixed $userId): bool { return $this->attendees()->where('user_id', $userId)->exists(); } public function isAttending(): bool { - return $this->attendees->first()->pivot->status === AttendingStatusEnum::Attending; + return $this->attendees() + ->wherePivot('status', AttendingStatusEnum::Attending) + ->exists(); } public function onWaitlist(): bool { - return $this->attendees->first()->pivot->status === AttendingStatusEnum::Waitlist; + return $this->attendees() + ->wherePivot('status', AttendingStatusEnum::Waitlist) + ->exists(); } /** @@ -156,7 +162,7 @@ public function talks(): HasMany } /** - * @return HasManyThrough + * @return HasManyThrough */ public function speakers(): HasManyThrough { @@ -172,6 +178,7 @@ public function agenda(): HasMany ->oldest('starting_at'); } + /** @return Attribute */ protected function duration(): Attribute { return Attribute::make( @@ -179,27 +186,34 @@ protected function duration(): Attribute ); } + /** @return Attribute */ protected function start(): Attribute { return Attribute::make( - get: fn () => $this->start_at?->format('H:i'), + get: fn () => $this->start_at->format('H:i'), ); } + /** @return Attribute */ protected function day(): Attribute { return Attribute::make( - get: fn () => $this->event_at?->format('d/m'), + get: fn () => $this->event_at->format('d/m'), ); } + /** @return Attribute */ protected function end(): Attribute { return Attribute::make( - get: fn () => $this->end_at?->format('H:i'), + get: fn () => $this->end_at->format('H:i'), ); } + /** + * @param Builder $query + * @return Builder + */ #[Scope] protected function availableHours(Builder $query, string $start, string $end): Builder { @@ -215,8 +229,12 @@ protected function availableHours(Builder $query, string $start, string $end): B }); } + /** + * @param Builder $query + * @return Builder + */ #[Scope] - protected function active($query) + protected function active(Builder $query): Builder { return $query->where('active', true); } diff --git a/app-modules/events/src/Models/EventSegment.php b/app-modules/events/src/Models/EventSegment.php index 1b09a4de..6a206361 100644 --- a/app-modules/events/src/Models/EventSegment.php +++ b/app-modules/events/src/Models/EventSegment.php @@ -11,6 +11,7 @@ class EventSegment extends Model { use Sushi; + /** @var array */ protected $rows = [ [ 'title' => 'Abertura do Evento', diff --git a/app-modules/events/src/Models/EventSubmission.php b/app-modules/events/src/Models/EventSubmission.php index 79609a16..4d529b38 100644 --- a/app-modules/events/src/Models/EventSubmission.php +++ b/app-modules/events/src/Models/EventSubmission.php @@ -16,7 +16,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Database\Eloquent\Relations\Pivot; /** * @property int|string $event_id @@ -31,6 +30,7 @@ #[UseFactory(EventSubmissionFactory::class)] class EventSubmission extends Model { + /** @use HasFactory */ use HasFactory; protected $table = 'events_talks'; @@ -62,7 +62,7 @@ public function event(): BelongsTo } /** - * @return BelongsToMany + * @return BelongsToMany */ public function speakers(): BelongsToMany { @@ -82,17 +82,23 @@ public function tenant(): BelongsTo return $this->belongsTo(Tenant::class); } + /** + * @return Attribute + */ protected function start(): Attribute { return Attribute::make( - get: fn () => $this->starts_at?->format('H:i'), + get: fn () => $this->starts_at->format('H:i'), ); } + /** + * @return Attribute + */ protected function end(): Attribute { return Attribute::make( - get: fn () => $this->ends_at?->format('H:i'), + get: fn () => $this->ends_at->format('H:i'), ); } diff --git a/app-modules/events/src/Models/Pivot/EventAttend.php b/app-modules/events/src/Models/Pivot/EventAttend.php index 2ff73d27..9f51376f 100644 --- a/app-modules/events/src/Models/Pivot/EventAttend.php +++ b/app-modules/events/src/Models/Pivot/EventAttend.php @@ -7,6 +7,10 @@ use He4rt\Events\Enums\AttendingStatusEnum; use Illuminate\Database\Eloquent\Relations\Pivot; +/** + * @property AttendingStatusEnum $status + * @property int $attend_order + */ class EventAttend extends Pivot { protected $table = 'events_attendees'; diff --git a/app-modules/events/src/Models/Pivot/EventSubmissionSpeaker.php b/app-modules/events/src/Models/Pivot/EventSubmissionSpeaker.php index 82e85cb5..30e91aeb 100644 --- a/app-modules/events/src/Models/Pivot/EventSubmissionSpeaker.php +++ b/app-modules/events/src/Models/Pivot/EventSubmissionSpeaker.php @@ -4,14 +4,21 @@ namespace He4rt\Events\Models\Pivot; +use Carbon\Carbon; +use He4rt\Events\Database\Factories\EventSubmissionSpeakerFactory; use He4rt\Events\Models\EventSubmission; use He4rt\Identity\User\Models\User; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\Pivot; +/** + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + */ class EventSubmissionSpeaker extends Pivot { + /** @use HasFactory */ use HasFactory; protected $table = 'event_submission_speakers'; diff --git a/app-modules/events/src/Models/Sponsor.php b/app-modules/events/src/Models/Sponsor.php index b91ecb5a..df5f8886 100644 --- a/app-modules/events/src/Models/Sponsor.php +++ b/app-modules/events/src/Models/Sponsor.php @@ -12,7 +12,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Database\Eloquent\Relations\Pivot; use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; @@ -24,6 +23,7 @@ #[UseFactory(SponsorFactory::class)] class Sponsor extends Model implements HasMedia { + /** @use HasFactory */ use HasFactory; use InteractsWithMedia; @@ -47,7 +47,7 @@ public function tenant(): BelongsTo } /** - * @return BelongsToMany + * @return BelongsToMany */ public function events(): BelongsToMany { From 966e3b53f47905f1ee26418c190f5f850495627c Mon Sep 17 00:00:00 2001 From: danielhe4rt Date: Sun, 22 Mar 2026 21:51:46 -0300 Subject: [PATCH 3/5] refactor(events/filament): add proper type annotations and fix static analysis issues --- .../EventAgenda/EventAgendaResource.php | 1 + .../AttendeesRelationManager.php | 8 +++++++- .../RelationManagers/TalksRelationManager.php | 2 ++ .../App/EventModels/Pages/ListEventModels.php | 4 ++++ .../src/Filament/Events/EventLandingPage.php | 7 +++++-- .../Filament/Events/ParticipantDashboard.php | 10 +++++----- .../EventSubmissionSpeakerResource.php | 9 +++++---- .../events/src/Filament/Shared/EventLogin.php | 10 ++++++---- .../Shared/Schemas/StartEndFieldsSchema.php | 17 +++-------------- 9 files changed, 38 insertions(+), 30 deletions(-) diff --git a/app-modules/events/src/Filament/Admin/Resources/EventAgenda/EventAgendaResource.php b/app-modules/events/src/Filament/Admin/Resources/EventAgenda/EventAgendaResource.php index fc0e6c94..836879dd 100644 --- a/app-modules/events/src/Filament/Admin/Resources/EventAgenda/EventAgendaResource.php +++ b/app-modules/events/src/Filament/Admin/Resources/EventAgenda/EventAgendaResource.php @@ -153,6 +153,7 @@ public static function getGloballySearchableAttributes(): array public static function getGlobalSearchResultDetails(Model $record): array { + /** @var EventAgenda $record */ $details = []; if ($record->tenant) { diff --git a/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/AttendeesRelationManager.php b/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/AttendeesRelationManager.php index 42ecb5a0..f88af0e4 100644 --- a/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/AttendeesRelationManager.php +++ b/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/AttendeesRelationManager.php @@ -11,6 +11,7 @@ use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use He4rt\Events\Models\EventModel; use He4rt\Identity\Filament\Admin\Resources\Users\UserResource; use He4rt\Identity\User\Models\User; use Illuminate\Database\Eloquent\Model; @@ -27,6 +28,7 @@ class AttendeesRelationManager extends RelationManager public static function getBadge(Model $ownerRecord, string $pageClass): ?string { + /** @var EventModel $ownerRecord */ return (string) $ownerRecord->attendees()->count(); } @@ -48,7 +50,11 @@ public function table(Table $table): Table ]) ->recordActions([ DetachAction::make() - ->using(fn (User $record) => $this->getOwnerRecord()->leave($record->getKey())), + ->using(function (User $record): void { + /** @var EventModel $ownerRecord */ + $ownerRecord = $this->getOwnerRecord(); + $ownerRecord->leave($record->getKey()); + }), ]); } } diff --git a/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/TalksRelationManager.php b/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/TalksRelationManager.php index a73b774b..79955d2c 100644 --- a/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/TalksRelationManager.php +++ b/app-modules/events/src/Filament/Admin/Resources/Events/RelationManagers/TalksRelationManager.php @@ -10,6 +10,7 @@ use Filament\Support\Icons\Heroicon; use Filament\Tables\Table; use He4rt\Events\Filament\Admin\Resources\Talks\TalkResource; +use He4rt\Events\Models\EventModel; use Illuminate\Database\Eloquent\Model; class TalksRelationManager extends RelationManager @@ -20,6 +21,7 @@ class TalksRelationManager extends RelationManager public static function getBadge(Model $ownerRecord, string $pageClass): ?string { + /** @var EventModel $ownerRecord */ return (string) $ownerRecord->talks()->count(); } diff --git a/app-modules/events/src/Filament/App/EventModels/Pages/ListEventModels.php b/app-modules/events/src/Filament/App/EventModels/Pages/ListEventModels.php index 2f558e7b..9e0747a4 100644 --- a/app-modules/events/src/Filament/App/EventModels/Pages/ListEventModels.php +++ b/app-modules/events/src/Filament/App/EventModels/Pages/ListEventModels.php @@ -40,6 +40,10 @@ public function leave(string|int $eventModelId): void ->send(); } + /** + * @param Builder $query + * @return Builder + */ protected function modifyQueryWithActiveTab(Builder $query, bool $isResolvingRecord = false): Builder { return $query->where('active', true)->with('attendees')->latest('end_at'); diff --git a/app-modules/events/src/Filament/Events/EventLandingPage.php b/app-modules/events/src/Filament/Events/EventLandingPage.php index 768b19f5..95835f1e 100644 --- a/app-modules/events/src/Filament/Events/EventLandingPage.php +++ b/app-modules/events/src/Filament/Events/EventLandingPage.php @@ -6,10 +6,11 @@ use Filament\Pages\Dashboard; use Filament\Support\Enums\Width; +use He4rt\Identity\Tenant\Models\Tenant; class EventLandingPage extends Dashboard { - public $tenant; + public ?Tenant $tenant = null; protected static bool $shouldRegisterNavigation = false; @@ -17,7 +18,9 @@ class EventLandingPage extends Dashboard public function mount(): void { - $this->tenant = filament()->getTenant(); + /** @var Tenant|null $tenant */ + $tenant = filament()->getTenant(); + $this->tenant = $tenant; } public function getView(): string diff --git a/app-modules/events/src/Filament/Events/ParticipantDashboard.php b/app-modules/events/src/Filament/Events/ParticipantDashboard.php index 4299f2e2..13748c8c 100644 --- a/app-modules/events/src/Filament/Events/ParticipantDashboard.php +++ b/app-modules/events/src/Filament/Events/ParticipantDashboard.php @@ -11,11 +11,9 @@ use He4rt\Identity\Tenant\Models\Tenant; use Illuminate\Contracts\Support\Htmlable; -/** @property Tenant $tenant */ class ParticipantDashboard extends Page { - /** @var Tenant|null */ - public $tenant; + public ?Tenant $tenant = null; /** @var EventModel|null */ public $event; @@ -34,14 +32,16 @@ public function getTitle(): string|Htmlable public function mount(): void { - $this->tenant = filament()->getTenant(); + /** @var Tenant $tenant */ + $tenant = filament()->getTenant(); + $this->tenant = $tenant; $this->event = $this->tenant ->events() ->where('active', true) ->first(); - abort_unless($this->event, 404); + abort_unless($this->event !== null, 404); } public function getView(): string diff --git a/app-modules/events/src/Filament/Resources/EventSubmissionSpeakerResource.php b/app-modules/events/src/Filament/Resources/EventSubmissionSpeakerResource.php index 367c1710..f66b07d9 100644 --- a/app-modules/events/src/Filament/Resources/EventSubmissionSpeakerResource.php +++ b/app-modules/events/src/Filament/Resources/EventSubmissionSpeakerResource.php @@ -110,20 +110,21 @@ public static function getEloquentQuery(): Builder public static function getGlobalSearchEloquentQuery(): Builder { - return parent::getGlobalSearchEloquentQuery()->with(['event', 'user']); + return parent::getGlobalSearchEloquentQuery()->with(['submission.event', 'user']); } public static function getGloballySearchableAttributes(): array { - return ['event.title', 'user.name']; + return ['submission.event.title', 'user.name']; } public static function getGlobalSearchResultDetails(Model $record): array { + /** @var EventSubmissionSpeaker $record */ $details = []; - if ($record->event) { - $details['Event'] = $record->event->title; + if ($record->submission?->event) { + $details['Event'] = $record->submission->event->title; } if ($record->user) { diff --git a/app-modules/events/src/Filament/Shared/EventLogin.php b/app-modules/events/src/Filament/Shared/EventLogin.php index fd3137c9..9d729bf9 100644 --- a/app-modules/events/src/Filament/Shared/EventLogin.php +++ b/app-modules/events/src/Filament/Shared/EventLogin.php @@ -174,8 +174,9 @@ public function defaultMultiFactorChallengeForm(Schema $schema): Schema return []; } - $authProvider = Filament::auth()->getProvider(); - /** @phpstan-ignore-line */ + /** @var SessionGuard $guard */ + $guard = Filament::auth(); + $authProvider = $guard->getProvider(); $user = $authProvider->retrieveById(decrypt($this->userUndertakingMultiFactorAuthentication)); $enabledMultiFactorAuthenticationProviders = array_filter( @@ -341,8 +342,9 @@ protected function getRememberFormComponent(): Component protected function getMultiFactorProviderFormComponent(): ?Component { - $authProvider = Filament::auth()->getProvider(); - /** @phpstan-ignore-line */ + /** @var SessionGuard $guard */ + $guard = Filament::auth(); + $authProvider = $guard->getProvider(); $user = $authProvider->retrieveById(decrypt($this->userUndertakingMultiFactorAuthentication)); $enabledMultiFactorAuthenticationProviders = array_filter( diff --git a/app-modules/events/src/Filament/Shared/Schemas/StartEndFieldsSchema.php b/app-modules/events/src/Filament/Shared/Schemas/StartEndFieldsSchema.php index 6aab309f..0a8585ac 100644 --- a/app-modules/events/src/Filament/Shared/Schemas/StartEndFieldsSchema.php +++ b/app-modules/events/src/Filament/Shared/Schemas/StartEndFieldsSchema.php @@ -9,37 +9,26 @@ use Filament\Forms\Components\DateTimePicker; use Filament\Schemas\Components\Utilities\Get; use He4rt\Events\Models\EventModel; -use Illuminate\Support\Facades\Date; final class StartEndFieldsSchema { + /** @return array */ public static function make(): array { return [ DateTimePicker::make('starts_at') ->label('Starts at') ->minDate(function (Get $get): ?Carbon { - - /** @var EventModel $event */ $event = EventModel::query()->where('id', $get('event_id'))->first(); - if ($event) { - return Date::parse($event->start_at); - } - return null; + return $event?->start_at; }) ->required(), DateTimePicker::make('ends_at') ->maxDate(function (Get $get): ?Carbon { - - /** @var EventModel $event */ $event = EventModel::query()->where('id', $get('event_id'))->first(); - if ($event) { - return Date::parse($event->end_at); - } - - return null; + return $event?->end_at; }) ->after('starts_at') ->rules([ From 843e9d931ff0e3c425c349cfc7635dca7d1714c2 Mon Sep 17 00:00:00 2001 From: danielhe4rt Date: Sun, 22 Mar 2026 21:51:51 -0300 Subject: [PATCH 4/5] refactor: add proper type annotations across application modules --- .../events/src/Actions/AttendEventAction.php | 5 ++- .../identity/src/Tenant/Models/Tenant.php | 12 ++++++ app/Contracts/Paginator.php | 8 ++-- .../EventsRelationManager.php | 3 ++ .../MembersRelationManager.php | 4 +- app/Http/Middleware/BotAuthentication.php | 2 +- app/Livewire/ConnectionHub.php | 9 +++- app/Providers/Filament/EventPanelProvider.php | 41 ++++++++++++------- app/Support/Paginator.php | 6 +++ 9 files changed, 67 insertions(+), 23 deletions(-) diff --git a/app-modules/events/src/Actions/AttendEventAction.php b/app-modules/events/src/Actions/AttendEventAction.php index 7dfea2da..b8dc4a1d 100644 --- a/app-modules/events/src/Actions/AttendEventAction.php +++ b/app-modules/events/src/Actions/AttendEventAction.php @@ -6,6 +6,7 @@ use Exception; use He4rt\Events\Models\EventModel; +use He4rt\Events\Models\Pivot\EventAttend; final class AttendEventAction { @@ -14,7 +15,9 @@ final class AttendEventAction */ public function execute(EventModel $eventModel): void { - $attendingStatus = $eventModel->attendees()->first()->pivot->status; + /** @var EventAttend|null $pivot */ + $pivot = $eventModel->attendees()->first()?->pivot; + $attendingStatus = $pivot->status; $eventModel->attend(auth()->user()->id, $attendingStatus); } } diff --git a/app-modules/identity/src/Tenant/Models/Tenant.php b/app-modules/identity/src/Tenant/Models/Tenant.php index bec3a316..471739b4 100644 --- a/app-modules/identity/src/Tenant/Models/Tenant.php +++ b/app-modules/identity/src/Tenant/Models/Tenant.php @@ -4,6 +4,7 @@ namespace He4rt\Identity\Tenant\Models; +use Carbon\Carbon; use He4rt\Activity\Models\Message; use He4rt\Events\Models\EventModel; use He4rt\Gamification\Character\Models\PastSeason; @@ -20,6 +21,17 @@ use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\SoftDeletes; +/** + * @property int $id + * @property string $name + * @property string $slug + * @property string|null $domain + * @property string $owner_id + * @property bool $active + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + */ class Tenant extends Model { use HasFactory; diff --git a/app/Contracts/Paginator.php b/app/Contracts/Paginator.php index 94f5615e..b1ce3187 100644 --- a/app/Contracts/Paginator.php +++ b/app/Contracts/Paginator.php @@ -11,7 +11,7 @@ interface Paginator * * @param int $start * @param int $end - * @return array + * @return array */ public function getUrlRange($start, $end); @@ -40,7 +40,7 @@ public function url($page); /** * Add a set of query string values to the paginator. * - * @param array|string|null $key + * @param array|string|null $key * @param string|null $value * @return $this */ @@ -71,7 +71,7 @@ public function previousPageUrl(); /** * Get all of the items being paginated. * - * @return array + * @return array */ public function items(); @@ -142,7 +142,7 @@ public function isNotEmpty(); * Render the paginator using a given view. * * @param string|null $view - * @param array $data + * @param array $data * @return string */ public function render($view = null, $data = []); diff --git a/app/Filament/Shared/RelationManagers/EventsRelationManager.php b/app/Filament/Shared/RelationManagers/EventsRelationManager.php index 08806c95..7bfb089c 100644 --- a/app/Filament/Shared/RelationManagers/EventsRelationManager.php +++ b/app/Filament/Shared/RelationManagers/EventsRelationManager.php @@ -11,6 +11,8 @@ use He4rt\Events\Filament\Admin\Resources\Events\Schemas\EventForm; use He4rt\Events\Filament\Admin\Resources\Events\Tables\EventsTable; use He4rt\Events\Filament\Resources\Sponsors\Pages\EditSponsor; +use He4rt\Events\Models\Sponsor; +use He4rt\Identity\Tenant\Models\Tenant; use Illuminate\Database\Eloquent\Model; class EventsRelationManager extends RelationManager @@ -19,6 +21,7 @@ class EventsRelationManager extends RelationManager public static function getBadge(Model $ownerRecord, string $pageClass): ?string { + /** @var Tenant|Sponsor $ownerRecord */ return (string) ($ownerRecord->events->where('active', true)->count()); } diff --git a/app/Filament/Shared/RelationManagers/MembersRelationManager.php b/app/Filament/Shared/RelationManagers/MembersRelationManager.php index 0d3f3856..74de1139 100644 --- a/app/Filament/Shared/RelationManagers/MembersRelationManager.php +++ b/app/Filament/Shared/RelationManagers/MembersRelationManager.php @@ -15,6 +15,7 @@ use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use He4rt\Identity\Tenant\Models\Tenant; use Illuminate\Database\Eloquent\Model; class MembersRelationManager extends RelationManager @@ -23,7 +24,8 @@ class MembersRelationManager extends RelationManager public static function getBadge(Model $ownerRecord, string $pageClass): ?string { - return (string) ($ownerRecord->members->count()); // TODO: Change the autogenerated stub + /** @var Tenant $ownerRecord */ + return (string) ($ownerRecord->members->count()); } public function infolist(Schema $schema): Schema diff --git a/app/Http/Middleware/BotAuthentication.php b/app/Http/Middleware/BotAuthentication.php index e27deb23..0272439d 100644 --- a/app/Http/Middleware/BotAuthentication.php +++ b/app/Http/Middleware/BotAuthentication.php @@ -10,7 +10,7 @@ final class BotAuthentication { - public function handle(Request $request, Closure $next) + public function handle(Request $request, Closure $next): Response { $apiKey = $request->header('X-He4rt-Authorization'); diff --git a/app/Livewire/ConnectionHub.php b/app/Livewire/ConnectionHub.php index 8af22c51..c64bf932 100644 --- a/app/Livewire/ConnectionHub.php +++ b/app/Livewire/ConnectionHub.php @@ -4,17 +4,21 @@ namespace App\Livewire; +use He4rt\Identity\Auth\DTOs\OAuthStateDTO; use He4rt\Identity\ExternalIdentity\Enums\IdentityProvider; +use He4rt\Identity\ExternalIdentity\Models\ExternalIdentity; use He4rt\Identity\Tenant\Models\Tenant; use Illuminate\Contracts\View\View; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\RedirectResponse; use Livewire\Attributes\Computed; use Livewire\Component; class ConnectionHub extends Component { + /** @return Collection */ #[Computed] - public function userProviders() + public function userProviders(): Collection { return auth()->user()->providers()->where('tenant_id', filament()->getTenant()->getKey())->get(); } @@ -33,7 +37,8 @@ public function connect(IdentityProvider $provider): RedirectResponse $tenant = filament()->getTenant(); session()->put('tenant', $tenant->slug); - $redirectUri = $provider->getClient()->redirectUrl($tenant->slug); + $state = new OAuthStateDTO(panel: 'user', tenant: $tenant->slug); + $redirectUri = $provider->getClient()->redirectUrl($state); return redirect()->away($redirectUri); } diff --git a/app/Providers/Filament/EventPanelProvider.php b/app/Providers/Filament/EventPanelProvider.php index 089a0cb1..ba56de6e 100644 --- a/app/Providers/Filament/EventPanelProvider.php +++ b/app/Providers/Filament/EventPanelProvider.php @@ -45,19 +45,27 @@ public function panel(Panel $panel): Panel ->path(app()->isProduction() ? '' : 'event') ->tenantDomain(app()->isProduction() ? '{tenant:domain}' : null) ->loginRouteSlug('{tenant}/login') - ->renderHook(PanelsRenderHook::SIDEBAR_NAV_END, fn () => Blade::render(sprintf(<<<'BLADE' - @guest - Fazer Login - @endguest - BLADE, Filament::getLoginUrl(['tenant' => filament()->getTenant()?->slug])) - )) - ->renderHook(PanelsRenderHook::TOPBAR_END, fn () => Blade::render(sprintf(<<<'BLADE' - @guest - - @endguest - BLADE, Filament::getLoginUrl(['tenant' => filament()->getTenant()?->slug])) - )) - ->tenantViteTheme() + ->renderHook(PanelsRenderHook::SIDEBAR_NAV_END, function (): string { + /** @var Tenant|null $tenant */ + $tenant = filament()->getTenant(); + + return Blade::render(sprintf(<<<'BLADE' + @guest + Fazer Login + @endguest + BLADE, Filament::getLoginUrl(['tenant' => $tenant?->slug]))); + }) + ->renderHook(PanelsRenderHook::TOPBAR_END, function (): string { + /** @var Tenant|null $tenant */ + $tenant = filament()->getTenant(); + + return Blade::render(sprintf(<<<'BLADE' + @guest + + @endguest + BLADE, Filament::getLoginUrl(['tenant' => $tenant?->slug]))); + }) + ->tenantViteTheme() /** @phpstan-ignore method.notFound */ ->topbarLivewireComponent(GuestTopbar::class) ->sidebarLivewireComponent(GuestSidebar::class) ->discoverResources(in: app_path('Filament/Event/Resources'), for: 'App\Filament\Event\Resources') @@ -72,7 +80,12 @@ public function panel(Panel $panel): Panel 'logout' => Action::make('logout') ->label(__('filament-panels::layout.actions.logout.label')) ->icon(FilamentIcon::resolve(PanelsIconAlias::USER_MENU_LOGOUT_BUTTON) ?? Heroicon::ArrowLeftEndOnRectangle) - ->url(fn () => route('tenant.logout', ['tenant' => filament()->getTenant()?->slug])) + ->url(function (): string { + /** @var Tenant|null $tenant */ + $tenant = filament()->getTenant(); + + return route('tenant.logout', ['tenant' => $tenant?->slug]); + }) ->postToUrl() ->sort(PHP_INT_MAX), ]) diff --git a/app/Support/Paginator.php b/app/Support/Paginator.php index 215837f3..86b6e41f 100644 --- a/app/Support/Paginator.php +++ b/app/Support/Paginator.php @@ -8,8 +8,14 @@ use Illuminate\Contracts\Pagination\LengthAwarePaginator as LengthAwarePaginatorContract; use Illuminate\Pagination\LengthAwarePaginator; +/** + * @extends LengthAwarePaginator + */ final class Paginator extends LengthAwarePaginator implements PaginatorInterface { + /** + * @param LengthAwarePaginatorContract $lengthAwarePaginator + */ public static function paginate(LengthAwarePaginatorContract $lengthAwarePaginator): self { return new self( From 64f5ccf0ab58e038750f7a24a4f5372e5f525e5f Mon Sep 17 00:00:00 2001 From: danielhe4rt Date: Sun, 22 Mar 2026 21:51:56 -0300 Subject: [PATCH 5/5] chore: add .claude to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2a7490ce..eae42679 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ _ide_helper_models.php tests/Browser/Screenshots /.github/git-commit-instructions.md /.laracord +.claude