diff --git a/.env.ci b/.env.ci index 0deb6363..7cfb7a3d 100644 --- a/.env.ci +++ b/.env.ci @@ -4,6 +4,7 @@ APP_KEY= APP_DEBUG=true APP_URL=http://localhost APP_FORCE_HTTPS=false +APP_ENABLE_REGISTRATION=true SESSION_SECURE_COOKIE=false # Logging diff --git a/.env.example b/.env.example index 1886023d..24ed1310 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,13 @@ +# Application APP_NAME=solidtime APP_ENV=local APP_KEY=base64:UNQNf1SXeASNkWux01Rj8EnHYx8FO0kAxWNDwktclkk= APP_DEBUG=true APP_URL=https://solidtime.test AUDITING_ENABLED=true +APP_ENABLE_REGISTRATION=true SUPER_ADMINS=admin@example.com +PAGINATION_PER_PAGE_DEFAULT=500 # Logging LOG_CHANNEL=single @@ -25,9 +28,16 @@ DB_TEST_DATABASE=laravel DB_TEST_USERNAME=root DB_TEST_PASSWORD=root -BROADCAST_DRIVER=log +# Broadcasting +BROADCAST_DRIVER=null + +# Cache CACHE_DRIVER=file + +# Queue QUEUE_CONNECTION=sync + +# Session SESSION_DRIVER=database SESSION_LIFETIME=120 @@ -41,14 +51,6 @@ MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS="no-reply@solidtime.test" MAIL_FROM_NAME="${APP_NAME}" -PUSHER_APP_ID= -PUSHER_APP_KEY= -PUSHER_APP_SECRET= -PUSHER_HOST= -PUSHER_PORT=443 -PUSHER_SCHEME=https -PUSHER_APP_CLUSTER=mt1 - # Filesystems FILESYSTEM_DISK=s3 PUBLIC_FILESYSTEM_DISK=s3 @@ -65,16 +67,9 @@ GOTENBERG_URL=http://gotenberg:3000 VITE_HOST_NAME=vite.solidtime.test VITE_APP_NAME="${APP_NAME}" -VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" -VITE_PUSHER_HOST="${PUSHER_HOST}" -VITE_PUSHER_PORT="${PUSHER_PORT}" -VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" -VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" +# Local setup NGINX_HOST_NAME=solidtime.test NETWORK_NAME=reverse-proxy-docker-traefik_routing - FORWARD_DB_PORT=5432 FORWARD_WEB_PORT=8083 - -PAGINATION_PER_PAGE_DEFAULT=500 diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index 2eeed782..df8fc21d 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -4,16 +4,14 @@ namespace App\Actions\Fortify; -use App\Enums\Role; use App\Enums\Weekday; use App\Events\NewsletterRegistered; -use App\Models\Organization; use App\Models\User; use App\Service\IpLookup\IpLookupServiceContract; use App\Service\TimezoneService; +use App\Service\UserService; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent; @@ -34,6 +32,12 @@ class CreateNewUser implements CreatesNewUsers */ public function create(array $input): User { + if (! config('app.enable_registration')) { + throw ValidationException::withMessages([ + 'email' => [__('Registration is disabled.')], + ]); + } + Validator::make($input, [ 'name' => [ 'required', @@ -81,30 +85,16 @@ public function create(array $input): User $currency = $ipLookupResponse->currency; } $user = null; - $organization = null; - DB::transaction(function () use (&$user, &$organization, $input, $timezone, $startOfWeek, $currency): void { - $user = User::create([ - 'name' => $input['name'], - 'email' => $input['email'], - 'password' => Hash::make($input['password']), - 'timezone' => $timezone ?? 'UTC', - 'week_start' => $startOfWeek, - ]); - - $organization = new Organization; - $organization->name = explode(' ', $user->name, 2)[0]."'s Organization"; - $organization->personal_team = true; - $organization->currency = $currency ?? 'EUR'; - $organization->owner()->associate($user); - $organization->save(); - - $organization->users()->attach( - $user, [ - 'role' => Role::Owner->value, - ] + DB::transaction(function () use (&$user, $input, $timezone, $startOfWeek, $currency): void { + $userService = app(UserService::class); + $user = $userService->createUser( + $input['name'], + $input['email'], + $input['password'], + $timezone ?? 'UTC', + $startOfWeek, + $currency ?? 'EUR', ); - - $user->ownedTeams()->save($organization); }); $newsletterConsent = isset($input['newsletter_consent']) && (bool) $input['newsletter_consent']; diff --git a/app/Actions/Jetstream/AddOrganizationMember.php b/app/Actions/Jetstream/AddOrganizationMember.php index 75574c3a..556eb8d1 100644 --- a/app/Actions/Jetstream/AddOrganizationMember.php +++ b/app/Actions/Jetstream/AddOrganizationMember.php @@ -7,18 +7,16 @@ use App\Enums\Role; use App\Models\Organization; use App\Models\User; +use App\Service\MemberService; use Closure; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; use Illuminate\Validation\Rules\In; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; use Laravel\Jetstream\Contracts\AddsTeamMembers; -use Laravel\Jetstream\Events\AddingTeamMember; -use Laravel\Jetstream\Events\TeamMemberAdded; class AddOrganizationMember implements AddsTeamMembers { @@ -36,15 +34,7 @@ public function add(User $owner, Organization $organization, string $email, ?str ->where('is_placeholder', '=', false) ->firstOrFail(); - AddingTeamMember::dispatch($organization, $newOrganizationMember); - - DB::transaction(function () use ($organization, $newOrganizationMember, $role): void { - $organization->users()->attach( - $newOrganizationMember, ['role' => $role] - ); - }); - - TeamMemberAdded::dispatch($organization, $newOrganizationMember); + app(MemberService::class)->addMember($newOrganizationMember, $organization, Role::from($role)); } /** diff --git a/app/Console/Commands/Admin/UserCreateCommand.php b/app/Console/Commands/Admin/UserCreateCommand.php new file mode 100644 index 00000000..08d67d18 --- /dev/null +++ b/app/Console/Commands/Admin/UserCreateCommand.php @@ -0,0 +1,89 @@ +argument('name'); + $email = $this->argument('email'); + $askForPassword = (bool) $this->option('ask-for-password'); + + if (User::query()->where('email', $email)->where('is_placeholder', '=', false)->exists()) { + $this->error('User with email "'.$email.'" already exists.'); + + return self::FAILURE; + } + + if ($askForPassword) { + $outputPassword = false; + $password = $this->secret('Enter the password'); + } else { + $outputPassword = true; + $password = bin2hex(random_bytes(16)); + } + + $user = null; + DB::transaction(function () use (&$user, $name, $email, $password): void { + $user = app(UserService::class)->createUser( + $name, + $email, + $password, + 'UTC', + Weekday::Monday, + 'EUR', + ); + }); + /** @var Organization|null $organization */ + $organization = $user->ownedTeams->first(); + if ($organization === null) { + throw new LogicException('User does not have an organization'); + } + + $this->info('Created user "'.$name.'" ("'.$email.'")'); + $this->line('ID: '.$user->getKey()); + $this->line('Name: '.$name); + $this->line('Email: '.$email); + if ($outputPassword) { + $this->line('Password: '.$password); + } + $this->line('Timezone: '.$user->timezone); + $this->line('Week start: '.$user->week_start->value); + + // Organization + $this->line('Currency: '.$organization->currency); + + return self::SUCCESS; + } +} diff --git a/app/Console/Commands/Admin/UserVerifyCommand.php b/app/Console/Commands/Admin/UserVerifyCommand.php index aa588a18..b7f8d51f 100644 --- a/app/Console/Commands/Admin/UserVerifyCommand.php +++ b/app/Console/Commands/Admin/UserVerifyCommand.php @@ -35,7 +35,9 @@ public function handle(): int $this->info('Start verifying user with email "'.$email.'"'); /** @var User|null $user */ - $user = User::where('email', $email)->first(); + $user = User::query()->where('email', $email) + ->where('is_placeholder', '=', false) + ->first(); if ($user === null) { $this->error('User with email "'.$email.'" not found.'); diff --git a/app/Filament/Resources/ClientResource/Pages/EditClient.php b/app/Filament/Resources/ClientResource/Pages/EditClient.php index 36a59497..028b3204 100644 --- a/app/Filament/Resources/ClientResource/Pages/EditClient.php +++ b/app/Filament/Resources/ClientResource/Pages/EditClient.php @@ -15,7 +15,8 @@ class EditClient extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->icon('heroicon-m-trash'), ]; } } diff --git a/app/Filament/Resources/ClientResource/Pages/ListClients.php b/app/Filament/Resources/ClientResource/Pages/ListClients.php index c468a5b7..65a2fbd2 100644 --- a/app/Filament/Resources/ClientResource/Pages/ListClients.php +++ b/app/Filament/Resources/ClientResource/Pages/ListClients.php @@ -15,7 +15,8 @@ class ListClients extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/OrganizationInvitationResource.php b/app/Filament/Resources/OrganizationInvitationResource.php new file mode 100644 index 00000000..88ca23a5 --- /dev/null +++ b/app/Filament/Resources/OrganizationInvitationResource.php @@ -0,0 +1,114 @@ +columns(1) + ->schema([ + Forms\Components\TextInput::make('email') + ->label('Email') + ->disabledOn(['edit']) + ->required(), + Select::make('role') + ->options(Role::class), + Forms\Components\Select::make('organization_id') + ->label('Organization') + ->relationship(name: 'organization', titleAttribute: 'name') + ->searchable(['name']) + ->disabledOn(['edit']) + ->required(), + Forms\Components\DateTimePicker::make('created_at') + ->label('Created At') + ->hiddenOn(['create']) + ->disabled(), + Forms\Components\DateTimePicker::make('updated_at') + ->label('Updated At') + ->hiddenOn(['create']) + ->disabled(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('organization.name') + ->searchable() + ->sortable(), + Tables\Columns\TextColumn::make('email') + ->sortable(), + Tables\Columns\TextColumn::make('role'), + Tables\Columns\TextColumn::make('created_at') + ->label('Created At') + ->dateTime() + ->sortable(), + Tables\Columns\TextColumn::make('updated_at') + ->label('Updated At') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->defaultSort('created_at', 'desc') + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\BulkAction::make('resend') + ->label('Resend') + ->action(function (Collection $records): void { + foreach ($records as $organizationInvite) { + app(OrganizationInvitationService::class)->resend($organizationInvite); + } + }), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListOrganizationInvitations::route('/'), + 'edit' => Pages\EditOrganizationInvitation::route('/{record}/edit'), + 'view' => Pages\ViewOrganizationInvitation::route('/{record}'), + ]; + } +} diff --git a/app/Filament/Resources/OrganizationInvitationResource/Pages/EditOrganizationInvitation.php b/app/Filament/Resources/OrganizationInvitationResource/Pages/EditOrganizationInvitation.php new file mode 100644 index 00000000..5011d0db --- /dev/null +++ b/app/Filament/Resources/OrganizationInvitationResource/Pages/EditOrganizationInvitation.php @@ -0,0 +1,19 @@ +icon('heroicon-s-pencil'), + ]; + } +} diff --git a/app/Filament/Resources/OrganizationResource.php b/app/Filament/Resources/OrganizationResource.php index 5561cb53..b0abcc0f 100644 --- a/app/Filament/Resources/OrganizationResource.php +++ b/app/Filament/Resources/OrganizationResource.php @@ -5,8 +5,10 @@ namespace App\Filament\Resources; use App\Filament\Resources\OrganizationResource\Pages; +use App\Filament\Resources\OrganizationResource\RelationManagers\InvitationsRelationManager; use App\Filament\Resources\OrganizationResource\RelationManagers\UsersRelationManager; use App\Models\Organization; +use App\Service\DeletionService; use App\Service\Export\ExportService; use App\Service\Import\Importers\ImporterProvider; use App\Service\Import\Importers\ImportException; @@ -46,10 +48,13 @@ public static function form(Form $form): Form ->maxLength(255), Forms\Components\Toggle::make('personal_team') ->label('Is personal?') + ->hiddenOn(['create']) ->required(), Forms\Components\Select::make('user_id') + ->label('Owner') ->relationship(name: 'owner', titleAttribute: 'email') ->searchable(['name', 'email']) + ->disabledOn(['edit']) ->required(), Forms\Components\Select::make('currency') ->label('Currency') @@ -62,6 +67,7 @@ public static function form(Form $form): Form return $select; }) + ->required() ->searchable(), Forms\Components\TextInput::make('billable_rate') ->label('Billable rate (in Cents)') @@ -75,9 +81,11 @@ public static function form(Form $form): Form ->numeric(), Forms\Components\DateTimePicker::make('created_at') ->label('Created At') + ->hiddenOn(['create']) ->disabled(), Forms\Components\DateTimePicker::make('updated_at') ->label('Updated At') + ->hiddenOn(['create']) ->disabled(), ]); } @@ -97,7 +105,7 @@ public static function table(Table $table): Table ->sortable(), Tables\Columns\TextColumn::make('currency'), TextColumn::make('billable_rate') - ->money(fn (Organization $resource) => $resource->currency ?? 'EUR', divideBy: 100), + ->money(fn (Organization $resource) => $resource->currency, divideBy: 100), Tables\Columns\TextColumn::make('created_at') ->dateTime() ->sortable(), @@ -112,6 +120,10 @@ public static function table(Table $table): Table ]) ->actions([ Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make() + ->using(function (Organization $record): void { + app(DeletionService::class)->deleteOrganization($record); + }), Action::make('Export') ->icon('heroicon-o-arrow-down-tray') ->action(function (Organization $record) { @@ -199,8 +211,6 @@ public static function table(Table $table): Table ]), ]) ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - ]), ]); } @@ -208,6 +218,7 @@ public static function getRelations(): array { return [ UsersRelationManager::class, + InvitationsRelationManager::class, ]; } diff --git a/app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php b/app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php index ed138e96..eb53e58c 100644 --- a/app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php +++ b/app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php @@ -15,7 +15,6 @@ class DeleteOrganization extends DeleteAction protected function setUp(): void { parent::setUp(); - // TODO: check why setting the icon is necessary $this->icon('heroicon-m-trash'); $this->action(function (): void { $result = $this->process(function (Organization $record): bool { diff --git a/app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php b/app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php index 5466056d..6d350394 100644 --- a/app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php +++ b/app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php @@ -4,10 +4,33 @@ namespace App\Filament\Resources\OrganizationResource\Pages; +use App\Enums\Role; use App\Filament\Resources\OrganizationResource; +use App\Models\Organization; use Filament\Resources\Pages\CreateRecord; class CreateOrganization extends CreateRecord { protected static string $resource = OrganizationResource::class; + + protected function mutateFormDataBeforeCreate(array $data): array + { + $data['personal_team'] = false; + + return $data; + } + + protected function afterCreate(): void + { + /** @var Organization $organization */ + $organization = $this->record; + + $user = $organization->owner; + + $organization->users()->attach( + $user, [ + 'role' => Role::Owner->value, + ] + ); + } } diff --git a/app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php b/app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php index 0db975bb..93cb0cdc 100644 --- a/app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php +++ b/app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php @@ -15,7 +15,8 @@ class ListOrganizations extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php b/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php new file mode 100644 index 00000000..be5e7e5d --- /dev/null +++ b/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php @@ -0,0 +1,86 @@ +schema([ + TextInput::make('email') + ->label('Email') + ->disabledOn(['edit']) + ->required(), + Select::make('role') + ->options(Role::class) + ->label('Role') + ->rules([ + 'required', + 'string', + Rule::enum(Role::class) + ->except([Role::Owner, Role::Placeholder]), + ]) + ->required(), + ]); + } + + public function table(Table $table): Table + { + return $table + ->recordTitleAttribute('email') + ->modelLabel('Invitation') + ->pluralModelLabel('Invitations') + ->columns([ + Tables\Columns\TextColumn::make('email'), + Tables\Columns\TextColumn::make('role'), + ]) + ->headerActions([ + Tables\Actions\CreateAction::make() + ->icon('heroicon-s-plus') + ->using(function (array $data, string $model): Model { + /** @var Organization $ownerRecord */ + $ownerRecord = $this->getOwnerRecord(); + + return app(InvitationService::class) + ->inviteUser($ownerRecord, $data['email'], Role::from($data['role'])); + }), + ]) + ->actions([ + Action::make('view') + ->icon('heroicon-o-eye') + ->color('gray') + ->url(fn (OrganizationInvitation $record): string => OrganizationInvitationResource::getUrl('view', [ + 'record' => $record->getKey(), + ])), + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DetachBulkAction::make(), + ]), + ]); + } +} diff --git a/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php b/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php index e8e9dcdf..d09b1057 100644 --- a/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php +++ b/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php @@ -5,17 +5,24 @@ namespace App\Filament\Resources\OrganizationResource\RelationManagers; use App\Enums\Role; +use App\Exceptions\Api\ApiException; use App\Filament\Resources\UserResource; +use App\Models\Member; +use App\Models\Organization; use App\Models\User; +use App\Service\BillableRateService; +use App\Service\MemberService; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; +use Filament\Notifications\Notification; use Filament\Resources\RelationManagers\RelationManager; use Filament\Tables; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\AttachAction; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Illuminate\Validation\Rule; class UsersRelationManager extends RelationManager { @@ -36,20 +43,39 @@ public function form(Form $form): Form public function table(Table $table): Table { + /** @var Organization $organization */ + $organization = $this->getOwnerRecord(); + return $table ->recordTitleAttribute('name') ->columns([ Tables\Columns\TextColumn::make('name'), Tables\Columns\TextColumn::make('role'), TextColumn::make('billable_rate') - ->money($this->getOwnerRecord()->currency ?? 'EUR', divideBy: 100), + ->money($organization->currency, divideBy: 100), ]) ->headerActions([ - Tables\Actions\AttachAction::make()->form(fn (AttachAction $action): array => [ - $action->getRecordSelect(), - Select::make('role') - ->options(Role::class), - ]), + Tables\Actions\AttachAction::make() + ->form(fn (AttachAction $action): array => [ + $action->getRecordSelect(), + Select::make('role') + ->required() + ->options(Role::class) + ->rule([ + 'required', + 'string', + Rule::enum(Role::class) + ->except([Role::Owner, Role::Placeholder]), + ]), + ]) + ->label('Add user') + ->modalHeading('Add user') + ->icon('heroicon-s-plus') + ->using(function (User $record, array $data): void { + /** @var Organization $organization */ + $organization = $this->getOwnerRecord(); + app(MemberService::class)->addMember($record, $organization, Role::from($data['role']), true); + }), ]) ->actions([ Action::make('view') @@ -58,13 +84,55 @@ public function table(Table $table): Table ->url(fn (User $record): string => UserResource::getUrl('view', [ 'record' => $record->getKey(), ])), - Tables\Actions\EditAction::make(), - Tables\Actions\DetachAction::make(), + Tables\Actions\EditAction::make() + ->using(function (User $record, array $data): User { + /** @var Organization $organization */ + $organization = $this->getOwnerRecord(); + /** @var Member $member */ + $member = $record->getRelation('membership'); + + if ($data['billable_rate'] !== $member->billable_rate) { + $member->billable_rate = $data['billable_rate']; + app(BillableRateService::class)->updateTimeEntriesBillableRateForMember($member); + } + + if ($data['role'] !== $member->role) { + try { + app(MemberService::class)->changeRole($member, $organization, Role::from($data['role']), true); + } catch (ApiException $exception) { + Notification::make() + ->danger() + ->title('Update failed') + ->body($exception->getTranslatedMessage()) + ->persistent() + ->send(); + } + } + $member->save(); + + return $record; + }), + Tables\Actions\DetachAction::make() + ->using(function (User $record): void { + /** @var Organization $organization */ + $organization = $this->getOwnerRecord(); + $member = Member::query() + ->whereBelongsTo($record, 'user') + ->whereBelongsTo($organization, 'organization') + ->firstOrFail(); + try { + app(MemberService::class)->removeMember($member, $organization); + } catch (ApiException $exception) { + Notification::make() + ->danger() + ->title('Delete failed') + ->body($exception->getTranslatedMessage()) + ->persistent() + ->send(); + } + }), ]) ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DetachBulkAction::make(), - ]), ]); } } diff --git a/app/Filament/Resources/ProjectMemberResource/Pages/EditProjectMember.php b/app/Filament/Resources/ProjectMemberResource/Pages/EditProjectMember.php index 6563f027..5852ae81 100644 --- a/app/Filament/Resources/ProjectMemberResource/Pages/EditProjectMember.php +++ b/app/Filament/Resources/ProjectMemberResource/Pages/EditProjectMember.php @@ -15,7 +15,8 @@ class EditProjectMember extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->icon('heroicon-m-trash'), ]; } } diff --git a/app/Filament/Resources/ProjectMemberResource/Pages/ListProjectMembers.php b/app/Filament/Resources/ProjectMemberResource/Pages/ListProjectMembers.php index 81c07d2a..a91bb454 100644 --- a/app/Filament/Resources/ProjectMemberResource/Pages/ListProjectMembers.php +++ b/app/Filament/Resources/ProjectMemberResource/Pages/ListProjectMembers.php @@ -15,7 +15,8 @@ class ListProjectMembers extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/ProjectResource/Pages/EditProject.php b/app/Filament/Resources/ProjectResource/Pages/EditProject.php index 1df03ff8..13eae2e6 100644 --- a/app/Filament/Resources/ProjectResource/Pages/EditProject.php +++ b/app/Filament/Resources/ProjectResource/Pages/EditProject.php @@ -15,7 +15,8 @@ class EditProject extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->icon('heroicon-m-trash'), ]; } } diff --git a/app/Filament/Resources/ProjectResource/Pages/ListProjects.php b/app/Filament/Resources/ProjectResource/Pages/ListProjects.php index b2d025ce..b44bbc0a 100644 --- a/app/Filament/Resources/ProjectResource/Pages/ListProjects.php +++ b/app/Filament/Resources/ProjectResource/Pages/ListProjects.php @@ -15,7 +15,8 @@ class ListProjects extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/ReportResource.php b/app/Filament/Resources/ReportResource.php new file mode 100644 index 00000000..064bdcfa --- /dev/null +++ b/app/Filament/Resources/ReportResource.php @@ -0,0 +1,136 @@ +columns(1) + ->schema([ + Forms\Components\TextInput::make('name') + ->label('Name') + ->required() + ->maxLength(255), + Forms\Components\TextInput::make('description') + ->label('Description') + ->nullable() + ->maxLength(255), + Toggle::make('is_public') + ->label('Is public?') + ->required(), + DateTimePicker::make('public_until') + ->label('Public until') + ->nullable(), + Forms\Components\Select::make('organization_id') + ->label('Organization') + ->relationship(name: 'organization', titleAttribute: 'name') + ->searchable(['name']) + ->disabled() + ->required(), + Forms\Components\TextInput::make('share_secret') + ->label('Share Secret') + ->nullable(), + PrettyJson::make('properties') + ->formatStateUsing(function (ReportPropertiesDto $state, Report $record): string { + return $record->getRawOriginal('properties'); + }) + ->disabled(), + Forms\Components\DateTimePicker::make('created_at') + ->label('Created At') + ->hiddenOn(['create']) + ->disabled(), + Forms\Components\DateTimePicker::make('updated_at') + ->label('Updated At') + ->hiddenOn(['create']) + ->disabled(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable() + ->sortable(), + Tables\Columns\TextColumn::make('description') + ->searchable() + ->sortable(), + ToggleColumn::make('is_public') + ->label('Is public?') + ->sortable(), + TextColumn::make('organization.name') + ->searchable() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable(), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->defaultSort('created_at', 'desc') + ->filters([ + SelectFilter::make('organization') + ->relationship('organization', 'name') + ->searchable(), + ]) + ->actions([ + Action::make('public-view') + ->label('Public') + ->icon('heroicon-o-eye') + ->color('gray') + ->hidden(fn (Report $record): bool => $record->getShareableLink() === null) + ->url(fn (Report $record): string => $record->getShareableLink(), true), + Tables\Actions\ViewAction::make(), + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + ]); + } + + public static function getRelations(): array + { + return [ + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListReports::route('/'), + 'edit' => Pages\EditReport::route('/{record}/edit'), + 'view' => Pages\ViewReport::route('/{record}'), + ]; + } +} diff --git a/app/Filament/Resources/ReportResource/Pages/EditReport.php b/app/Filament/Resources/ReportResource/Pages/EditReport.php new file mode 100644 index 00000000..1acc1738 --- /dev/null +++ b/app/Filament/Resources/ReportResource/Pages/EditReport.php @@ -0,0 +1,22 @@ +icon('heroicon-m-trash'), + ]; + } +} diff --git a/app/Filament/Resources/ReportResource/Pages/ListReports.php b/app/Filament/Resources/ReportResource/Pages/ListReports.php new file mode 100644 index 00000000..04c3e600 --- /dev/null +++ b/app/Filament/Resources/ReportResource/Pages/ListReports.php @@ -0,0 +1,19 @@ +icon('heroicon-s-pencil'), + ]; + } +} diff --git a/app/Filament/Resources/TagResource/Pages/EditTag.php b/app/Filament/Resources/TagResource/Pages/EditTag.php index 570c84bc..b61b1269 100644 --- a/app/Filament/Resources/TagResource/Pages/EditTag.php +++ b/app/Filament/Resources/TagResource/Pages/EditTag.php @@ -15,7 +15,8 @@ class EditTag extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->icon('heroicon-m-trash'), ]; } } diff --git a/app/Filament/Resources/TagResource/Pages/ListTags.php b/app/Filament/Resources/TagResource/Pages/ListTags.php index 5fb0949f..c17bc294 100644 --- a/app/Filament/Resources/TagResource/Pages/ListTags.php +++ b/app/Filament/Resources/TagResource/Pages/ListTags.php @@ -15,7 +15,8 @@ class ListTags extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/TaskResource/Pages/EditTask.php b/app/Filament/Resources/TaskResource/Pages/EditTask.php index 25795be4..26331b2c 100644 --- a/app/Filament/Resources/TaskResource/Pages/EditTask.php +++ b/app/Filament/Resources/TaskResource/Pages/EditTask.php @@ -15,7 +15,8 @@ class EditTask extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->icon('heroicon-m-trash'), ]; } } diff --git a/app/Filament/Resources/TaskResource/Pages/ListTasks.php b/app/Filament/Resources/TaskResource/Pages/ListTasks.php index a221527c..4c0519bb 100644 --- a/app/Filament/Resources/TaskResource/Pages/ListTasks.php +++ b/app/Filament/Resources/TaskResource/Pages/ListTasks.php @@ -15,7 +15,8 @@ class ListTasks extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/TimeEntryResource/Pages/EditTimeEntry.php b/app/Filament/Resources/TimeEntryResource/Pages/EditTimeEntry.php index 435d7372..96105ecd 100644 --- a/app/Filament/Resources/TimeEntryResource/Pages/EditTimeEntry.php +++ b/app/Filament/Resources/TimeEntryResource/Pages/EditTimeEntry.php @@ -15,7 +15,8 @@ class EditTimeEntry extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->icon('heroicon-m-trash'), ]; } } diff --git a/app/Filament/Resources/TimeEntryResource/Pages/ListTimeEntries.php b/app/Filament/Resources/TimeEntryResource/Pages/ListTimeEntries.php index 5d8cf8c0..93f1e497 100644 --- a/app/Filament/Resources/TimeEntryResource/Pages/ListTimeEntries.php +++ b/app/Filament/Resources/TimeEntryResource/Pages/ListTimeEntries.php @@ -15,7 +15,8 @@ class ListTimeEntries extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index 149d4933..535a846a 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -5,20 +5,25 @@ namespace App\Filament\Resources; use App\Enums\Weekday; +use App\Exceptions\Api\ApiException; use App\Filament\Resources\UserResource\Pages; use App\Filament\Resources\UserResource\RelationManagers\OrganizationsRelationManager; use App\Filament\Resources\UserResource\RelationManagers\OwnedOrganizationsRelationManager; use App\Models\User; +use App\Service\DeletionService; use App\Service\TimezoneService; +use Brick\Money\ISOCurrencyProvider; use Exception; use Filament\Forms; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; +use Filament\Notifications\Notification; use Filament\Resources\Resource; use Filament\Tables; use Filament\Tables\Filters\TernaryFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use STS\FilamentImpersonate\Tables\Actions\Impersonate; @@ -52,7 +57,9 @@ public static function form(Form $form): Form ->required() ->maxLength(255), Forms\Components\Toggle::make('is_placeholder') - ->label('Is Placeholder'), + ->label('Is Placeholder?') + ->hiddenOn(['create']) + ->disabledOn(['edit']), Forms\Components\DateTimePicker::make('email_verified_at') ->label('Email Verified At') ->nullable(), @@ -71,11 +78,27 @@ public static function form(Form $form): Form ->dehydrated(fn ($state) => filled($state)) ->required(fn (string $context): bool => $context === 'create') ->maxLength(255), + Forms\Components\Select::make('currency') + ->label('Currency (Personal Organization)') + ->options(function (): array { + $currencies = ISOCurrencyProvider::getInstance()->getAvailableCurrencies(); + $select = []; + foreach ($currencies as $currency) { + $select[$currency->getCurrencyCode()] = $currency->getName().' ('.$currency->getCurrencyCode().')'; + } + + return $select; + }) + ->required() + ->visibleOn(['create']) + ->searchable(), Forms\Components\DateTimePicker::make('created_at') ->label('Created At') + ->hiddenOn(['create']) ->disabled(), Forms\Components\DateTimePicker::make('updated_at') ->label('Updated At') + ->hiddenOn(['create']) ->disabled(), ]); } @@ -145,11 +168,22 @@ public static function table(Table $table): Table } }), Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make() + ->hidden(fn (User $record) => $record->is(Auth::user())) + ->using(function (User $record): void { + try { + app(DeletionService::class)->deleteUser($record); + } catch (ApiException $exception) { + Notification::make() + ->danger() + ->title('Delete failed') + ->body($exception->getTranslatedMessage()) + ->persistent() + ->send(); + } + }), ]) ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), ]); } diff --git a/app/Filament/Resources/UserResource/Pages/CreateUser.php b/app/Filament/Resources/UserResource/Pages/CreateUser.php index b5cac367..3ec53fb2 100644 --- a/app/Filament/Resources/UserResource/Pages/CreateUser.php +++ b/app/Filament/Resources/UserResource/Pages/CreateUser.php @@ -4,24 +4,28 @@ namespace App\Filament\Resources\UserResource\Pages; +use App\Enums\Weekday; use App\Filament\Resources\UserResource; -use App\Models\Organization; use App\Models\User; +use App\Service\UserService; use Filament\Resources\Pages\CreateRecord; class CreateUser extends CreateRecord { protected static string $resource = UserResource::class; - protected function afterCreate(): void + protected function handleRecordCreation(array $data): User { - /** @var User $user */ - $user = $this->record; + $userService = app(UserService::class); + $user = $userService->createUser( + $data['name'], + $data['email'], + $data['password'], + $data['timezone'], + Weekday::from($data['week_start']), + $data['currency'], + ); - $user->ownedTeams()->save(Organization::forceCreate([ - 'user_id' => $user->id, - 'name' => explode(' ', $user->name, 2)[0]."'s Organization", - 'personal_team' => true, - ])); + return $user; } } diff --git a/app/Filament/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Resources/UserResource/Pages/ListUsers.php index 3298c135..8d04ff0e 100644 --- a/app/Filament/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Resources/UserResource/Pages/ListUsers.php @@ -15,7 +15,8 @@ class ListUsers extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make() + ->icon('heroicon-s-plus'), ]; } } diff --git a/app/Filament/Resources/UserResource/Pages/ViewUser.php b/app/Filament/Resources/UserResource/Pages/ViewUser.php index e2def8ee..6b49282d 100644 --- a/app/Filament/Resources/UserResource/Pages/ViewUser.php +++ b/app/Filament/Resources/UserResource/Pages/ViewUser.php @@ -7,6 +7,7 @@ use App\Filament\Resources\UserResource; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; +use STS\FilamentImpersonate\Pages\Actions\Impersonate; class ViewUser extends ViewRecord { @@ -15,6 +16,7 @@ class ViewUser extends ViewRecord protected function getHeaderActions(): array { return [ + Impersonate::make()->record($this->getRecord()), EditAction::make('edit') ->icon('heroicon-s-pencil'), ]; diff --git a/app/Filament/Resources/UserResource/RelationManagers/OrganizationsRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/OrganizationsRelationManager.php index fc821a1c..72b31442 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/OrganizationsRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/OrganizationsRelationManager.php @@ -5,15 +5,18 @@ namespace App\Filament\Resources\UserResource\RelationManagers; use App\Enums\Role; +use App\Exceptions\Api\ApiException; use App\Filament\Resources\OrganizationResource; +use App\Models\Member; use App\Models\Organization; +use App\Models\User; +use App\Service\MemberService; use Filament\Forms\Components\Select; -use Filament\Forms\Components\TextInput; use Filament\Forms\Form; +use Filament\Notifications\Notification; use Filament\Resources\RelationManagers\RelationManager; use Filament\Tables; use Filament\Tables\Actions\Action; -use Filament\Tables\Actions\AttachAction; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; @@ -27,10 +30,6 @@ public function form(Form $form): Form ->schema([ Select::make('role') ->options(Role::class), - TextInput::make('billable_rate') - ->label('Billable rate (in Cents)') - ->nullable() - ->numeric(), ]); } @@ -41,15 +40,11 @@ public function table(Table $table): Table ->columns([ TextColumn::make('name'), TextColumn::make('role'), - TextColumn::make('billable_rate') - ->money(fn (Organization $resource) => $resource->currency ?? 'EUR', divideBy: 100), + TextColumn::make('membership.billable_rate') + ->label('Billable rate') + ->money(fn (Organization $resource) => $resource->currency, divideBy: 100), ]) ->headerActions([ - Tables\Actions\AttachAction::make()->form(fn (AttachAction $action): array => [ - $action->getRecordSelect(), - Select::make('role') - ->options(Role::class), - ]), ]) ->actions([ Action::make('view') @@ -58,13 +53,48 @@ public function table(Table $table): Table ->url(fn (Organization $record): string => OrganizationResource::getUrl('view', [ 'record' => $record->getKey(), ])), - Tables\Actions\EditAction::make(), - Tables\Actions\DetachAction::make(), + Tables\Actions\EditAction::make() + ->using(function (Organization $record, array $data): Organization { + /** @var Member $member */ + $member = $record->getRelation('membership'); + + if ($data['role'] !== $member->role) { + try { + app(MemberService::class)->changeRole($member, $record, Role::from($data['role']), true); + } catch (ApiException $exception) { + Notification::make() + ->danger() + ->title('Update failed') + ->body($exception->getTranslatedMessage()) + ->persistent() + ->send(); + } + } + $member->save(); + + return $record; + }), + Tables\Actions\DetachAction::make() + ->using(function (Organization $record): void { + /** @var User $user */ + $user = $this->getOwnerRecord(); + $member = Member::query() + ->whereBelongsTo($user, 'user') + ->whereBelongsTo($record, 'organization') + ->firstOrFail(); + try { + app(MemberService::class)->removeMember($member, $record); + } catch (ApiException $exception) { + Notification::make() + ->danger() + ->title('Delete failed') + ->body($exception->getTranslatedMessage()) + ->persistent() + ->send(); + } + }), ]) ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DetachBulkAction::make(), - ]), ]); } } diff --git a/app/Http/Controllers/Api/V1/InvitationController.php b/app/Http/Controllers/Api/V1/InvitationController.php index e2353ec1..4d8a3a33 100644 --- a/app/Http/Controllers/Api/V1/InvitationController.php +++ b/app/Http/Controllers/Api/V1/InvitationController.php @@ -9,13 +9,12 @@ use App\Http\Requests\V1\Invitation\InvitationStoreRequest; use App\Http\Resources\V1\Invitation\InvitationCollection; use App\Http\Resources\V1\Invitation\InvitationResource; -use App\Mail\OrganizationInvitationMail; use App\Models\Organization; use App\Models\OrganizationInvitation; use App\Service\InvitationService; +use App\Service\OrganizationInvitationService; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Http\JsonResponse; -use Illuminate\Support\Facades\Mail; class InvitationController extends Controller { @@ -73,12 +72,11 @@ public function store(Organization $organization, InvitationStoreRequest $reques * * @operationId resendInvitationEmail */ - public function resend(Organization $organization, OrganizationInvitation $invitation): JsonResponse + public function resend(Organization $organization, OrganizationInvitation $invitation, OrganizationInvitationService $organizationInvitationService): JsonResponse { $this->checkPermission($organization, 'invitations:resend', $invitation); - Mail::to($invitation->email) - ->queue(new OrganizationInvitationMail($invitation)); + $organizationInvitationService->resend($invitation); return response()->json(null, 204); } diff --git a/app/Http/Controllers/Api/V1/MemberController.php b/app/Http/Controllers/Api/V1/MemberController.php index bf900a7a..c1e1220f 100644 --- a/app/Http/Controllers/Api/V1/MemberController.php +++ b/app/Http/Controllers/Api/V1/MemberController.php @@ -6,7 +6,6 @@ use App\Enums\Role; use App\Events\MemberMadeToPlaceholder; -use App\Events\MemberRemoved; use App\Exceptions\Api\CanNotRemoveOwnerFromOrganization; use App\Exceptions\Api\ChangingRoleToPlaceholderIsNotAllowed; use App\Exceptions\Api\EntityStillInUseApiException; @@ -19,8 +18,6 @@ use App\Http\Resources\V1\Member\MemberResource; use App\Models\Member; use App\Models\Organization; -use App\Models\ProjectMember; -use App\Models\TimeEntry; use App\Service\BillableRateService; use App\Service\InvitationService; use App\Service\MemberService; @@ -80,22 +77,8 @@ public function update(Organization $organization, Member $member, MemberUpdateR } if ($request->has('role') && $member->role !== $request->getRole()->value) { $newRole = $request->getRole(); - $oldRole = Role::from($member->role); - if ($oldRole === Role::Owner) { - throw new OrganizationNeedsAtLeastOneOwner; - } - if ($newRole === Role::Placeholder) { - throw new ChangingRoleToPlaceholderIsNotAllowed; - } - if ($newRole === Role::Owner) { - if ($this->hasPermission($organization, 'members:change-ownership')) { - $memberService->changeOwnership($organization, $member); - } else { - throw new OnlyOwnerCanChangeOwnership; - } - } else { - $member->role = $request->getRole()->value; - } + $allowOwnerChange = $this->hasPermission($organization, 'members:change-ownership'); + $memberService->changeRole($member, $organization, $newRole, $allowOwnerChange); } $member->save(); @@ -109,22 +92,11 @@ public function update(Organization $organization, Member $member, MemberUpdateR * * @operationId removeMember */ - public function destroy(Organization $organization, Member $member): JsonResponse + public function destroy(Organization $organization, Member $member, MemberService $memberService): JsonResponse { $this->checkPermission($organization, 'members:delete', $member); - if (TimeEntry::query()->where('user_id', $member->user_id)->whereBelongsTo($organization, 'organization')->exists()) { - throw new EntityStillInUseApiException('member', 'time_entry'); - } - if (ProjectMember::query()->whereBelongsToOrganization($organization)->where('user_id', $member->user_id)->exists()) { - throw new EntityStillInUseApiException('member', 'project_member'); - } - if ($member->role === Role::Owner->value) { - throw new CanNotRemoveOwnerFromOrganization; - } - - $member->delete(); - MemberRemoved::dispatch($member, $organization); + $memberService->removeMember($member, $organization); return response() ->json(null, 204); diff --git a/app/Service/DeletionService.php b/app/Service/DeletionService.php index 7fc6fd08..0e78a58c 100644 --- a/app/Service/DeletionService.php +++ b/app/Service/DeletionService.php @@ -13,6 +13,7 @@ use App\Models\OrganizationInvitation; use App\Models\Project; use App\Models\ProjectMember; +use App\Models\Report; use App\Models\Tag; use App\Models\Task; use App\Models\TimeEntry; @@ -71,6 +72,9 @@ public function deleteOrganization(Organization $organization, bool $inTransacti // Delete all clients Client::query()->whereBelongsTo($organization, 'organization')->delete(); + // Delete all reports + Report::query()->whereBelongsTo($organization, 'organization')->delete(); + // Reset the current organization $organization->owner() ->where('current_team_id', $organization->getKey()) diff --git a/app/Service/MemberService.php b/app/Service/MemberService.php index 01f5f4ec..b5c1f6e0 100644 --- a/app/Service/MemberService.php +++ b/app/Service/MemberService.php @@ -5,10 +5,21 @@ namespace App\Service; use App\Enums\Role; +use App\Events\MemberRemoved; +use App\Exceptions\Api\CanNotRemoveOwnerFromOrganization; +use App\Exceptions\Api\ChangingRoleToPlaceholderIsNotAllowed; +use App\Exceptions\Api\EntityStillInUseApiException; +use App\Exceptions\Api\OnlyOwnerCanChangeOwnership; +use App\Exceptions\Api\OrganizationNeedsAtLeastOneOwner; use App\Models\Member; use App\Models\Organization; +use App\Models\ProjectMember; +use App\Models\TimeEntry; use App\Models\User; +use Illuminate\Support\Facades\DB; use InvalidArgumentException; +use Laravel\Jetstream\Events\AddingTeamMember; +use Laravel\Jetstream\Events\TeamMemberAdded; class MemberService { @@ -19,6 +30,72 @@ public function __construct(UserService $userService) $this->userService = $userService; } + public function addMember(User $user, Organization $organization, Role $role, bool $asSuperAdmin = false): Member + { + if (! $asSuperAdmin) { + AddingTeamMember::dispatch($organization, $user); + } + + $member = new Member; + DB::transaction(function () use ($organization, $user, $role, &$member): void { + $member->user()->associate($user); + $member->organization()->associate($organization); + $member->role = $role->value; + $member->save(); + }); + + if (! $asSuperAdmin) { + TeamMemberAdded::dispatch($organization, $user); + } + + return $member; + } + + /** + * @throws CanNotRemoveOwnerFromOrganization + * @throws EntityStillInUseApiException + */ + public function removeMember(Member $member, Organization $organization): void + { + if (TimeEntry::query()->where('user_id', $member->user_id)->whereBelongsTo($organization, 'organization')->exists()) { + throw new EntityStillInUseApiException('member', 'time_entry'); + } + if (ProjectMember::query()->whereBelongsToOrganization($organization)->where('user_id', $member->user_id)->exists()) { + throw new EntityStillInUseApiException('member', 'project_member'); + } + if ($member->role === Role::Owner->value) { + throw new CanNotRemoveOwnerFromOrganization; + } + + $member->delete(); + MemberRemoved::dispatch($member, $organization); + } + + /** + * @throws ChangingRoleToPlaceholderIsNotAllowed + * @throws OnlyOwnerCanChangeOwnership + * @throws OrganizationNeedsAtLeastOneOwner + */ + public function changeRole(Member $member, Organization $organization, Role $newRole, bool $allowOwnerChange): void + { + $oldRole = Role::from($member->role); + if ($oldRole === Role::Owner) { + throw new OrganizationNeedsAtLeastOneOwner; + } + if ($newRole === Role::Placeholder) { + throw new ChangingRoleToPlaceholderIsNotAllowed; + } + if ($newRole === Role::Owner) { + if ($allowOwnerChange) { + $this->changeOwnership($organization, $member); + } else { + throw new OnlyOwnerCanChangeOwnership; + } + } else { + $member->role = $newRole->value; + } + } + /** * Change the ownership of an organization to a new user. * The previous owner will be demoted to an admin. diff --git a/app/Service/OrganizationInvitationService.php b/app/Service/OrganizationInvitationService.php new file mode 100644 index 00000000..815974ca --- /dev/null +++ b/app/Service/OrganizationInvitationService.php @@ -0,0 +1,18 @@ +email) + ->queue(new OrganizationInvitationMail($invitation)); + } +} diff --git a/app/Service/UserService.php b/app/Service/UserService.php index ff0f8821..c130eded 100644 --- a/app/Service/UserService.php +++ b/app/Service/UserService.php @@ -5,15 +5,45 @@ namespace App\Service; use App\Enums\Role; +use App\Enums\Weekday; use App\Events\AfterCreateOrganization; use App\Models\Member; use App\Models\Organization; use App\Models\ProjectMember; use App\Models\TimeEntry; use App\Models\User; +use Illuminate\Support\Facades\Hash; class UserService { + public function createUser(string $name, string $email, string $password, string $timezone, Weekday $weekStart, string $currency): User + { + $user = new User; + $user->name = $name; + $user->email = $email; + $user->password = Hash::make($password); + $user->timezone = $timezone; + $user->week_start = $weekStart; + $user->save(); + + $organization = new Organization; + $organization->name = explode(' ', $user->name, 2)[0]."'s Organization"; + $organization->personal_team = true; + $organization->currency = $currency; + $organization->owner()->associate($user); + $organization->save(); + + $organization->users()->attach( + $user, [ + 'role' => Role::Owner->value, + ] + ); + + $user->ownedTeams()->save($organization); + + return $user; + } + /** * Assign all organization entities (time entries, project members) from one user to another. * This is useful when a placeholder user is replaced with a real user. diff --git a/composer.json b/composer.json index 60997170..882fd358 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "barryvdh/laravel-ide-helper": "^3.0", "brianium/paratest": "^7.3", "fakerphp/faker": "^1.9.1", - "fumeapp/modeltyper": "^2.2", + "fumeapp/modeltyper": "^3.0", "phpstan/phpstan": "1.12.0", "larastan/larastan": "^2.0", "laravel/pint": "^1.0", diff --git a/composer.lock b/composer.lock index 44fb9fc9..9ca8f46e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3e4b0fb7db1fbd785f3079f3788b86eb", + "content-hash": "4af1e2264911945c72974bbcadeb6308", "packages": [ { "name": "anourvalar/eloquent-serialize", - "version": "1.2.26", + "version": "1.2.27", "source": { "type": "git", "url": "https://github.com/AnourValar/eloquent-serialize.git", - "reference": "756c1232ff0d02321fd90f4fe3c221d6a7b8d697" + "reference": "f1c4fcd41a6db1467ed75bc295b62f582d6fd0fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/756c1232ff0d02321fd90f4fe3c221d6a7b8d697", - "reference": "756c1232ff0d02321fd90f4fe3c221d6a7b8d697", + "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/f1c4fcd41a6db1467ed75bc295b62f582d6fd0fe", + "reference": "f1c4fcd41a6db1467ed75bc295b62f582d6fd0fe", "shasum": "" }, "require": { @@ -68,9 +68,9 @@ ], "support": { "issues": "https://github.com/AnourValar/eloquent-serialize/issues", - "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.2.26" + "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.2.27" }, - "time": "2024-11-16T12:29:47+00:00" + "time": "2024-11-30T08:27:24+00:00" }, { "name": "aws/aws-crt-php", @@ -128,16 +128,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.328.0", + "version": "3.336.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "a99b58e166ae367f2b067937afb04e843e900745" + "reference": "954bfdfc048840ca34afe2a2e1cbcff6681989c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a99b58e166ae367f2b067937afb04e843e900745", - "reference": "a99b58e166ae367f2b067937afb04e843e900745", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/954bfdfc048840ca34afe2a2e1cbcff6681989c4", + "reference": "954bfdfc048840ca34afe2a2e1cbcff6681989c4", "shasum": "" }, "require": { @@ -166,8 +166,8 @@ "nette/neon": "^2.3", "paragonie/random_compat": ">= 2", "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", - "psr/cache": "^1.0", - "psr/simple-cache": "^1.0", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "sebastian/comparator": "^1.2.3 || ^4.0", "yoast/phpunit-polyfills": "^1.0" }, @@ -220,9 +220,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.328.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.336.2" }, - "time": "2024-11-15T19:06:57+00:00" + "time": "2024-12-20T19:05:10+00:00" }, { "name": "bacon/bacon-qr-code", @@ -280,16 +280,16 @@ }, { "name": "blade-ui-kit/blade-heroicons", - "version": "2.4.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/blade-ui-kit/blade-heroicons.git", - "reference": "a7c377a4ef88cd54712e3e15cbed30446820da0b" + "reference": "4ed3ed08e9ac192d0d126b2f12711d6fb6576a48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/a7c377a4ef88cd54712e3e15cbed30446820da0b", - "reference": "a7c377a4ef88cd54712e3e15cbed30446820da0b", + "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/4ed3ed08e9ac192d0d126b2f12711d6fb6576a48", + "reference": "4ed3ed08e9ac192d0d126b2f12711d6fb6576a48", "shasum": "" }, "require": { @@ -333,7 +333,7 @@ ], "support": { "issues": "https://github.com/blade-ui-kit/blade-heroicons/issues", - "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/2.4.0" + "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/2.5.0" }, "funding": [ { @@ -345,7 +345,7 @@ "type": "paypal" } ], - "time": "2024-07-16T07:00:01+00:00" + "time": "2024-11-18T19:59:07+00:00" }, { "name": "blade-ui-kit/blade-icons", @@ -616,16 +616,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.3", + "version": "1.5.4", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "3b1fc3f0be055baa7c6258b1467849c3e8204eb2" + "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/3b1fc3f0be055baa7c6258b1467849c3e8204eb2", - "reference": "3b1fc3f0be055baa7c6258b1467849c3e8204eb2", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/bc0593537a463e55cadf45fd938d23b75095b7e1", + "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1", "shasum": "" }, "require": { @@ -672,7 +672,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.3" + "source": "https://github.com/composer/ca-bundle/tree/1.5.4" }, "funding": [ { @@ -688,20 +688,20 @@ "type": "tidelift" } ], - "time": "2024-11-04T10:15:26+00:00" + "time": "2024-11-27T15:35:25+00:00" }, { "name": "composer/class-map-generator", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "98bbf6780e56e0fd2404fe4b82eb665a0f93b783" + "reference": "4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/98bbf6780e56e0fd2404fe4b82eb665a0f93b783", - "reference": "98bbf6780e56e0fd2404fe4b82eb665a0f93b783", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915", + "reference": "4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915", "shasum": "" }, "require": { @@ -710,10 +710,10 @@ "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" }, "require-dev": { - "phpstan/phpstan": "^1.6", - "phpstan/phpstan-deprecation-rules": "^1", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", "phpunit/phpunit": "^8", "symfony/filesystem": "^5.4 || ^6" }, @@ -745,7 +745,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.4.0" + "source": "https://github.com/composer/class-map-generator/tree/1.5.0" }, "funding": [ { @@ -761,20 +761,20 @@ "type": "tidelift" } ], - "time": "2024-10-03T18:14:00+00:00" + "time": "2024-11-25T16:11:06+00:00" }, { "name": "composer/composer", - "version": "2.8.2", + "version": "2.8.4", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "6e543d03187c882ea1c6ba43add2467754427803" + "reference": "112e37d1dca22b3fdb81cf3524ab4994f47fdb8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/6e543d03187c882ea1c6ba43add2467754427803", - "reference": "6e543d03187c882ea1c6ba43add2467754427803", + "url": "https://api.github.com/repos/composer/composer/zipball/112e37d1dca22b3fdb81cf3524ab4994f47fdb8c", + "reference": "112e37d1dca22b3fdb81cf3524ab4994f47fdb8c", "shasum": "" }, "require": { @@ -788,7 +788,7 @@ "justinrainbow/json-schema": "^5.3", "php": "^7.2.5 || ^8.0", "psr/log": "^1.0 || ^2.0 || ^3.0", - "react/promise": "^3.2", + "react/promise": "^2.11 || ^3.2", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.2", "seld/signal-handler": "^2.0", @@ -818,13 +818,13 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.8-dev" - }, "phpstan": { "includes": [ "phpstan/rules.neon" ] + }, + "branch-alias": { + "dev-main": "2.8-dev" } }, "autoload": { @@ -859,7 +859,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.8.2" + "source": "https://github.com/composer/composer/tree/2.8.4" }, "funding": [ { @@ -875,7 +875,7 @@ "type": "tidelift" } ], - "time": "2024-10-29T15:12:11+00:00" + "time": "2024-12-11T10:57:47+00:00" }, { "name": "composer/metadata-minifier", @@ -973,13 +973,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - }, "phpstan": { "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-main": "3.x-dev" } }, "autoload": { @@ -1457,16 +1457,16 @@ }, { "name": "datomatic/laravel-enum-helper", - "version": "v2.0.0", + "version": "v2.0.2", "source": { "type": "git", "url": "https://github.com/datomatic/laravel-enum-helper.git", - "reference": "51bc8e932d98b9d902dc8f63afbf0337066798fb" + "reference": "44709b6dca5f4e44d18b5ccf4edf0b4fbb92be9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/datomatic/laravel-enum-helper/zipball/51bc8e932d98b9d902dc8f63afbf0337066798fb", - "reference": "51bc8e932d98b9d902dc8f63afbf0337066798fb", + "url": "https://api.github.com/repos/datomatic/laravel-enum-helper/zipball/44709b6dca5f4e44d18b5ccf4edf0b4fbb92be9e", + "reference": "44709b6dca5f4e44d18b5ccf4edf0b4fbb92be9e", "shasum": "" }, "require": { @@ -1481,10 +1481,10 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.8", "laravel/pint": "^1.18", - "nunomaduro/larastan": "^2.9", + "nunomaduro/larastan": "^2.0", "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0", - "pestphp/pest": "^2.0|^3.0", - "pestphp/pest-plugin-laravel": "^2.0|^3.0", + "pestphp/pest": "^1.0|^2.0|^3.0", + "pestphp/pest-plugin-laravel": "^1.0|^2.0|^3.0", "phpstan/phpstan": "^1.7" }, "type": "library", @@ -1513,22 +1513,22 @@ "description": "Simple opinionated framework agnostic PHP 8.1 enum helper for Laravel", "support": { "issues": "https://github.com/datomatic/laravel-enum-helper/issues", - "source": "https://github.com/datomatic/laravel-enum-helper/tree/v2.0.0" + "source": "https://github.com/datomatic/laravel-enum-helper/tree/v2.0.2" }, - "time": "2024-11-03T09:34:41+00:00" + "time": "2024-12-09T13:32:03+00:00" }, { "name": "dedoc/scramble", - "version": "v0.11.28", + "version": "v0.11.31", "source": { "type": "git", "url": "https://github.com/dedoc/scramble.git", - "reference": "714036967f6ee5fd139af0a3af0b2f0f374cb720" + "reference": "bd7aeda823765565adc79bbb1a2b7d066b77c318" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dedoc/scramble/zipball/714036967f6ee5fd139af0a3af0b2f0f374cb720", - "reference": "714036967f6ee5fd139af0a3af0b2f0f374cb720", + "url": "https://api.github.com/repos/dedoc/scramble/zipball/bd7aeda823765565adc79bbb1a2b7d066b77c318", + "reference": "bd7aeda823765565adc79bbb1a2b7d066b77c318", "shasum": "" }, "require": { @@ -1582,7 +1582,7 @@ ], "support": { "issues": "https://github.com/dedoc/scramble/issues", - "source": "https://github.com/dedoc/scramble/tree/v0.11.28" + "source": "https://github.com/dedoc/scramble/tree/v0.11.31" }, "funding": [ { @@ -1590,7 +1590,7 @@ "type": "github" } ], - "time": "2024-11-25T12:25:37+00:00" + "time": "2024-12-20T10:12:41+00:00" }, { "name": "defuse/php-encryption", @@ -1844,29 +1844,27 @@ }, { "name": "doctrine/deprecations", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", + "doctrine/coding-standard": "^9 || ^12", + "phpstan/phpstan": "1.4.10 || 2.0.3", + "phpstan/phpstan-phpunit": "^1.0 || ^2", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" + "psr/log": "^1 || ^2 || ^3" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -1874,7 +1872,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1885,9 +1883,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "source": "https://github.com/doctrine/deprecations/tree/1.1.4" }, - "time": "2024-01-30T19:34:25+00:00" + "time": "2024-12-07T21:18:45+00:00" }, { "name": "doctrine/inflector", @@ -2252,16 +2250,16 @@ }, { "name": "filament/actions", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "631b38a36f5209a3884182acee60a0db682c6d24" + "reference": "8d9ceaf392eeff55fd335f5169d14f84af8c325e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/631b38a36f5209a3884182acee60a0db682c6d24", - "reference": "631b38a36f5209a3884182acee60a0db682c6d24", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/8d9ceaf392eeff55fd335f5169d14f84af8c325e", + "reference": "8d9ceaf392eeff55fd335f5169d14f84af8c325e", "shasum": "" }, "require": { @@ -2301,20 +2299,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:31+00:00" + "time": "2024-12-17T13:03:16+00:00" }, { "name": "filament/filament", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "3f170b1c57033ad8e9e6bd71f3dc3f0665bf3ae9" + "reference": "21febddcc6720b250b41386805a8dbd1deef2c56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/3f170b1c57033ad8e9e6bd71f3dc3f0665bf3ae9", - "reference": "3f170b1c57033ad8e9e6bd71f3dc3f0665bf3ae9", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/21febddcc6720b250b41386805a8dbd1deef2c56", + "reference": "21febddcc6720b250b41386805a8dbd1deef2c56", "shasum": "" }, "require": { @@ -2366,20 +2364,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:35+00:00" + "time": "2024-12-17T13:03:11+00:00" }, { "name": "filament/forms", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "c73351c086036bd8de24e8671fd97018942d6d61" + "reference": "72429b0df9c3d123273dd51ba62b764e2114697c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/c73351c086036bd8de24e8671fd97018942d6d61", - "reference": "c73351c086036bd8de24e8671fd97018942d6d61", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/72429b0df9c3d123273dd51ba62b764e2114697c", + "reference": "72429b0df9c3d123273dd51ba62b764e2114697c", "shasum": "" }, "require": { @@ -2422,20 +2420,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:31+00:00" + "time": "2024-12-17T13:03:11+00:00" }, { "name": "filament/infolists", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "7946035f47746e69ff9d98bfed04b0248000ee2e" + "reference": "15c200a3172b88a6247ff4b7230f69982d848194" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/7946035f47746e69ff9d98bfed04b0248000ee2e", - "reference": "7946035f47746e69ff9d98bfed04b0248000ee2e", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/15c200a3172b88a6247ff4b7230f69982d848194", + "reference": "15c200a3172b88a6247ff4b7230f69982d848194", "shasum": "" }, "require": { @@ -2473,11 +2471,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:31+00:00" + "time": "2024-12-17T13:03:14+00:00" }, { "name": "filament/notifications", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -2529,27 +2527,27 @@ }, { "name": "filament/support", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "13b1e485d3bc993950c9e61a3f6a8cb05efd2b96" + "reference": "ddc16d8da50d73f7300671b70c9dcb942d845d9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/13b1e485d3bc993950c9e61a3f6a8cb05efd2b96", - "reference": "13b1e485d3bc993950c9e61a3f6a8cb05efd2b96", + "url": "https://api.github.com/repos/filamentphp/support/zipball/ddc16d8da50d73f7300671b70c9dcb942d845d9d", + "reference": "ddc16d8da50d73f7300671b70c9dcb942d845d9d", "shasum": "" }, "require": { - "blade-ui-kit/blade-heroicons": "^2.2.1", + "blade-ui-kit/blade-heroicons": "^2.5", "doctrine/dbal": "^3.2|^4.0", "ext-intl": "*", "illuminate/contracts": "^10.45|^11.0", "illuminate/support": "^10.45|^11.0", "illuminate/view": "^10.45|^11.0", "kirschbaum-development/eloquent-power-joins": "^3.0|^4.0", - "livewire/livewire": "^3.4.10", + "livewire/livewire": "3.5.12", "php": "^8.1", "ryangjchandler/blade-capture-directive": "^0.2|^0.3|^1.0", "spatie/color": "^1.5", @@ -2584,20 +2582,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:51+00:00" + "time": "2024-12-17T13:03:15+00:00" }, { "name": "filament/tables", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "5f1b04952080e71f3f72bae3801f2757619722e7" + "reference": "224aea12a4a4cfcd158b53df94cdd190f8226cac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/5f1b04952080e71f3f72bae3801f2757619722e7", - "reference": "5f1b04952080e71f3f72bae3801f2757619722e7", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/224aea12a4a4cfcd158b53df94cdd190f8226cac", + "reference": "224aea12a4a4cfcd158b53df94cdd190f8226cac", "shasum": "" }, "require": { @@ -2636,20 +2634,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:47+00:00" + "time": "2024-12-17T13:03:09+00:00" }, { "name": "filament/widgets", - "version": "v3.2.124", + "version": "v3.2.131", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "59a907af93c9027180e2bac5879f35b5fb11c96f" + "reference": "869a419fe42e2cf1b9461f2d1e702e2fcad030ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/59a907af93c9027180e2bac5879f35b5fb11c96f", - "reference": "59a907af93c9027180e2bac5879f35b5fb11c96f", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/869a419fe42e2cf1b9461f2d1e702e2fcad030ae", + "reference": "869a419fe42e2cf1b9461f2d1e702e2fcad030ae", "shasum": "" }, "require": { @@ -2680,20 +2678,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-11-13T16:35:48+00:00" + "time": "2024-12-17T13:03:07+00:00" }, { "name": "firebase/php-jwt", - "version": "v6.10.1", + "version": "v6.10.2", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "500501c2ce893c824c801da135d02661199f60c5" + "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", - "reference": "500501c2ce893c824c801da135d02661199f60c5", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/30c19ed0f3264cb660ea496895cfb6ef7ee3653b", + "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b", "shasum": "" }, "require": { @@ -2741,9 +2739,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" + "source": "https://github.com/firebase/php-jwt/tree/v6.10.2" }, - "time": "2024-05-18T18:05:11+00:00" + "time": "2024-11-24T11:22:49+00:00" }, { "name": "flowframe/laravel-trend", @@ -2892,23 +2890,23 @@ }, { "name": "gotenberg/gotenberg-php", - "version": "v2.9.0", + "version": "v2.10.1", "source": { "type": "git", "url": "https://github.com/gotenberg/gotenberg-php.git", - "reference": "d99f5b531c5302126a8065c0cf3cddf6698f40ff" + "reference": "00efc25de591691e70264623ce2b7d979a22a933" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/gotenberg/gotenberg-php/zipball/d99f5b531c5302126a8065c0cf3cddf6698f40ff", - "reference": "d99f5b531c5302126a8065c0cf3cddf6698f40ff", + "url": "https://api.github.com/repos/gotenberg/gotenberg-php/zipball/00efc25de591691e70264623ce2b7d979a22a933", + "reference": "00efc25de591691e70264623ce2b7d979a22a933", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", "guzzlehttp/psr7": "^1 || ^2.1", - "php": "^8.1|^8.2|^8.3", + "php": "^8.1|^8.2|^8.3|^8.4", "php-http/discovery": "^1.14", "psr/http-client": "^1.0", "psr/http-message": "^1.0|^2.0" @@ -2961,7 +2959,7 @@ ], "support": { "issues": "https://github.com/gotenberg/gotenberg-php/issues", - "source": "https://github.com/gotenberg/gotenberg-php/tree/v2.9.0" + "source": "https://github.com/gotenberg/gotenberg-php/tree/v2.10.1" }, "funding": [ { @@ -2969,7 +2967,7 @@ "type": "github" } ], - "time": "2024-11-05T13:22:45+00:00" + "time": "2024-11-29T15:40:54+00:00" }, { "name": "graham-campbell/result-type", @@ -3446,27 +3444,27 @@ }, { "name": "inertiajs/inertia-laravel", - "version": "v1.3.0", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/inertiajs/inertia-laravel.git", - "reference": "36730d13b1dab9017069004fd458b3e67449a326" + "reference": "7e6a030ffab315099782a4844a2175455f511c68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/36730d13b1dab9017069004fd458b3e67449a326", - "reference": "36730d13b1dab9017069004fd458b3e67449a326", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/7e6a030ffab315099782a4844a2175455f511c68", + "reference": "7e6a030ffab315099782a4844a2175455f511c68", "shasum": "" }, "require": { "ext-json": "*", "laravel/framework": "^8.74|^9.0|^10.0|^11.0", - "php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0", + "php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0|~8.4.0", "symfony/console": "^5.3|^6.0|^7.0" }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^6.4|^7.0|^8.0|^9.0", + "orchestra/testbench": "^6.45|^7.44|^8.25|^9.3", "phpunit/phpunit": "^8.0|^9.5.8|^10.4", "roave/security-advisories": "dev-master" }, @@ -3510,7 +3508,7 @@ ], "support": { "issues": "https://github.com/inertiajs/inertia-laravel/issues", - "source": "https://github.com/inertiajs/inertia-laravel/tree/v1.3.0" + "source": "https://github.com/inertiajs/inertia-laravel/tree/v1.3.2" }, "funding": [ { @@ -3518,7 +3516,7 @@ "type": "github" } ], - "time": "2024-06-13T01:25:09+00:00" + "time": "2024-12-05T14:52:50+00:00" }, { "name": "jawira/case-converter", @@ -3654,16 +3652,16 @@ }, { "name": "kirschbaum-development/eloquent-power-joins", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", - "reference": "c6c42a52c5a097cc11761e72782b2d0215692caf" + "reference": "3c1af9b86b02f1e39219849c1d2fee7cf77e8638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/c6c42a52c5a097cc11761e72782b2d0215692caf", - "reference": "c6c42a52c5a097cc11761e72782b2d0215692caf", + "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/3c1af9b86b02f1e39219849c1d2fee7cf77e8638", + "reference": "3c1af9b86b02f1e39219849c1d2fee7cf77e8638", "shasum": "" }, "require": { @@ -3711,9 +3709,9 @@ ], "support": { "issues": "https://github.com/kirschbaum-development/eloquent-power-joins/issues", - "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.0.0" + "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.0.1" }, - "time": "2024-10-06T12:28:14+00:00" + "time": "2024-11-26T13:22:08+00:00" }, { "name": "korridor/laravel-computed-attributes", @@ -3917,16 +3915,16 @@ }, { "name": "laminas/laminas-code", - "version": "4.15.1", + "version": "4.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-code.git", - "reference": "877ad42fe9c164785182fca8afa3f416a056884d" + "reference": "1793e78dad4108b594084d05d1fb818b85b110af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/877ad42fe9c164785182fca8afa3f416a056884d", - "reference": "877ad42fe9c164785182fca8afa3f416a056884d", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1793e78dad4108b594084d05d1fb818b85b110af", + "reference": "1793e78dad4108b594084d05d1fb818b85b110af", "shasum": "" }, "require": { @@ -3976,7 +3974,7 @@ "type": "community_bridge" } ], - "time": "2024-10-25T10:15:16+00:00" + "time": "2024-11-20T13:15:13+00:00" }, { "name": "laminas/laminas-diactoros", @@ -4019,8 +4017,8 @@ "type": "library", "extra": { "laminas": { - "config-provider": "Laminas\\Diactoros\\ConfigProvider", - "module": "Laminas\\Diactoros" + "module": "Laminas\\Diactoros", + "config-provider": "Laminas\\Diactoros\\ConfigProvider" } }, "autoload": { @@ -4068,16 +4066,16 @@ }, { "name": "laravel/fortify", - "version": "v1.24.5", + "version": "v1.25.1", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "bba8c2ecc3fcc78e8632e0d719ae10bef6343eef" + "reference": "5022e7c01385fd6edcef91c12b19071f8f20d6d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/bba8c2ecc3fcc78e8632e0d719ae10bef6343eef", - "reference": "bba8c2ecc3fcc78e8632e0d719ae10bef6343eef", + "url": "https://api.github.com/repos/laravel/fortify/zipball/5022e7c01385fd6edcef91c12b19071f8f20d6d8", + "reference": "5022e7c01385fd6edcef91c12b19071f8f20d6d8", "shasum": "" }, "require": { @@ -4096,13 +4094,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, "laravel": { "providers": [ "Laravel\\Fortify\\FortifyServiceProvider" ] + }, + "branch-alias": { + "dev-master": "1.x-dev" } }, "autoload": { @@ -4129,27 +4127,27 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2024-11-12T14:51:12+00:00" + "time": "2024-11-27T14:51:15+00:00" }, { "name": "laravel/framework", - "version": "v11.32.0", + "version": "v11.36.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927" + "reference": "df06f5163f4550641fdf349ebc04916a61135a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/bc2aad63f83ee5089be7b21cf29d645ccf31e927", - "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927", + "url": "https://api.github.com/repos/laravel/framework/zipball/df06f5163f4550641fdf349ebc04916a61135a64", + "reference": "df06f5163f4550641fdf349ebc04916a61135a64", "shasum": "" }, "require": { "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", - "dragonmantank/cron-expression": "^3.3.2", + "dragonmantank/cron-expression": "^3.4", "egulias/email-validator": "^3.2.1|^4.0", "ext-ctype": "*", "ext-filter": "*", @@ -4159,35 +4157,37 @@ "ext-session": "*", "ext-tokenizer": "*", "fruitcake/php-cors": "^1.3", - "guzzlehttp/guzzle": "^7.8", + "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", - "laravel/serializable-closure": "^1.3", - "league/commonmark": "^2.2.1", - "league/flysystem": "^3.8.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.6", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.2|^3.0", + "nesbot/carbon": "^2.72.2|^3.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^7.0", - "symfony/error-handler": "^7.0", - "symfony/finder": "^7.0", - "symfony/http-foundation": "^7.0", - "symfony/http-kernel": "^7.0", - "symfony/mailer": "^7.0", - "symfony/mime": "^7.0", - "symfony/polyfill-php83": "^1.28", - "symfony/process": "^7.0", - "symfony/routing": "^7.0", - "symfony/uid": "^7.0", - "symfony/var-dumper": "^7.0", + "symfony/console": "^7.0.3", + "symfony/error-handler": "^7.0.3", + "symfony/finder": "^7.0.3", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.0.3", + "symfony/mailer": "^7.0.3", + "symfony/mime": "^7.0.3", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.0.3", + "symfony/routing": "^7.0.3", + "symfony/uid": "^7.0.3", + "symfony/var-dumper": "^7.0.3", "tijsverkoyen/css-to-inline-styles": "^2.2.5", - "vlucas/phpdotenv": "^5.4.1", - "voku/portable-ascii": "^2.0" + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" }, "conflict": { "mockery/mockery": "1.6.8", @@ -4237,29 +4237,32 @@ }, "require-dev": { "ably/ably-php": "^1.0", - "aws/aws-sdk-php": "^3.235.5", + "aws/aws-sdk-php": "^3.322.9", "ext-gmp": "*", - "fakerphp/faker": "^1.23", - "league/flysystem-aws-s3-v3": "^3.0", - "league/flysystem-ftp": "^3.0", - "league/flysystem-path-prefixing": "^3.3", - "league/flysystem-read-only": "^3.3", - "league/flysystem-sftp-v3": "^3.0", - "mockery/mockery": "^1.6", - "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^9.5", - "pda/pheanstalk": "^5.0", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^9.6", + "pda/pheanstalk": "^5.0.6", + "php-http/discovery": "^1.15", "phpstan/phpstan": "^1.11.5", - "phpunit/phpunit": "^10.5|^11.0", - "predis/predis": "^2.0.2", + "phpunit/phpunit": "^10.5.35|^11.3.6", + "predis/predis": "^2.3", "resend/resend-php": "^0.10.0", - "symfony/cache": "^7.0", - "symfony/http-client": "^7.0", - "symfony/psr-http-message-bridge": "^7.0" + "symfony/cache": "^7.0.3", + "symfony/http-client": "^7.0.3", + "symfony/psr-http-message-bridge": "^7.0.3", + "symfony/translation": "^7.0.3" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", "ext-apcu": "Required to use the APC cache driver.", "ext-fileinfo": "Required to use the Filesystem class.", @@ -4273,16 +4276,16 @@ "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "laravel/tinker": "Required to use the tinker console command (^2.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", - "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", - "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", - "league/flysystem-read-only": "Required to use read-only disks (^3.3)", - "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", "mockery/mockery": "Required to use mocking (^1.6).", - "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", "phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).", - "predis/predis": "Required to use the predis connector (^2.0.2).", + "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", @@ -4301,6 +4304,7 @@ }, "autoload": { "files": [ + "src/Illuminate/Collections/functions.php", "src/Illuminate/Collections/helpers.php", "src/Illuminate/Events/functions.php", "src/Illuminate/Filesystem/functions.php", @@ -4338,20 +4342,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-11-15T17:04:33+00:00" + "time": "2024-12-17T22:32:08+00:00" }, { "name": "laravel/jetstream", - "version": "v5.3.2", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/laravel/jetstream.git", - "reference": "e5b9ef610bf13fb3b6053893f711227213833f35" + "reference": "d8d4d83a64d1035b05030e2e97230524b1fa8177" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/jetstream/zipball/e5b9ef610bf13fb3b6053893f711227213833f35", - "reference": "e5b9ef610bf13fb3b6053893f711227213833f35", + "url": "https://api.github.com/repos/laravel/jetstream/zipball/d8d4d83a64d1035b05030e2e97230524b1fa8177", + "reference": "d8d4d83a64d1035b05030e2e97230524b1fa8177", "shasum": "" }, "require": { @@ -4359,7 +4363,7 @@ "illuminate/console": "^11.0", "illuminate/support": "^11.0", "laravel/fortify": "^1.20", - "mobiledetect/mobiledetectlib": "^4.8", + "mobiledetect/mobiledetectlib": "^4.8.08", "php": "^8.2.0", "symfony/console": "^7.0" }, @@ -4405,27 +4409,27 @@ "issues": "https://github.com/laravel/jetstream/issues", "source": "https://github.com/laravel/jetstream" }, - "time": "2024-11-11T20:18:18+00:00" + "time": "2024-12-10T15:11:20+00:00" }, { "name": "laravel/octane", - "version": "v2.5.9", + "version": "v2.6.0", "source": { "type": "git", "url": "https://github.com/laravel/octane.git", - "reference": "d8d432eb1e51a8ab2575854963d94e70d4592e15" + "reference": "b8b11ef25600baa835d364e724f2e948dc1eb88b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/octane/zipball/d8d432eb1e51a8ab2575854963d94e70d4592e15", - "reference": "d8d432eb1e51a8ab2575854963d94e70d4592e15", + "url": "https://api.github.com/repos/laravel/octane/zipball/b8b11ef25600baa835d364e724f2e948dc1eb88b", + "reference": "b8b11ef25600baa835d364e724f2e948dc1eb88b", "shasum": "" }, "require": { "laminas/laminas-diactoros": "^3.0", "laravel/framework": "^10.10.1|^11.0", "laravel/prompts": "^0.1.24|^0.2.0|^0.3.0", - "laravel/serializable-closure": "^1.3.0", + "laravel/serializable-closure": "^1.3|^2.0", "nesbot/carbon": "^2.66.0|^3.0", "php": "^8.1.0", "symfony/console": "^6.0|^7.0", @@ -4444,7 +4448,7 @@ "livewire/livewire": "^2.12.3|^3.0", "mockery/mockery": "^1.5.1", "nunomaduro/collision": "^6.4.0|^7.5.2|^8.0", - "orchestra/testbench": "^8.5.2|^9.0", + "orchestra/testbench": "^8.21|^9.0", "phpstan/phpstan": "^1.10.15", "phpunit/phpunit": "^10.4", "spiral/roadrunner-cli": "^2.6.0", @@ -4495,7 +4499,7 @@ "issues": "https://github.com/laravel/octane/issues", "source": "https://github.com/laravel/octane" }, - "time": "2024-10-06T21:09:20+00:00" + "time": "2024-11-25T21:47:18+00:00" }, { "name": "laravel/passport", @@ -4634,32 +4638,32 @@ }, { "name": "laravel/serializable-closure", - "version": "v1.3.6", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "f865a58ea3a0107c336b7045104c75243fa59d96" + "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f865a58ea3a0107c336b7045104c75243fa59d96", - "reference": "f865a58ea3a0107c336b7045104c75243fa59d96", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/613b2d4998f85564d40497e05e89cb6d9bd1cbe8", + "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^8.1" }, "require-dev": { - "illuminate/support": "^8.0|^9.0|^10.0|^11.0", - "nesbot/carbon": "^2.61|^3.0", - "pestphp/pest": "^1.21.3", - "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" + "illuminate/support": "^10.0|^11.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -4691,7 +4695,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-11-11T17:06:04+00:00" + "time": "2024-12-16T15:26:28+00:00" }, { "name": "laravel/tinker", @@ -4898,16 +4902,16 @@ }, { "name": "league/commonmark", - "version": "2.5.3", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0" + "reference": "d150f911e0079e90ae3c106734c93137c184f932" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d150f911e0079e90ae3c106734c93137c184f932", + "reference": "d150f911e0079e90ae3c106734c93137c184f932", "shasum": "" }, "require": { @@ -4932,8 +4936,9 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 || ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0" }, @@ -4943,7 +4948,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.6-dev" + "dev-main": "2.7-dev" } }, "autoload": { @@ -5000,7 +5005,7 @@ "type": "tidelift" } ], - "time": "2024-08-16T11:46:16+00:00" + "time": "2024-12-07T15:34:16+00:00" }, { "name": "league/config", @@ -5086,16 +5091,16 @@ }, { "name": "league/csv", - "version": "9.18.0", + "version": "9.20.1", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "b02d010e4055ae992247f6ffd1e7b103ef2a0790" + "reference": "491d1e79e973a7370c7571dc0fe4a7241f4936ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/b02d010e4055ae992247f6ffd1e7b103ef2a0790", - "reference": "b02d010e4055ae992247f6ffd1e7b103ef2a0790", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/491d1e79e973a7370c7571dc0fe4a7241f4936ee", + "reference": "491d1e79e973a7370c7571dc0fe4a7241f4936ee", "shasum": "" }, "require": { @@ -5107,12 +5112,12 @@ "ext-xdebug": "*", "friendsofphp/php-cs-fixer": "^3.64.0", "phpbench/phpbench": "^1.3.1", - "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan": "^1.12.11", "phpstan/phpstan-deprecation-rules": "^1.2.1", - "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-phpunit": "^1.4.1", "phpstan/phpstan-strict-rules": "^1.6.1", - "phpunit/phpunit": "^10.5.16 || ^11.4.1", - "symfony/var-dumper": "^6.4.8 || ^7.1.5" + "phpunit/phpunit": "^10.5.16 || ^11.4.3", + "symfony/var-dumper": "^6.4.8 || ^7.1.8" }, "suggest": { "ext-dom": "Required to use the XMLConverter and the HTMLConverter classes", @@ -5169,7 +5174,7 @@ "type": "github" } ], - "time": "2024-10-18T08:14:48+00:00" + "time": "2024-12-18T10:11:15+00:00" }, { "name": "league/event", @@ -5558,20 +5563,20 @@ }, { "name": "league/uri", - "version": "7.4.1", + "version": "7.5.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "bedb6e55eff0c933668addaa7efa1e1f2c417cc4" + "reference": "81fb5145d2644324614cc532b28efd0215bda430" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/bedb6e55eff0c933668addaa7efa1e1f2c417cc4", - "reference": "bedb6e55eff0c933668addaa7efa1e1f2c417cc4", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.3", + "league/uri-interfaces": "^7.5", "php": "^8.1" }, "conflict": { @@ -5636,7 +5641,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.4.1" + "source": "https://github.com/thephpleague/uri/tree/7.5.1" }, "funding": [ { @@ -5644,20 +5649,20 @@ "type": "github" } ], - "time": "2024-03-23T07:42:40+00:00" + "time": "2024-12-08T08:40:02+00:00" }, { "name": "league/uri-interfaces", - "version": "7.4.1", + "version": "7.5.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "8d43ef5c841032c87e2de015972c06f3865ef718" + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/8d43ef5c841032c87e2de015972c06f3865ef718", - "reference": "8d43ef5c841032c87e2de015972c06f3865ef718", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", "shasum": "" }, "require": { @@ -5720,7 +5725,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.4.1" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" }, "funding": [ { @@ -5728,7 +5733,7 @@ "type": "github" } ], - "time": "2024-03-23T07:42:40+00:00" + "time": "2024-12-08T08:18:47+00:00" }, { "name": "livewire/livewire", @@ -5767,12 +5772,12 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Livewire\\LivewireServiceProvider" - ], "aliases": { "Livewire": "Livewire\\Livewire" - } + }, + "providers": [ + "Livewire\\LivewireServiceProvider" + ] } }, "autoload": { @@ -5808,16 +5813,16 @@ }, { "name": "maatwebsite/excel", - "version": "3.1.60", + "version": "3.1.61", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "4906dc57fbe6a41c405a77e1f7cac9078982c9c7" + "reference": "62616317c5ec07e885c5d7f6b537f57a7239c2ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/4906dc57fbe6a41c405a77e1f7cac9078982c9c7", - "reference": "4906dc57fbe6a41c405a77e1f7cac9078982c9c7", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/62616317c5ec07e885c5d7f6b537f57a7239c2ff", + "reference": "62616317c5ec07e885c5d7f6b537f57a7239c2ff", "shasum": "" }, "require": { @@ -5873,7 +5878,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.60" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.61" }, "funding": [ { @@ -5885,7 +5890,7 @@ "type": "github" } ], - "time": "2024-11-11T12:27:45+00:00" + "time": "2024-11-25T18:41:59+00:00" }, { "name": "maennchen/zipstream-php", @@ -6140,28 +6145,29 @@ }, { "name": "mobiledetect/mobiledetectlib", - "version": "4.8.06", + "version": "4.8.09", "source": { "type": "git", "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "af088b54cecc13b3264edca7da93a89ba7aa2d9e" + "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/af088b54cecc13b3264edca7da93a89ba7aa2d9e", - "reference": "af088b54cecc13b3264edca7da93a89ba7aa2d9e", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/a06fe2e546a06bb8c2639d6823d5250b2efb3209", + "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209", "shasum": "" }, "require": { "php": ">=8.0", - "psr/simple-cache": "^2 || ^3" + "psr/cache": "^3.0", + "psr/simple-cache": "^3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.35.1", + "friendsofphp/php-cs-fixer": "^v3.65.0", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6", - "squizlabs/php_codesniffer": "^3.7" + "phpstan/phpstan": "^1.12.x-dev", + "phpunit/phpunit": "^9.6.18", + "squizlabs/php_codesniffer": "^3.11.1" }, "type": "library", "autoload": { @@ -6192,7 +6198,7 @@ ], "support": { "issues": "https://github.com/serbanghita/Mobile-Detect/issues", - "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.8.06" + "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.8.09" }, "funding": [ { @@ -6200,20 +6206,20 @@ "type": "github" } ], - "time": "2024-03-01T22:28:42+00:00" + "time": "2024-12-10T15:32:06+00:00" }, { "name": "monolog/monolog", - "version": "3.8.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67" + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/32e515fdc02cdafbe4593e30a9350d486b125b67", - "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4", + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4", "shasum": "" }, "require": { @@ -6291,7 +6297,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.8.0" + "source": "https://github.com/Seldaek/monolog/tree/3.8.1" }, "funding": [ { @@ -6303,7 +6309,7 @@ "type": "tidelift" } ], - "time": "2024-11-12T13:57:08+00:00" + "time": "2024-12-05T17:15:07+00:00" }, { "name": "mtdowling/jmespath.php", @@ -6474,10 +6480,6 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.x-dev", - "dev-2.x": "2.x-dev" - }, "laravel": { "providers": [ "Carbon\\Laravel\\ServiceProvider" @@ -6487,6 +6489,10 @@ "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" } }, "autoload": { @@ -6817,31 +6823,31 @@ }, { "name": "nunomaduro/termwind", - "version": "v2.2.0", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3" + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/42c84e4e8090766bbd6445d06cd6e57650626ea3", - "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.1.5" + "symfony/console": "^7.1.8" }, "require-dev": { - "illuminate/console": "^11.28.0", - "laravel/pint": "^1.18.1", + "illuminate/console": "^11.33.2", + "laravel/pint": "^1.18.2", "mockery/mockery": "^1.6.12", "pestphp/pest": "^2.36.0", - "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan": "^1.12.11", "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^7.1.5", + "symfony/var-dumper": "^7.1.8", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -6884,7 +6890,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.2.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" }, "funding": [ { @@ -6900,20 +6906,20 @@ "type": "github" } ], - "time": "2024-10-15T16:15:16+00:00" + "time": "2024-11-21T10:39:51+00:00" }, { "name": "nwidart/laravel-modules", - "version": "v11.1.5", + "version": "v11.1.7", "source": { "type": "git", "url": "https://github.com/nWidart/laravel-modules.git", - "reference": "7e52dd96e69da04e8733b74db28370276c57097a" + "reference": "26c0716994b2669c308e15a7090a6867f7a1ba09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/7e52dd96e69da04e8733b74db28370276c57097a", - "reference": "7e52dd96e69da04e8733b74db28370276c57097a", + "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/26c0716994b2669c308e15a7090a6867f7a1ba09", + "reference": "26c0716994b2669c308e15a7090a6867f7a1ba09", "shasum": "" }, "require": { @@ -6925,7 +6931,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^v3.52", - "laravel/framework": "^v11.0", + "laravel/framework": "^v11.33", "laravel/pint": "^1.16", "mockery/mockery": "^1.6", "orchestra/testbench": "^v9.0", @@ -6936,12 +6942,12 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Nwidart\\Modules\\LaravelModulesServiceProvider" - ], "aliases": { "Module": "Nwidart\\Modules\\Facades\\Module" - } + }, + "providers": [ + "Nwidart\\Modules\\LaravelModulesServiceProvider" + ] }, "branch-alias": { "dev-master": "11.0-dev" @@ -6977,7 +6983,7 @@ ], "support": { "issues": "https://github.com/nWidart/laravel-modules/issues", - "source": "https://github.com/nWidart/laravel-modules/tree/v11.1.5" + "source": "https://github.com/nWidart/laravel-modules/tree/v11.1.7" }, "funding": [ { @@ -6989,7 +6995,7 @@ "type": "github" } ], - "time": "2024-11-16T14:05:05+00:00" + "time": "2024-12-06T08:10:11+00:00" }, { "name": "nyholm/psr7", @@ -7071,16 +7077,16 @@ }, { "name": "openspout/openspout", - "version": "v4.26.0", + "version": "v4.28.3", "source": { "type": "git", "url": "https://github.com/openspout/openspout.git", - "reference": "a49b947c0c109f4fd112f9b5c6d6cb3e6baf8b50" + "reference": "12b5eddcc230a97a9a67a722ad75c247e1a16750" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/openspout/openspout/zipball/a49b947c0c109f4fd112f9b5c6d6cb3e6baf8b50", - "reference": "a49b947c0c109f4fd112f9b5c6d6cb3e6baf8b50", + "url": "https://api.github.com/repos/openspout/openspout/zipball/12b5eddcc230a97a9a67a722ad75c247e1a16750", + "reference": "12b5eddcc230a97a9a67a722ad75c247e1a16750", "shasum": "" }, "require": { @@ -7094,13 +7100,13 @@ }, "require-dev": { "ext-zlib": "*", - "friendsofphp/php-cs-fixer": "^3.64.0", - "infection/infection": "^0.29.6", + "friendsofphp/php-cs-fixer": "^3.65.0", + "infection/infection": "^0.29.8", "phpbench/phpbench": "^1.3.1", - "phpstan/phpstan": "^1.12.4", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.1", - "phpunit/phpunit": "^11.3.6" + "phpstan/phpstan": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.1", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^11.5.0" }, "suggest": { "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", @@ -7148,7 +7154,7 @@ ], "support": { "issues": "https://github.com/openspout/openspout/issues", - "source": "https://github.com/openspout/openspout/tree/v4.26.0" + "source": "https://github.com/openspout/openspout/tree/v4.28.3" }, "funding": [ { @@ -7160,7 +7166,7 @@ "type": "github" } ], - "time": "2024-09-24T14:04:43+00:00" + "time": "2024-12-17T11:28:11+00:00" }, { "name": "owen-it/laravel-auditing", @@ -7194,13 +7200,13 @@ }, "type": "package", "extra": { - "branch-alias": { - "dev-master": "v13-dev" - }, "laravel": { "providers": [ "OwenIt\\Auditing\\AuditingServiceProvider" ] + }, + "branch-alias": { + "dev-master": "v13-dev" } }, "autoload": { @@ -7448,16 +7454,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.29.4", + "version": "1.29.6", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "7ca7e325dca3adb6a598385aab81f527b8d6c75d" + "reference": "08597725b84570cd6f32bf0ea92e75a803ef28c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/7ca7e325dca3adb6a598385aab81f527b8d6c75d", - "reference": "7ca7e325dca3adb6a598385aab81f527b8d6c75d", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/08597725b84570cd6f32bf0ea92e75a803ef28c2", + "reference": "08597725b84570cd6f32bf0ea92e75a803ef28c2", "shasum": "" }, "require": { @@ -7485,7 +7491,7 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "dev-main", - "dompdf/dompdf": "^1.0 || ^2.0", + "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", "friendsofphp/php-cs-fixer": "^3.2", "mitoteam/jpgraph": "^10.3", "mpdf/mpdf": "^8.1.1", @@ -7547,9 +7553,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.4" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.6" }, - "time": "2024-11-10T16:26:22+00:00" + "time": "2024-12-08T05:49:00+00:00" }, { "name": "phpoption/phpoption", @@ -7628,16 +7634,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.42", + "version": "3.0.43", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98" + "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/db92f1b1987b12b13f248fe76c3a52cadb67bb98", - "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", + "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", "shasum": "" }, "require": { @@ -7718,7 +7724,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.42" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" }, "funding": [ { @@ -7734,34 +7740,34 @@ "type": "tidelift" } ], - "time": "2024-09-16T03:06:04+00:00" + "time": "2024-12-14T21:12:59+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.33.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -7779,9 +7785,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" }, - "time": "2024-10-13T11:25:22+00:00" + "time": "2024-10-13T11:29:49+00:00" }, { "name": "pragmarx/google2fa", @@ -8298,16 +8304,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.4", + "version": "v0.12.7", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "2fd717afa05341b4f8152547f142cd2f130f6818" + "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/2fd717afa05341b4f8152547f142cd2f130f6818", - "reference": "2fd717afa05341b4f8152547f142cd2f130f6818", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/d73fa3c74918ef4522bb8a3bf9cab39161c4b57c", + "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c", "shasum": "" }, "require": { @@ -8334,12 +8340,12 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-main": "0.12.x-dev" - }, "bamarni-bin": { "bin-links": false, "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" } }, "autoload": { @@ -8371,22 +8377,22 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.4" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.7" }, - "time": "2024-06-10T01:18:23+00:00" + "time": "2024-12-10T01:58:33+00:00" }, { "name": "pxlrbt/filament-environment-indicator", - "version": "v2.0.2", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/pxlrbt/filament-environment-indicator.git", - "reference": "928ccebe9ce14810805b8c23f994f1392e321da2" + "reference": "e55bca20af0c9cff8a90d0a8779b09df5c4bb9d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pxlrbt/filament-environment-indicator/zipball/928ccebe9ce14810805b8c23f994f1392e321da2", - "reference": "928ccebe9ce14810805b8c23f994f1392e321da2", + "url": "https://api.github.com/repos/pxlrbt/filament-environment-indicator/zipball/e55bca20af0c9cff8a90d0a8779b09df5c4bb9d4", + "reference": "e55bca20af0c9cff8a90d0a8779b09df5c4bb9d4", "shasum": "" }, "require": { @@ -8427,7 +8433,7 @@ ], "support": { "issues": "https://github.com/pxlrbt/filament-environment-indicator/issues", - "source": "https://github.com/pxlrbt/filament-environment-indicator/tree/v2.0.2" + "source": "https://github.com/pxlrbt/filament-environment-indicator/tree/v2.1.0" }, "funding": [ { @@ -8435,7 +8441,7 @@ "type": "github" } ], - "time": "2024-09-21T17:43:56+00:00" + "time": "2024-11-18T13:24:51+00:00" }, { "name": "ralouphie/getallheaders", @@ -8769,12 +8775,12 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "RyanChandler\\BladeCaptureDirective\\BladeCaptureDirectiveServiceProvider" - ], "aliases": { "BladeCaptureDirective": "RyanChandler\\BladeCaptureDirective\\Facades\\BladeCaptureDirective" - } + }, + "providers": [ + "RyanChandler\\BladeCaptureDirective\\BladeCaptureDirectiveServiceProvider" + ] } }, "autoload": { @@ -8988,16 +8994,16 @@ }, { "name": "spatie/color", - "version": "1.6.0", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/spatie/color.git", - "reference": "02ce48c480f86d65702188f738f4e8ccad1b999a" + "reference": "b4fac074a9e5999dcca12cbfab0f7c73e2684d6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/color/zipball/02ce48c480f86d65702188f738f4e8ccad1b999a", - "reference": "02ce48c480f86d65702188f738f4e8ccad1b999a", + "url": "https://api.github.com/repos/spatie/color/zipball/b4fac074a9e5999dcca12cbfab0f7c73e2684d6d", + "reference": "b4fac074a9e5999dcca12cbfab0f7c73e2684d6d", "shasum": "" }, "require": { @@ -9035,7 +9041,7 @@ ], "support": { "issues": "https://github.com/spatie/color/issues", - "source": "https://github.com/spatie/color/tree/1.6.0" + "source": "https://github.com/spatie/color/tree/1.6.2" }, "funding": [ { @@ -9043,7 +9049,7 @@ "type": "github" } ], - "time": "2024-09-20T14:00:15+00:00" + "time": "2024-12-09T16:20:38+00:00" }, { "name": "spatie/invade", @@ -9106,16 +9112,16 @@ }, { "name": "spatie/laravel-package-tools", - "version": "1.16.5", + "version": "1.17.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2" + "reference": "9ab30fd24f677e5aa370ea4cf6b41c517d16cf85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/c7413972cf22ffdff97b68499c22baa04eddb6a2", - "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/9ab30fd24f677e5aa370ea4cf6b41c517d16cf85", + "reference": "9ab30fd24f677e5aa370ea4cf6b41c517d16cf85", "shasum": "" }, "require": { @@ -9124,10 +9130,10 @@ }, "require-dev": { "mockery/mockery": "^1.5", - "orchestra/testbench": "^7.7|^8.0", - "pestphp/pest": "^1.22", - "phpunit/phpunit": "^9.5.24", - "spatie/pest-plugin-test-time": "^1.1" + "orchestra/testbench": "^7.7|^8.0|^9.0", + "pestphp/pest": "^1.22|^2", + "phpunit/phpunit": "^9.5.24|^10.5", + "spatie/pest-plugin-test-time": "^1.1|^2.2" }, "type": "library", "autoload": { @@ -9154,7 +9160,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.5" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.17.0" }, "funding": [ { @@ -9162,7 +9168,7 @@ "type": "github" } ], - "time": "2024-08-27T18:56:10+00:00" + "time": "2024-12-09T16:29:14+00:00" }, { "name": "spatie/regex", @@ -9393,16 +9399,16 @@ }, { "name": "stechstudio/filament-impersonate", - "version": "3.14", + "version": "3.15", "source": { "type": "git", "url": "https://github.com/stechstudio/filament-impersonate.git", - "reference": "40538e1617232449e264b8dc17d266e9a96fd440" + "reference": "1214583c9637bf941cc0ea0f260884c0fce65fe3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stechstudio/filament-impersonate/zipball/40538e1617232449e264b8dc17d266e9a96fd440", - "reference": "40538e1617232449e264b8dc17d266e9a96fd440", + "url": "https://api.github.com/repos/stechstudio/filament-impersonate/zipball/1214583c9637bf941cc0ea0f260884c0fce65fe3", + "reference": "1214583c9637bf941cc0ea0f260884c0fce65fe3", "shasum": "" }, "require": { @@ -9429,22 +9435,22 @@ "description": "A Filament package to impersonate your users.", "support": { "issues": "https://github.com/stechstudio/filament-impersonate/issues", - "source": "https://github.com/stechstudio/filament-impersonate/tree/3.14" + "source": "https://github.com/stechstudio/filament-impersonate/tree/3.15" }, - "time": "2024-08-27T12:29:07+00:00" + "time": "2024-12-03T17:20:46+00:00" }, { "name": "symfony/clock", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "97bebc53548684c17ed696bc8af016880f0f098d" + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/97bebc53548684c17ed696bc8af016880f0f098d", - "reference": "97bebc53548684c17ed696bc8af016880f0f098d", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", "shasum": "" }, "require": { @@ -9489,7 +9495,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.1.6" + "source": "https://github.com/symfony/clock/tree/v7.2.0" }, "funding": [ { @@ -9505,20 +9511,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/console", - "version": "v7.1.8", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", "shasum": "" }, "require": { @@ -9582,7 +9588,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.8" + "source": "https://github.com/symfony/console/tree/v7.2.1" }, "funding": [ { @@ -9598,20 +9604,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/css-selector", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66" + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", - "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", "shasum": "" }, "require": { @@ -9647,7 +9653,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.1.6" + "source": "https://github.com/symfony/css-selector/tree/v7.2.0" }, "funding": [ { @@ -9663,20 +9669,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -9714,7 +9720,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -9730,20 +9736,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/error-handler", - "version": "v7.1.7", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "010e44661f4c6babaf8c4862fe68c24a53903342" + "reference": "6150b89186573046167796fa5f3f76601d5145f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/010e44661f4c6babaf8c4862fe68c24a53903342", - "reference": "010e44661f4c6babaf8c4862fe68c24a53903342", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/6150b89186573046167796fa5f3f76601d5145f8", + "reference": "6150b89186573046167796fa5f3f76601d5145f8", "shasum": "" }, "require": { @@ -9789,7 +9795,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.1.7" + "source": "https://github.com/symfony/error-handler/tree/v7.2.1" }, "funding": [ { @@ -9805,20 +9811,20 @@ "type": "tidelift" } ], - "time": "2024-11-05T15:34:55+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "87254c78dd50721cfd015b62277a8281c5589702" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87254c78dd50721cfd015b62277a8281c5589702", - "reference": "87254c78dd50721cfd015b62277a8281c5589702", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { @@ -9869,7 +9875,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.6" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -9885,20 +9891,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -9945,7 +9951,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -9961,20 +9967,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { @@ -10011,7 +10017,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.6" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -10027,20 +10033,20 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", + "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", "shasum": "" }, "require": { @@ -10075,7 +10081,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.6" + "source": "https://github.com/symfony/finder/tree/v7.2.0" }, "funding": [ { @@ -10091,20 +10097,20 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "symfony/html-sanitizer", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/html-sanitizer.git", - "reference": "a25620fc6407e14331f3c0c5668eb4f35c392d4a" + "reference": "1d23de45af5e8508441ff5f82bb493e83cdcbba4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/a25620fc6407e14331f3c0c5668eb4f35c392d4a", - "reference": "a25620fc6407e14331f3c0c5668eb4f35c392d4a", + "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/1d23de45af5e8508441ff5f82bb493e83cdcbba4", + "reference": "1d23de45af5e8508441ff5f82bb493e83cdcbba4", "shasum": "" }, "require": { @@ -10144,7 +10150,7 @@ "sanitizer" ], "support": { - "source": "https://github.com/symfony/html-sanitizer/tree/v7.1.6" + "source": "https://github.com/symfony/html-sanitizer/tree/v7.2.0" }, "funding": [ { @@ -10160,24 +10166,25 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f4419ec69ccfc3f725a4de7c20e4e57626d10112" + "reference": "e88a66c3997859532bc2ddd6dd8f35aba2711744" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f4419ec69ccfc3f725a4de7c20e4e57626d10112", - "reference": "f4419ec69ccfc3f725a4de7c20e4e57626d10112", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e88a66c3997859532bc2ddd6dd8f35aba2711744", + "reference": "e88a66c3997859532bc2ddd6dd8f35aba2711744", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php83": "^1.27" }, @@ -10221,7 +10228,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.1.8" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.0" }, "funding": [ { @@ -10237,20 +10244,20 @@ "type": "tidelift" } ], - "time": "2024-11-09T09:16:45+00:00" + "time": "2024-11-13T18:58:46+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.1.8", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "33fef24e3dc79d6d30bf4936531f2f4bd2ca189e" + "reference": "d8ae58eecae44c8e66833e76cc50a4ad3c002d97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/33fef24e3dc79d6d30bf4936531f2f4bd2ca189e", - "reference": "33fef24e3dc79d6d30bf4936531f2f4bd2ca189e", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d8ae58eecae44c8e66833e76cc50a4ad3c002d97", + "reference": "d8ae58eecae44c8e66833e76cc50a4ad3c002d97", "shasum": "" }, "require": { @@ -10279,7 +10286,7 @@ "symfony/twig-bridge": "<6.4", "symfony/validator": "<6.4", "symfony/var-dumper": "<6.4", - "twig/twig": "<3.0.4" + "twig/twig": "<3.12" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" @@ -10307,7 +10314,7 @@ "symfony/validator": "^6.4|^7.0", "symfony/var-dumper": "^6.4|^7.0", "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.0.4" + "twig/twig": "^3.12" }, "type": "library", "autoload": { @@ -10335,7 +10342,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.8" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.1" }, "funding": [ { @@ -10351,20 +10358,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T14:25:32+00:00" + "time": "2024-12-11T12:09:10+00:00" }, { "name": "symfony/mailer", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd" + "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/69c9948451fb3a6a4d47dc8261d1794734e76cdd", - "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd", + "url": "https://api.github.com/repos/symfony/mailer/zipball/e4d358702fb66e4c8a2af08e90e7271a62de39cc", + "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc", "shasum": "" }, "require": { @@ -10373,7 +10380,7 @@ "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", + "symfony/mime": "^7.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -10415,7 +10422,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.1.6" + "source": "https://github.com/symfony/mailer/tree/v7.2.0" }, "funding": [ { @@ -10431,20 +10438,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-25T15:21:05+00:00" }, { "name": "symfony/mime", - "version": "v7.1.6", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "caa1e521edb2650b8470918dfe51708c237f0598" + "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", - "reference": "caa1e521edb2650b8470918dfe51708c237f0598", + "url": "https://api.github.com/repos/symfony/mime/zipball/7f9617fcf15cb61be30f8b252695ed5e2bfac283", + "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283", "shasum": "" }, "require": { @@ -10499,7 +10506,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.6" + "source": "https://github.com/symfony/mime/tree/v7.2.1" }, "funding": [ { @@ -10515,7 +10522,7 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/polyfill-ctype", @@ -10543,8 +10550,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -10619,8 +10626,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -10698,8 +10705,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -10780,8 +10787,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -10864,8 +10871,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -10938,8 +10945,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -11014,8 +11021,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -11094,8 +11101,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -11170,8 +11177,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -11252,8 +11259,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -11307,16 +11314,16 @@ }, { "name": "symfony/process", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", "shasum": "" }, "require": { @@ -11348,7 +11355,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.8" + "source": "https://github.com/symfony/process/tree/v7.2.0" }, "funding": [ { @@ -11364,20 +11371,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "f16471bb19f6685b9ccf0a2c03c213840ae68cd6" + "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/f16471bb19f6685b9ccf0a2c03c213840ae68cd6", - "reference": "f16471bb19f6685b9ccf0a2c03c213840ae68cd6", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", "shasum": "" }, "require": { @@ -11431,7 +11438,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.1.6" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.2.0" }, "funding": [ { @@ -11447,20 +11454,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-26T08:57:56+00:00" }, { "name": "symfony/routing", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a" + "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/66a2c469f6c22d08603235c46a20007c0701ea0a", - "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a", + "url": "https://api.github.com/repos/symfony/routing/zipball/e10a2450fa957af6c448b9b93c9010a4e4c0725e", + "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e", "shasum": "" }, "require": { @@ -11512,7 +11519,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.6" + "source": "https://github.com/symfony/routing/tree/v7.2.0" }, "funding": [ { @@ -11528,20 +11535,20 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-11-25T11:08:51+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -11595,7 +11602,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -11611,20 +11618,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { @@ -11682,7 +11689,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.8" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -11698,24 +11705,25 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:21+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "symfony/translation", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f" + "reference": "dc89e16b44048ceecc879054e5b7f38326ab6cc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b9f72ab14efdb6b772f85041fa12f820dee8d55f", - "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f", + "url": "https://api.github.com/repos/symfony/translation/zipball/dc89e16b44048ceecc879054e5b7f38326ab6cc5", + "reference": "dc89e16b44048ceecc879054e5b7f38326ab6cc5", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.5|^3.0" }, @@ -11776,7 +11784,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.1.6" + "source": "https://github.com/symfony/translation/tree/v7.2.0" }, "funding": [ { @@ -11792,20 +11800,20 @@ "type": "tidelift" } ], - "time": "2024-09-28T12:35:13+00:00" + "time": "2024-11-12T20:47:56+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { @@ -11854,7 +11862,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -11870,20 +11878,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/uid", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "65befb3bb2d503bbffbd08c815aa38b472999917" + "reference": "2d294d0c48df244c71c105a169d0190bfb080426" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/65befb3bb2d503bbffbd08c815aa38b472999917", - "reference": "65befb3bb2d503bbffbd08c815aa38b472999917", + "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426", "shasum": "" }, "require": { @@ -11928,7 +11936,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.6" + "source": "https://github.com/symfony/uid/tree/v7.2.0" }, "funding": [ { @@ -11944,20 +11952,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8" + "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8", - "reference": "7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", + "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", "shasum": "" }, "require": { @@ -11973,7 +11981,7 @@ "symfony/http-kernel": "^6.4|^7.0", "symfony/process": "^6.4|^7.0", "symfony/uid": "^6.4|^7.0", - "twig/twig": "^3.0.4" + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -12011,7 +12019,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.8" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" }, "funding": [ { @@ -12027,20 +12035,20 @@ "type": "tidelift" } ], - "time": "2024-11-08T15:46:42+00:00" + "time": "2024-11-08T15:48:14+00:00" }, { "name": "tightenco/ziggy", - "version": "v2.4.0", + "version": "v2.4.1", "source": { "type": "git", "url": "https://github.com/tighten/ziggy.git", - "reference": "e5d51d2a58c23a2932d80938990fa6a7623cbe46" + "reference": "8e002298678fd4d61155bb1d6e3837048235bff7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tighten/ziggy/zipball/e5d51d2a58c23a2932d80938990fa6a7623cbe46", - "reference": "e5d51d2a58c23a2932d80938990fa6a7623cbe46", + "url": "https://api.github.com/repos/tighten/ziggy/zipball/8e002298678fd4d61155bb1d6e3837048235bff7", + "reference": "8e002298678fd4d61155bb1d6e3837048235bff7", "shasum": "" }, "require": { @@ -12095,9 +12103,9 @@ ], "support": { "issues": "https://github.com/tighten/ziggy/issues", - "source": "https://github.com/tighten/ziggy/tree/v2.4.0" + "source": "https://github.com/tighten/ziggy/tree/v2.4.1" }, - "time": "2024-11-09T17:21:59+00:00" + "time": "2024-11-21T15:51:20+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -12154,16 +12162,16 @@ }, { "name": "tpetry/laravel-postgresql-enhanced", - "version": "2.0.1", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/tpetry/laravel-postgresql-enhanced.git", - "reference": "2e47e65fc68044c1c3c15b079329c45c3f9ee627" + "reference": "387779b26b5018af535e30a9b6c3a0cbeab69aab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tpetry/laravel-postgresql-enhanced/zipball/2e47e65fc68044c1c3c15b079329c45c3f9ee627", - "reference": "2e47e65fc68044c1c3c15b079329c45c3f9ee627", + "url": "https://api.github.com/repos/tpetry/laravel-postgresql-enhanced/zipball/387779b26b5018af535e30a9b6c3a0cbeab69aab", + "reference": "387779b26b5018af535e30a9b6c3a0cbeab69aab", "shasum": "" }, "require": { @@ -12178,12 +12186,12 @@ "require-dev": { "composer/semver": "^3.4", "friendsofphp/php-cs-fixer": "^2.19.3|^3.5.0", + "larastan/larastan": "^1.0|^2.1|^3.0", "nesbot/carbon": "^2.7|^3.3", - "nunomaduro/larastan": "^1.0|^2.1", "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^8.5.23|^9.5.13|^10.5", + "phpstan/phpstan": "^1.5|^2.0", + "phpunit/phpunit": "^8.5.23|^9.5.13|^10.5|^11.4", "ramsey/uuid": "^3.9|^4.7" }, "type": "library", @@ -12222,9 +12230,9 @@ ], "support": { "issues": "https://github.com/tpetry/laravel-postgresql-enhanced/issues", - "source": "https://github.com/tpetry/laravel-postgresql-enhanced/tree/2.0.1" + "source": "https://github.com/tpetry/laravel-postgresql-enhanced/tree/2.1.0" }, - "time": "2024-10-30T09:12:29+00:00" + "time": "2024-12-16T16:08:11+00:00" }, { "name": "vlucas/phpdotenv", @@ -12312,16 +12320,16 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b56450eed252f6801410d810c8e1727224ae0743" + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", - "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", "shasum": "" }, "require": { @@ -12346,7 +12354,7 @@ "authors": [ { "name": "Lars Moelleken", - "homepage": "http://www.moelleken.org/" + "homepage": "https://www.moelleken.org/" } ], "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", @@ -12358,7 +12366,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" }, "funding": [ { @@ -12382,7 +12390,7 @@ "type": "tidelift" } ], - "time": "2022-03-08T17:03:00+00:00" + "time": "2024-11-21T01:49:47+00:00" }, { "name": "webmozart/assert", @@ -12471,10 +12479,10 @@ }, "type": "composer-plugin", "extra": { + "class": "Wikimedia\\Composer\\Merge\\V2\\MergePlugin", "branch-alias": { "dev-master": "2.x-dev" - }, - "class": "Wikimedia\\Composer\\Merge\\V2\\MergePlugin" + } }, "autoload": { "psr-4": { @@ -12502,16 +12510,16 @@ "packages-dev": [ { "name": "barryvdh/laravel-ide-helper", - "version": "v3.2.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "07e3bd8796f3d1414801a03d3783f9d3ec9efc08" + "reference": "b7675670f75914bf34afdea52a6c2fe3781f7c44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/07e3bd8796f3d1414801a03d3783f9d3ec9efc08", - "reference": "07e3bd8796f3d1414801a03d3783f9d3ec9efc08", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/b7675670f75914bf34afdea52a6c2fe3781f7c44", + "reference": "b7675670f75914bf34afdea52a6c2fe3781f7c44", "shasum": "" }, "require": { @@ -12542,13 +12550,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - }, "laravel": { "providers": [ "Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider" ] + }, + "branch-alias": { + "dev-master": "3.2-dev" } }, "autoload": { @@ -12580,7 +12588,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.2.2" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.3.0" }, "funding": [ { @@ -12592,7 +12600,7 @@ "type": "github" } ], - "time": "2024-10-29T14:00:16+00:00" + "time": "2024-12-18T08:24:19+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -12648,16 +12656,16 @@ }, { "name": "brianium/paratest", - "version": "v7.6.0", + "version": "v7.7.0", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254" + "reference": "4fb3f73bc5a4c3146bac2850af7dc72435a32daf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/68ff89a8de47d086588e391a516d2a5b5fde6254", - "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/4fb3f73bc5a4c3146bac2850af7dc72435a32daf", + "reference": "4fb3f73bc5a4c3146bac2850af7dc72435a32daf", "shasum": "" }, "require": { @@ -12666,26 +12674,26 @@ "ext-reflection": "*", "ext-simplexml": "*", "fidry/cpu-core-counter": "^1.2.0", - "jean85/pretty-package-versions": "^2.0.6", + "jean85/pretty-package-versions": "^2.1.0", "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-code-coverage": "^11.0.8", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-timer": "^7.0.1", - "phpunit/phpunit": "^11.4.1", + "phpunit/phpunit": "^11.5.1", "sebastian/environment": "^7.2.0", - "symfony/console": "^6.4.11 || ^7.1.5", - "symfony/process": "^6.4.8 || ^7.1.5" + "symfony/console": "^6.4.14 || ^7.2.1", + "symfony/process": "^6.4.14 || ^7.2.0" }, "require-dev": { "doctrine/coding-standard": "^12.0.0", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^1.12.6", - "phpstan/phpstan-deprecation-rules": "^1.2.1", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.1", - "squizlabs/php_codesniffer": "^3.10.3", - "symfony/filesystem": "^6.4.9 || ^7.1.5" + "phpstan/phpstan": "^2.0.3", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.1", + "phpstan/phpstan-strict-rules": "^2", + "squizlabs/php_codesniffer": "^3.11.1", + "symfony/filesystem": "^6.4.13 || ^7.2.0" }, "bin": [ "bin/paratest", @@ -12725,7 +12733,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.6.0" + "source": "https://github.com/paratestphp/paratest/tree/v7.7.0" }, "funding": [ { @@ -12737,20 +12745,20 @@ "type": "paypal" } ], - "time": "2024-10-15T12:38:31+00:00" + "time": "2024-12-11T14:50:44+00:00" }, { "name": "fakerphp/faker", - "version": "v1.24.0", + "version": "v1.24.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "a136842a532bac9ecd8a1c723852b09915d7db50" + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/a136842a532bac9ecd8a1c723852b09915d7db50", - "reference": "a136842a532bac9ecd8a1c723852b09915d7db50", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", "shasum": "" }, "require": { @@ -12798,9 +12806,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.24.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" }, - "time": "2024-11-07T15:11:20+00:00" + "time": "2024-11-21T13:46:39+00:00" }, { "name": "fidry/cpu-core-counter", @@ -12936,32 +12944,35 @@ }, { "name": "fumeapp/modeltyper", - "version": "v2.8.2", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/fumeapp/modeltyper.git", - "reference": "527cffc2af6191fcb39cd424f338119f44a7cc9b" + "reference": "9e03f3344bbac3e32006fc6959d30b347847d28c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fumeapp/modeltyper/zipball/527cffc2af6191fcb39cd424f338119f44a7cc9b", - "reference": "527cffc2af6191fcb39cd424f338119f44a7cc9b", + "url": "https://api.github.com/repos/fumeapp/modeltyper/zipball/9e03f3344bbac3e32006fc6959d30b347847d28c", + "reference": "9e03f3344bbac3e32006fc6959d30b347847d28c", "shasum": "" }, "require": { - "illuminate/console": "^10.0.0|^11.0", - "illuminate/database": "^10.0.0|^11.0", - "illuminate/support": "^10.0.0|^11.0", - "php": "^8.1" + "illuminate/console": "^11.33.0", + "illuminate/database": "^11.33.0", + "illuminate/support": "^11.33.0", + "php": "^8.2" + }, + "conflict": { + "laravel/framework": "<11.33.0", + "nesbot/carbon": "<3.5.0" }, "require-dev": { - "consolidation/robo": "^4.0", - "doctrine/dbal": "^3.6", - "larastan/larastan": "^2.2", - "laravel/pint": "^1.7", - "orchestra/testbench": "^8.0|^9.0", - "phpunit/phpunit": "^10.0", - "spatie/laravel-ray": "^1.32", + "consolidation/robo": "^5.1.0", + "larastan/larastan": "^3.0.2", + "laravel/pint": "^1.18.3", + "orchestra/testbench": "^9.6.1", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpunit/phpunit": "^11.4.4", "totten/lurkerlite": "^1.3" }, "type": "library", @@ -12990,9 +13001,9 @@ "description": "Generate TypeScript interfaces from Laravel Models", "support": { "issues": "https://github.com/fumeapp/modeltyper/issues", - "source": "https://github.com/fumeapp/modeltyper/tree/v2.8.2" + "source": "https://github.com/fumeapp/modeltyper/tree/v3.0.1" }, - "time": "2024-11-07T17:48:04+00:00" + "time": "2024-12-16T16:58:38+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -13047,28 +13058,28 @@ }, { "name": "jean85/pretty-package-versions", - "version": "2.0.6", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", "shasum": "" }, "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.1|^8.0" + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^7.5|^8.5|^9.4", - "vimeo/psalm": "^4.3" + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "vimeo/psalm": "^4.3 || ^5.0" }, "type": "library", "extra": { @@ -13100,9 +13111,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0" }, - "time": "2024-03-08T09:58:59+00:00" + "time": "2024-11-18T16:19:46+00:00" }, { "name": "larastan/larastan", @@ -13143,13 +13154,13 @@ }, "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - }, "phpstan": { "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-master": "2.0-dev" } }, "autoload": { @@ -13208,16 +13219,16 @@ }, { "name": "laravel/pint", - "version": "v1.18.1", + "version": "v1.18.3", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9" + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/cef51821608239040ab841ad6e1c6ae502ae3026", + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026", "shasum": "" }, "require": { @@ -13228,13 +13239,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", + "friendsofphp/php-cs-fixer": "^3.65.0", + "illuminate/view": "^10.48.24", + "larastan/larastan": "^2.9.11", "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^1.17.0", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -13270,20 +13281,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-09-24T17:22:50+00:00" + "time": "2024-11-26T15:34:00+00:00" }, { "name": "laravel/sail", - "version": "v1.38.0", + "version": "v1.39.1", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "d17abae06661dd6c46d13627b1683a2924259145" + "reference": "1a3c7291bc88de983b66688919a4d298d68ddec7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/d17abae06661dd6c46d13627b1683a2924259145", - "reference": "d17abae06661dd6c46d13627b1683a2924259145", + "url": "https://api.github.com/repos/laravel/sail/zipball/1a3c7291bc88de983b66688919a4d298d68ddec7", + "reference": "1a3c7291bc88de983b66688919a4d298d68ddec7", "shasum": "" }, "require": { @@ -13333,20 +13344,20 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2024-11-11T20:16:51+00:00" + "time": "2024-11-27T15:42:28+00:00" }, { "name": "laravel/telescope", - "version": "v5.2.5", + "version": "v5.2.6", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "f68386a8d816c9e3a011b8301bfd263213bf00d4" + "reference": "7ee46fbea8e3b01108575c8edf7377abddfe8bb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/f68386a8d816c9e3a011b8301bfd263213bf00d4", - "reference": "f68386a8d816c9e3a011b8301bfd263213bf00d4", + "url": "https://api.github.com/repos/laravel/telescope/zipball/7ee46fbea8e3b01108575c8edf7377abddfe8bb9", + "reference": "7ee46fbea8e3b01108575c8edf7377abddfe8bb9", "shasum": "" }, "require": { @@ -13400,9 +13411,9 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v5.2.5" + "source": "https://github.com/laravel/telescope/tree/v5.2.6" }, - "time": "2024-10-31T17:06:07+00:00" + "time": "2024-11-25T20:34:58+00:00" }, { "name": "mockery/mockery", @@ -13815,16 +13826,16 @@ }, { "name": "phpmyadmin/sql-parser", - "version": "5.10.1", + "version": "5.10.2", "source": { "type": "git", "url": "https://github.com/phpmyadmin/sql-parser.git", - "reference": "b14fd66496a22d8dd7f7e2791edd9e8674422f17" + "reference": "72afbce7e4b421593b60d2eb7281e37a50734df8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/b14fd66496a22d8dd7f7e2791edd9e8674422f17", - "reference": "b14fd66496a22d8dd7f7e2791edd9e8674422f17", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/72afbce7e4b421593b60d2eb7281e37a50734df8", + "reference": "72afbce7e4b421593b60d2eb7281e37a50734df8", "shasum": "" }, "require": { @@ -13898,7 +13909,7 @@ "type": "other" } ], - "time": "2024-11-10T04:10:31+00:00" + "time": "2024-12-05T15:04:09+00:00" }, { "name": "phpstan/phpstan", @@ -13960,16 +13971,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "11.0.7", + "version": "11.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", - "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", "shasum": "" }, "require": { @@ -13988,7 +13999,7 @@ "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^11.4.1" + "phpunit/phpunit": "^11.5.0" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -14026,7 +14037,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" }, "funding": [ { @@ -14034,7 +14045,7 @@ "type": "github" } ], - "time": "2024-10-09T06:21:38+00:00" + "time": "2024-12-11T12:34:27+00:00" }, { "name": "phpunit/php-file-iterator", @@ -14283,16 +14294,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.4.3", + "version": "11.5.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" + "reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", - "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2b94d4f2450b9869fa64a46fd8a6a41997aef56a", + "reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a", "shasum": "" }, "require": { @@ -14302,7 +14313,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.12.1", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", @@ -14313,14 +14324,15 @@ "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", "sebastian/code-unit": "^3.0.1", - "sebastian/comparator": "^6.1.1", + "sebastian/comparator": "^6.2.1", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", - "sebastian/exporter": "^6.1.3", + "sebastian/exporter": "^6.3.0", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", "sebastian/type": "^5.1.0", - "sebastian/version": "^5.0.2" + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -14331,7 +14343,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "11.4-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -14363,7 +14375,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.1" }, "funding": [ { @@ -14379,7 +14391,7 @@ "type": "tidelift" } ], - "time": "2024-10-28T13:07:50+00:00" + "time": "2024-12-11T10:52:48+00:00" }, { "name": "sebastian/cli-parser", @@ -14440,23 +14452,23 @@ }, { "name": "sebastian/code-unit", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", - "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { @@ -14485,7 +14497,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" }, "funding": [ { @@ -14493,7 +14505,7 @@ "type": "github" } ], - "time": "2024-07-03T04:44:28+00:00" + "time": "2024-12-12T09:59:06+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -14819,16 +14831,16 @@ }, { "name": "sebastian/exporter", - "version": "6.1.3", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", - "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { @@ -14837,7 +14849,7 @@ "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.2" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -14885,7 +14897,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { @@ -14893,7 +14905,7 @@ "type": "github" } ], - "time": "2024-07-03T04:56:19+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { "name": "sebastian/global-state", @@ -15306,27 +15318,27 @@ }, { "name": "spatie/backtrace", - "version": "1.6.2", + "version": "1.7.1", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9" + "reference": "0f2477c520e3729de58e061b8192f161c99f770b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/1a9a145b044677ae3424693f7b06479fc8c137a9", - "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/0f2477c520e3729de58e061b8192f161c99f770b", + "reference": "0f2477c520e3729de58e061b8192f161c99f770b", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^7.3 || ^8.0" }, "require-dev": { "ext-json": "*", - "laravel/serializable-closure": "^1.3", - "phpunit/phpunit": "^9.3", - "spatie/phpunit-snapshot-assertions": "^4.2", - "symfony/var-dumper": "^5.1" + "laravel/serializable-closure": "^1.3 || ^2.0", + "phpunit/phpunit": "^9.3 || ^11.4.3", + "spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1.6", + "symfony/var-dumper": "^5.1 || ^6.0 || ^7.0" }, "type": "library", "autoload": { @@ -15353,7 +15365,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.6.2" + "source": "https://github.com/spatie/backtrace/tree/1.7.1" }, "funding": [ { @@ -15365,20 +15377,20 @@ "type": "other" } ], - "time": "2024-07-22T08:21:24+00:00" + "time": "2024-12-02T13:28:15+00:00" }, { "name": "spatie/error-solutions", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "ae7393122eda72eed7cc4f176d1e96ea444f2d67" + "reference": "d239a65235a1eb128dfa0a4e4c4ef032ea11b541" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/ae7393122eda72eed7cc4f176d1e96ea444f2d67", - "reference": "ae7393122eda72eed7cc4f176d1e96ea444f2d67", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/d239a65235a1eb128dfa0a4e4c4ef032ea11b541", + "reference": "d239a65235a1eb128dfa0a4e4c4ef032ea11b541", "shasum": "" }, "require": { @@ -15431,7 +15443,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.1.1" + "source": "https://github.com/spatie/error-solutions/tree/1.1.2" }, "funding": [ { @@ -15439,20 +15451,20 @@ "type": "github" } ], - "time": "2024-07-25T11:06:04+00:00" + "time": "2024-12-11T09:51:56+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.8.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122" + "reference": "140a42b2c5d59ac4ecf8f5b493386a4f2eb28272" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122", - "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/140a42b2c5d59ac4ecf8f5b493386a4f2eb28272", + "reference": "140a42b2c5d59ac4ecf8f5b493386a4f2eb28272", "shasum": "" }, "require": { @@ -15500,7 +15512,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.8.0" + "source": "https://github.com/spatie/flare-client-php/tree/1.10.0" }, "funding": [ { @@ -15508,7 +15520,7 @@ "type": "github" } ], - "time": "2024-08-01T08:27:26+00:00" + "time": "2024-12-02T14:30:06+00:00" }, { "name": "spatie/ignition", @@ -15595,16 +15607,16 @@ }, { "name": "spatie/laravel-ignition", - "version": "2.8.0", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "3c067b75bfb50574db8f7e2c3978c65eed71126c" + "reference": "62042df15314b829d0f26e02108f559018e2aad0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/3c067b75bfb50574db8f7e2c3978c65eed71126c", - "reference": "3c067b75bfb50574db8f7e2c3978c65eed71126c", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/62042df15314b829d0f26e02108f559018e2aad0", + "reference": "62042df15314b829d0f26e02108f559018e2aad0", "shasum": "" }, "require": { @@ -15635,12 +15647,12 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Spatie\\LaravelIgnition\\IgnitionServiceProvider" - ], "aliases": { "Flare": "Spatie\\LaravelIgnition\\Facades\\Flare" - } + }, + "providers": [ + "Spatie\\LaravelIgnition\\IgnitionServiceProvider" + ] } }, "autoload": { @@ -15682,24 +15694,77 @@ "type": "github" } ], - "time": "2024-06-12T15:01:18+00:00" + "time": "2024-12-02T08:43:31+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" }, { "name": "symfony/yaml", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671" + "reference": "099581e99f557e9f16b43c5916c26380b54abb22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", - "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", + "url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22", + "reference": "099581e99f557e9f16b43c5916c26380b54abb22", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -15737,7 +15802,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.1.6" + "source": "https://github.com/symfony/yaml/tree/v7.2.0" }, "funding": [ { @@ -15753,7 +15818,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/app.php b/config/app.php index f2eababf..35a13f39 100644 --- a/config/app.php +++ b/config/app.php @@ -67,6 +67,8 @@ 'force_https' => (bool) env('APP_FORCE_HTTPS', false), + 'enable_registration' => (bool) env('APP_ENABLE_REGISTRATION', false), + /* |-------------------------------------------------------------------------- | Application Timezone diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index c286c6fb..78c6eb36 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -12,6 +12,7 @@ use App\Models\OrganizationInvitation; use App\Models\Project; use App\Models\ProjectMember; +use App\Models\Report; use App\Models\Tag; use App\Models\Task; use App\Models\TimeEntry; @@ -134,6 +135,7 @@ public function run(): void 'personal_team' => true, 'currency' => 'USD', ]); + Member::factory()->forUser($rivalOwner)->forOrganization($organizationRival)->role(Role::Owner)->create(); $userRivalManager = User::factory()->withPersonalOrganization()->create([ 'name' => 'Other User', 'email' => 'test@rival-company.test', @@ -186,6 +188,7 @@ private function deleteAll(): void // Application tables DB::table((new Audit)->getTable())->delete(); + DB::table((new Report)->getTable())->delete(); DB::table((new TimeEntry)->getTable())->delete(); DB::table((new Task)->getTable())->delete(); DB::table((new Tag)->getTable())->delete(); diff --git a/tests/Feature/RegistrationTest.php b/tests/Feature/RegistrationTest.php index be1d7f9b..66e027ee 100644 --- a/tests/Feature/RegistrationTest.php +++ b/tests/Feature/RegistrationTest.php @@ -13,6 +13,7 @@ use App\Service\IpLookup\IpLookupResponseDto; use App\Service\IpLookup\IpLookupServiceContract; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Event; use Laravel\Fortify\Features; use Laravel\Jetstream\Jetstream; @@ -63,6 +64,31 @@ public function test_new_users_can_register(): void Event::assertNotDispatched(NewsletterRegistered::class); } + public function test_user_registration_fails_if_registration_is_deactivated(): void + { + // Arrange + Event::fake([ + NewsletterRegistered::class, + ]); + Config::set('app.enable_registration', false); + + // Act + $response = $this->post('/register', [ + 'name' => 'Test User', + 'email' => 'test@example.com', + 'password' => 'password', + 'password_confirmation' => 'password', + 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(), + ]); + + // Assert + $response->assertInvalid([ + 'email' => 'Registration is disabled.', + ]); + $this->assertFalse(User::query()->where('email', 'test@example.com')->exists()); + Event::assertNotDispatched(NewsletterRegistered::class); + } + public function test_new_user_can_not_register_with_likely_invalid_domain(): void { // Act diff --git a/tests/Unit/Endpoint/Api/V1/Public/PublicReportEndpointTest.php b/tests/Unit/Endpoint/Api/V1/Public/PublicReportEndpointTest.php index 909e311e..b0b81e9d 100644 --- a/tests/Unit/Endpoint/Api/V1/Public/PublicReportEndpointTest.php +++ b/tests/Unit/Endpoint/Api/V1/Public/PublicReportEndpointTest.php @@ -79,6 +79,7 @@ public function test_show_fails_with_not_found_if_report_is_expired(): void public function test_show_returns_detailed_information_about_the_report(): void { // Arrange + $timezone = 'Europe/Vienna'; $reportDto = new ReportPropertiesDto; $organization = Organization::factory()->create(); $reportDto->start = now()->subDays(2); @@ -87,7 +88,7 @@ public function test_show_returns_detailed_information_about_the_report(): void $reportDto->subGroup = TimeEntryAggregationType::Task; $reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day; $reportDto->weekStart = Weekday::Monday; - $reportDto->timezone = 'Europe/Vienna'; + $reportDto->timezone = $timezone; $report = Report::factory()->forOrganization($organization)->public()->create([ 'public_until' => null, 'properties' => $reportDto, @@ -182,7 +183,7 @@ public function test_show_returns_detailed_information_about_the_report(): void 'grouped_type' => TimeEntryAggregationTypeInterval::Day->value, 'grouped_data' => [ [ - 'key' => now()->subDays(2)->toDateString(), + 'key' => now()->timezone($timezone)->subDays(2)->toDateString(), 'seconds' => 0, 'cost' => 0, 'grouped_type' => null, @@ -191,7 +192,7 @@ public function test_show_returns_detailed_information_about_the_report(): void 'color' => null, ], [ - 'key' => now()->subDays(1)->toDateString(), + 'key' => now()->timezone($timezone)->subDays(1)->toDateString(), 'seconds' => 300, 'cost' => 0, 'grouped_type' => null, @@ -200,7 +201,7 @@ public function test_show_returns_detailed_information_about_the_report(): void 'color' => null, ], [ - 'key' => now()->toDateString(), + 'key' => now()->timezone($timezone)->toDateString(), 'seconds' => 0, 'cost' => 0, 'grouped_type' => null, @@ -320,6 +321,7 @@ public function test_show_returns_detailed_information_about_the_report_with_all public function test_if_the_resources_behind_the_filters_no_longer_exist_the_report_ignores_those_filters_but_this_does_not_increase_the_visible_data(): void { // Arrange + $timezone = 'Europe/Vienna'; $organization = Organization::factory()->create(); $client = Client::factory()->forOrganization($organization)->create(); $project = Project::factory()->forClient($client)->forOrganization($organization)->create(); @@ -341,7 +343,7 @@ public function test_if_the_resources_behind_the_filters_no_longer_exist_the_rep $reportDto->subGroup = TimeEntryAggregationType::Task; $reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day; $reportDto->weekStart = Weekday::Monday; - $reportDto->timezone = 'Europe/Vienna'; + $reportDto->timezone = $timezone; $reportDto->setMemberIds([Str::uuid()->toString()]); $reportDto->setClientIds([Str::uuid()->toString()]); $reportDto->setProjectIds([Str::uuid()->toString()]); @@ -382,7 +384,7 @@ public function test_if_the_resources_behind_the_filters_no_longer_exist_the_rep 'grouped_type' => TimeEntryAggregationTypeInterval::Day->value, 'grouped_data' => [ [ - 'key' => now()->subDays(2)->toDateString(), + 'key' => now()->timezone($timezone)->subDays(2)->toDateString(), 'seconds' => 0, 'cost' => 0, 'grouped_type' => null, @@ -391,7 +393,7 @@ public function test_if_the_resources_behind_the_filters_no_longer_exist_the_rep 'color' => null, ], [ - 'key' => now()->subDays(1)->toDateString(), + 'key' => now()->timezone($timezone)->subDays(1)->toDateString(), 'seconds' => 0, 'cost' => 0, 'grouped_type' => null, @@ -400,7 +402,7 @@ public function test_if_the_resources_behind_the_filters_no_longer_exist_the_rep 'color' => null, ], [ - 'key' => now()->toDateString(), + 'key' => now()->timezone($timezone)->toDateString(), 'seconds' => 0, 'cost' => 0, 'grouped_type' => null, diff --git a/tests/Unit/Endpoint/Api/V1/TimeEntryEndpointTest.php b/tests/Unit/Endpoint/Api/V1/TimeEntryEndpointTest.php index 94bde8a2..22b8773b 100644 --- a/tests/Unit/Endpoint/Api/V1/TimeEntryEndpointTest.php +++ b/tests/Unit/Endpoint/Api/V1/TimeEntryEndpointTest.php @@ -261,7 +261,7 @@ public function test_index_endpoint_filter_only_full_dates_returns_time_entries_ { // Arrange $now = Carbon::create(2024, 1, 1, 12, 0, 0, 'Europe/Vienna'); - $this->freezeTime($now); + $this->travelTo($now); $data = $this->createUserWithPermission([ 'time-entries:view:own', ]); @@ -310,7 +310,7 @@ public function test_index_endpoint_filter_only_full_dates_returns_time_entries_ { // Arrange $now = Carbon::create(2024, 1, 1, 12, 0, 0, 'Europe/Vienna'); - $this->freezeTime($now); + $this->travelTo($now); $data = $this->createUserWithPermission([ 'time-entries:view:own', ]); diff --git a/tests/Unit/Service/BillableRateServiceTest.php b/tests/Unit/Service/BillableRateServiceTest.php index 90bdc98e..cd6a0b7e 100644 --- a/tests/Unit/Service/BillableRateServiceTest.php +++ b/tests/Unit/Service/BillableRateServiceTest.php @@ -25,7 +25,7 @@ class BillableRateServiceTest extends TestCaseWithDatabase private BillableRateService $billableRateService; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->billableRateService = app(BillableRateService::class); diff --git a/tests/Unit/Service/DashboardServiceTest.php b/tests/Unit/Service/DashboardServiceTest.php index 2fdb808c..56f94325 100644 --- a/tests/Unit/Service/DashboardServiceTest.php +++ b/tests/Unit/Service/DashboardServiceTest.php @@ -27,7 +27,7 @@ class DashboardServiceTest extends TestCase protected DashboardService $dashboardService; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->dashboardService = app(DashboardService::class); diff --git a/tests/Unit/Service/DeletionServiceTest.php b/tests/Unit/Service/DeletionServiceTest.php index 929636e1..05bdf4e3 100644 --- a/tests/Unit/Service/DeletionServiceTest.php +++ b/tests/Unit/Service/DeletionServiceTest.php @@ -12,6 +12,7 @@ use App\Models\Organization; use App\Models\Project; use App\Models\ProjectMember; +use App\Models\Report; use App\Models\Tag; use App\Models\Task; use App\Models\TimeEntry; @@ -55,7 +56,8 @@ protected function setUp(): void * members: Collection, * tasks: Collection, * timeEntries: Collection, - * owner: User + * owner: User, + * reports: Collection * } */ private function createOrganizationWithAllRelations(): object @@ -96,6 +98,10 @@ private function createOrganizationWithAllRelations(): object $task2 = Task::factory()->forProject($projectWithoutClient)->forOrganization($organization)->create(); $tasks = collect([$task1, $task2]); + $report1 = Report::factory()->forOrganization($organization)->create(); + $report2 = Report::factory()->forOrganization($organization)->create(); + $reports = collect([$report1, $report2]); + $timeEntries = TimeEntry::factory()->forOrganization($organization)->forMember($memberOwner)->createMany(2); $timeEntriesWithTask = TimeEntry::factory()->forTask($task1)->forOrganization($organization)->forMember($memberEmployee)->createMany(2); $timeEntriesWithProject = TimeEntry::factory()->forProject($projectWithClient)->forOrganization($organization)->forMember($memberPlaceholder)->createMany(2); @@ -111,6 +117,7 @@ private function createOrganizationWithAllRelations(): object 'tasks' => $tasks, 'timeEntries' => $timeEntries, 'owner' => $userOwner, + 'reports' => $reports, ]; } @@ -126,6 +133,7 @@ private function assertOrganizationDeleted(Organization $organization): void $this->assertSame(0, Tag::query()->whereBelongsTo($organization, 'organization')->count()); $this->assertSame(0, Member::query()->whereBelongsTo($organization, 'organization')->count()); $this->assertSame(0, Task::query()->whereBelongsTo($organization, 'organization')->count()); + $this->assertSame(0, Report::query()->whereBelongsTo($organization, 'organization')->count()); $this->assertSame(0, TimeEntry::query()->whereBelongsTo($organization, 'organization')->count()); } @@ -138,6 +146,7 @@ private function assertOrganizationNothingDeleted(Organization $organization, bo $this->assertSame(2, Tag::query()->whereBelongsTo($organization, 'organization')->count()); $this->assertSame(3, Member::query()->whereBelongsTo($organization, 'organization')->count()); $this->assertSame(2, Task::query()->whereBelongsTo($organization, 'organization')->count()); + $this->assertSame(2, Report::query()->whereBelongsTo($organization, 'organization')->count()); $this->assertSame($specialCase ? 7 : 6, TimeEntry::query()->whereBelongsTo($organization, 'organization')->count()); }