diff --git a/composer.json b/composer.json index 44dc10c6ce..a3a6394c4c 100644 --- a/composer.json +++ b/composer.json @@ -69,6 +69,10 @@ } }, "scripts": { + "cs": [ + "pint", + "npm run prettier" + ], "pint": "pint", "test:pest": "pest --parallel", "test:phpstan": "phpstan analyse", diff --git a/packages/actions/.stubs.php b/packages/actions/.stubs.php index 7fb9f8e8d9..44cd38d9fe 100644 --- a/packages/actions/.stubs.php +++ b/packages/actions/.stubs.php @@ -1,6 +1,6 @@ class(['block h-9 text-sm w-full rounded-lg border-gray-300 py-1 text-gray-900 shadow-sm outline-none transition duration-75 invalid:text-gray-400 focus:border-primary-500 focus:ring-1 focus:ring-inset focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:focus:border-primary-500']) }} + {{ $attributes->class(['block h-9 w-full rounded-lg border-gray-300 py-1 text-sm text-gray-900 shadow-sm outline-none transition duration-75 invalid:text-gray-400 focus:border-primary-500 focus:ring-1 focus:ring-inset focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:focus:border-primary-500']) }} > @if (($placeholder = $getPlaceholder()) !== null) diff --git a/packages/actions/src/ActionsServiceProvider.php b/packages/actions/src/ActionsServiceProvider.php index 7a306d354d..2e4d68109e 100644 --- a/packages/actions/src/ActionsServiceProvider.php +++ b/packages/actions/src/ActionsServiceProvider.php @@ -3,7 +3,7 @@ namespace Filament\Actions; use Filament\Actions\Testing\TestsActions; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; diff --git a/packages/actions/src/Concerns/InteractsWithActions.php b/packages/actions/src/Concerns/InteractsWithActions.php index 0edeb1a2a1..a7ac92e7c8 100644 --- a/packages/actions/src/Concerns/InteractsWithActions.php +++ b/packages/actions/src/Concerns/InteractsWithActions.php @@ -6,7 +6,6 @@ use Closure; use Filament\Actions\Action; use Filament\Forms; use Filament\Forms\Form; -use Filament\Support\Contracts\TranslatableContentDriver; use Filament\Support\Exceptions\Cancel; use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Model; diff --git a/packages/actions/src/Contracts/HasActions.php b/packages/actions/src/Contracts/HasActions.php index d012aa416b..859c209523 100644 --- a/packages/actions/src/Contracts/HasActions.php +++ b/packages/actions/src/Contracts/HasActions.php @@ -3,7 +3,6 @@ namespace Filament\Actions\Contracts; use Filament\Actions\Action; -use Filament\Forms\Contracts\HasForms; use Filament\Support\Contracts\TranslatableContentDriver; interface HasActions diff --git a/packages/actions/src/CreateAction.php b/packages/actions/src/CreateAction.php index 46588db42d..b68b4b4b92 100644 --- a/packages/actions/src/CreateAction.php +++ b/packages/actions/src/CreateAction.php @@ -6,7 +6,9 @@ use Closure; use Filament\Actions\Concerns\CanCustomizeProcess; use Filament\Actions\Contracts\HasActions; use Filament\Forms\Form; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\Relation; class CreateAction extends Action { @@ -14,6 +16,8 @@ class CreateAction extends Action protected bool | Closure $canCreateAnother = true; + protected ?Closure $getRelationshipUsing = null; + public static function getDefaultName(): ?string { return 'create'; @@ -51,6 +55,13 @@ class CreateAction extends Action $record->fill($data); } + if ($relationship = $this->getRelationship()) { + /** @phpstan-ignore-next-line */ + $relationship->save($record); + + return $record; + } + $record->save(); return $record; @@ -79,6 +90,13 @@ class CreateAction extends Action }); } + public function relationship(?Closure $relationship): static + { + $this->getRelationshipUsing = $relationship; + + return $this; + } + public function createAnother(bool | Closure $condition = true): static { $this->canCreateAnother = $condition; @@ -105,4 +123,9 @@ class CreateAction extends Action { return true; } + + public function getRelationship(): Relation | Builder | null + { + return $this->evaluate($this->getRelationshipUsing); + } } diff --git a/packages/actions/src/SelectAction.php b/packages/actions/src/SelectAction.php index b3672c959c..502780ac77 100644 --- a/packages/actions/src/SelectAction.php +++ b/packages/actions/src/SelectAction.php @@ -2,11 +2,6 @@ namespace Filament\Actions; -use Closure; -use Filament\Support\Contracts\HasLabel as LabelInterface; -use Illuminate\Contracts\Support\Arrayable; -use Illuminate\Support\Collection; - class SelectAction extends Action { use Concerns\HasSelect; diff --git a/packages/actions/src/Testing/TestsActions.php b/packages/actions/src/Testing/TestsActions.php index 08cef848b3..3f898d25a7 100644 --- a/packages/actions/src/Testing/TestsActions.php +++ b/packages/actions/src/Testing/TestsActions.php @@ -11,7 +11,7 @@ use Filament\Actions\MountableAction; use Filament\Actions\StaticAction; use Illuminate\Support\Arr; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; use function Livewire\store; /** diff --git a/packages/forms/.stubs.php b/packages/forms/.stubs.php index 5cead185f9..59296c17a8 100644 --- a/packages/forms/.stubs.php +++ b/packages/forms/.stubs.php @@ -2,7 +2,7 @@ use Closure; -namespace Livewire\Features\SupportUnitTesting\Tests { +namespace Livewire\Features\SupportTesting\Tests { class Testable { public function fillForm(array $state = [], string $formName = 'form'): static {} diff --git a/packages/forms/resources/js/components/color-picker.js b/packages/forms/resources/js/components/color-picker.js index 9c90cdfaea..1e1454006c 100644 --- a/packages/forms/resources/js/components/color-picker.js +++ b/packages/forms/resources/js/components/color-picker.js @@ -31,12 +31,15 @@ export default function colorPickerFormComponent({ if (isLiveOnPickerClose) { new MutationObserver(() => { - if (this.$refs.panel.style.display !== 'none'){ + if (this.$refs.panel.style.display !== 'none') { return } this.$wire.call('$refresh') - }).observe(this.$refs.panel, { attributes: true, childList: true }) + }).observe(this.$refs.panel, { + attributes: true, + childList: true, + }) } }, diff --git a/packages/forms/resources/js/components/markdown-editor.js b/packages/forms/resources/js/components/markdown-editor.js index 644decfa9e..767cbc198e 100644 --- a/packages/forms/resources/js/components/markdown-editor.js +++ b/packages/forms/resources/js/components/markdown-editor.js @@ -175,9 +175,8 @@ export default function markdownEditorFormComponent({ ) if (isLiveOnBlur) { - this.editor.codemirror.on( - 'blur', - () => this.$wire.call('$refresh'), + this.editor.codemirror.on('blur', () => + this.$wire.call('$refresh'), ) } diff --git a/packages/forms/resources/js/components/rich-editor.js b/packages/forms/resources/js/components/rich-editor.js index c833d84fe6..a482872fed 100644 --- a/packages/forms/resources/js/components/rich-editor.js +++ b/packages/forms/resources/js/components/rich-editor.js @@ -49,9 +49,7 @@ Trix.LineBreakInsertion.prototype.shouldInsertBlockBreak = function () { } } -export default function richEditorFormComponent({ - state, -}) { +export default function richEditorFormComponent({ state }) { return { state, diff --git a/packages/forms/resources/views/components/affixes.blade.php b/packages/forms/resources/views/components/affixes.blade.php index aee944af53..fca3118a08 100644 --- a/packages/forms/resources/views/components/affixes.blade.php +++ b/packages/forms/resources/views/components/affixes.blade.php @@ -42,7 +42,7 @@ @if (filled($statePath)) x-bind:class="{ 'text-gray-400': ! (@js($statePath) in $wire.__instance.snapshot.memo.errors), - 'text-danger-400': (@js($statePath) in $wire.__instance.snapshot.memo.errors), + 'text-danger-400': @js($statePath) in $wire.__instance.snapshot.memo.errors, }" @endif > diff --git a/packages/forms/resources/views/components/date-time-picker.blade.php b/packages/forms/resources/views/components/date-time-picker.blade.php index 55e61f8254..2ec5f3a318 100644 --- a/packages/forms/resources/views/components/date-time-picker.blade.php +++ b/packages/forms/resources/views/components/date-time-picker.blade.php @@ -26,8 +26,10 @@ class(['filament-forms-markdown-editor-component font-mono']) }} > - + @else
beforeLast('s')) * 1000; } - return preg_replace("/[^0-9]/", '', $debounce) ?: 0; + return preg_replace('/[^0-9]/', '', $debounce) ?: 0; } } diff --git a/packages/forms/src/FormsServiceProvider.php b/packages/forms/src/FormsServiceProvider.php index 5ebabb80ec..7b5acd7e32 100644 --- a/packages/forms/src/FormsServiceProvider.php +++ b/packages/forms/src/FormsServiceProvider.php @@ -7,7 +7,7 @@ use Filament\Support\Assets\AlpineComponent; use Filament\Support\Assets\Js; use Filament\Support\Facades\FilamentAsset; use Illuminate\Filesystem\Filesystem; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; diff --git a/packages/forms/src/Testing/TestsForms.php b/packages/forms/src/Testing/TestsForms.php index 137bae244f..78d66ba3d8 100644 --- a/packages/forms/src/Testing/TestsForms.php +++ b/packages/forms/src/Testing/TestsForms.php @@ -9,7 +9,7 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Contracts\HasForms; use Illuminate\Support\Arr; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; /** * @method HasForms instance() diff --git a/packages/infolists/src/Contracts/HasInfolists.php b/packages/infolists/src/Contracts/HasInfolists.php index 837f48234b..432e4940f5 100644 --- a/packages/infolists/src/Contracts/HasInfolists.php +++ b/packages/infolists/src/Contracts/HasInfolists.php @@ -2,7 +2,6 @@ namespace Filament\Infolists\Contracts; -use Filament\Forms\Contracts\HasForms; use Filament\Infolists\Infolist; interface HasInfolists diff --git a/packages/notifications/.stubs.php b/packages/notifications/.stubs.php index f1663c1cc5..907a23f7fa 100644 --- a/packages/notifications/.stubs.php +++ b/packages/notifications/.stubs.php @@ -1,6 +1,6 @@ [ 'back' => [ - 'label' => 'back' + 'label' => 'back', ], ], diff --git a/packages/panels/resources/views/components/layouts/card.blade.php b/packages/panels/resources/views/components/layouts/card.blade.php index 15a09cce20..991408393b 100644 --- a/packages/panels/resources/views/components/layouts/card.blade.php +++ b/packages/panels/resources/views/components/layouts/card.blade.php @@ -4,7 +4,9 @@ 'subheading' => null, ]) -
+
@if (filled($heading ??= $this->getHeading())) -

+

{{ $heading }}

@endif @@ -64,7 +64,8 @@ class="absolute end-0 top-0 flex w-full items-center justify-end p-2" > @if (filament()->hasDatabaseNotifications()) - @livewire(Filament\Livewire\DatabaseNotifications::class, ['lazy' => true])) + @livewire(Filament\Livewire\DatabaseNotifications::class, ['lazy' => true]) + ) @endif diff --git a/packages/panels/resources/views/components/user-menu.blade.php b/packages/panels/resources/views/components/user-menu.blade.php index 964c0d6604..5ef5ded5b5 100644 --- a/packages/panels/resources/views/components/user-menu.blade.php +++ b/packages/panels/resources/views/components/user-menu.blade.php @@ -4,6 +4,7 @@ $profileItem = $items['profile'] ?? $items['account'] ?? null; $profileItemUrl = $profileItem?->getUrl(); + $profilePage = filament()->getProfilePage(); $hasProfile = filament()->hasProfile() || filled($profileItemUrl); $logoutItem = $items['logout'] ?? null; @@ -33,7 +34,7 @@ :href="$profileItemUrl ?? filament()->getProfileUrl()" tag="a" > - {{ $profileItem?->getLabel() ?? filament()->getProfilePage()::getLabel() ?? filament()->getUserName($user) }} + {{ $profileItem?->getLabel() ?? ($profilePage ? $profilePage::getLabel() : null) ?? filament()->getUserName($user) }} @else diff --git a/packages/panels/resources/views/resources/pages/view-record.blade.php b/packages/panels/resources/views/resources/pages/view-record.blade.php index cebcea5ae3..2c51ff8d33 100644 --- a/packages/panels/resources/views/resources/pages/view-record.blade.php +++ b/packages/panels/resources/views/resources/pages/view-record.blade.php @@ -13,7 +13,9 @@ @if ($this->hasInfolist()) {{ $this->infolist }} @else -
+
{{ $this->form }}
@endif diff --git a/packages/panels/src/GlobalSearch/Actions/Action.php b/packages/panels/src/GlobalSearch/Actions/Action.php index 280e7e0d16..b24a5a0cb3 100644 --- a/packages/panels/src/GlobalSearch/Actions/Action.php +++ b/packages/panels/src/GlobalSearch/Actions/Action.php @@ -2,7 +2,6 @@ namespace Filament\GlobalSearch\Actions; -use Filament\Actions\Concerns\CanDispatchEvent; use Filament\Actions\StaticAction; class Action extends StaticAction diff --git a/packages/panels/src/Pages/Auth/EditProfile.php b/packages/panels/src/Pages/Auth/EditProfile.php index f69031a367..2ddf383233 100644 --- a/packages/panels/src/Pages/Auth/EditProfile.php +++ b/packages/panels/src/Pages/Auth/EditProfile.php @@ -2,6 +2,7 @@ namespace Filament\Pages\Auth; +use Exception; use Filament\Actions\Action; use Filament\Actions\ActionGroup; use Filament\Facades\Filament; @@ -14,7 +15,8 @@ use Filament\Pages\CardPage; use Filament\Pages\Concerns; use Filament\Panel; use Filament\Support\Exceptions\Halt; -use Illuminate\Contracts\Auth\Authenticatable;use Illuminate\Contracts\Support\Htmlable; +use Illuminate\Contracts\Auth\Authenticatable; +use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Route; @@ -68,9 +70,15 @@ class EditProfile extends CardPage $this->fillForm(); } - public function getUser(): Authenticatable + public function getUser(): Authenticatable & Model { - return Filament::auth()->getUser(); + $user = Filament::auth()->user(); + + if (! $user instanceof Model) { + throw new Exception('The authenticated user object must be an Eloquent model to allow the profile page to update it.'); + } + + return $user; } protected function fillForm(): void diff --git a/packages/panels/src/Pages/Auth/Register.php b/packages/panels/src/Pages/Auth/Register.php index d37e78de8b..4c26c6a094 100644 --- a/packages/panels/src/Pages/Auth/Register.php +++ b/packages/panels/src/Pages/Auth/Register.php @@ -7,7 +7,6 @@ use DanHarrin\LivewireRateLimiting\WithRateLimiting; use Filament\Actions\Action; use Filament\Facades\Filament; use Filament\Forms\Components\Component; -use Filament\Forms\Components\Field; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Http\Responses\Auth\Contracts\RegistrationResponse; diff --git a/packages/panels/src/Pages/Tenancy/EditTenantProfile.php b/packages/panels/src/Pages/Tenancy/EditTenantProfile.php index 90a112899f..693201cb89 100644 --- a/packages/panels/src/Pages/Tenancy/EditTenantProfile.php +++ b/packages/panels/src/Pages/Tenancy/EditTenantProfile.php @@ -4,10 +4,10 @@ namespace Filament\Pages\Tenancy; use Filament\Actions\Action; use Filament\Actions\ActionGroup; +use function Filament\authorize; use Filament\Facades\Filament; use Filament\Forms\Form; use Filament\Notifications\Notification; -use Filament\Pages\CardPage; use Filament\Pages\Concerns; use Filament\Pages\Page; use Filament\Panel; @@ -17,7 +17,6 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Route; use Livewire\Attributes\Locked; -use function Filament\authorize; /** * @property Form $form @@ -37,6 +36,9 @@ abstract class EditTenantProfile extends Page */ public ?array $data = []; + /** + * @var ?Model + */ #[Locked] public $tenant = null; diff --git a/packages/panels/src/Resources/Pages/CreateRecord.php b/packages/panels/src/Resources/Pages/CreateRecord.php index 3f3ef6fd28..21a78ace99 100644 --- a/packages/panels/src/Resources/Pages/CreateRecord.php +++ b/packages/panels/src/Resources/Pages/CreateRecord.php @@ -2,7 +2,6 @@ namespace Filament\Resources\Pages; -use Exception; use Filament\Actions\Action; use Filament\Actions\ActionGroup; use Filament\Facades\Filament; @@ -102,7 +101,7 @@ class CreateRecord extends Page /** * @internal Never override or call this method. If you completely override `create()`, copy the contents of this method into your override. * - * @param array $data + * @param array $data */ protected function createRecordAndCallHooks(array $data): void { @@ -174,7 +173,7 @@ class CreateRecord extends Page $record = new ($this->getModel())($data); if ($tenant = Filament::getTenant()) { - $this->associateRecordWithTenant($record, $tenant); + return $this->associateRecordWithTenant($record, $tenant); } $record->save(); @@ -182,18 +181,9 @@ class CreateRecord extends Page return $record; } - protected function associateRecordWithTenant(Model $record, Model $tenant): void + protected function associateRecordWithTenant(Model $record, Model $tenant): Model { - $relationshipName = Filament::getTenantOwnershipRelationshipName(); - - if (! $record->isRelation($relationshipName)) { - $pageClass = static::class; - $recordClass = $record::class; - - throw new Exception("The model [{$recordClass}] does not have a relationship named [{$relationshipName}]. This relationship is required to associate the record with the tenant. You can change the relationship being used by passing it to the [ownershipRelationship] argument of the [tenant()] method in configuration. Alternatively, you can override the [associateRecordWithTenant()] method on the [{$pageClass}] class to associate the record with the tenant in a different way."); - } - - $record->{$relationshipName}()->associate($tenant); + return static::getResource()::getTenantRelationship($tenant)->save($record); } /** diff --git a/packages/panels/src/Resources/Pages/EditRecord.php b/packages/panels/src/Resources/Pages/EditRecord.php index b9c7b7ca08..a94c86606c 100644 --- a/packages/panels/src/Resources/Pages/EditRecord.php +++ b/packages/panels/src/Resources/Pages/EditRecord.php @@ -84,7 +84,7 @@ class EditRecord extends Page /** * @internal Never override or call this method. If you completely override `fillForm()`, copy the contents of this method into your override. * - * @param array $data + * @param array $data */ protected function fillFormWithDataAndCallHooks(array $data): void { diff --git a/packages/panels/src/Resources/Pages/ListRecords.php b/packages/panels/src/Resources/Pages/ListRecords.php index 6e4f0e57ca..d1530bf113 100644 --- a/packages/panels/src/Resources/Pages/ListRecords.php +++ b/packages/panels/src/Resources/Pages/ListRecords.php @@ -4,6 +4,7 @@ namespace Filament\Resources\Pages; use Filament\Actions\Action; use Filament\Actions\CreateAction; +use Filament\Facades\Filament; use Filament\Forms; use Filament\Forms\Form; use Filament\Infolists\Infolist; @@ -14,6 +15,7 @@ use Filament\Tables\Table; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Str; class ListRecords extends Page implements Forms\Contracts\HasForms, Tables\Contracts\HasTable @@ -97,7 +99,8 @@ class ListRecords extends Page implements Forms\Contracts\HasForms, Tables\Contr ->authorize($resource::canCreate()) ->model($this->getModel()) ->modelLabel($this->getModelLabel()) - ->form(fn (Form $form): Form => $this->form($form->columns(2))); + ->form(fn (Form $form): Form => $this->form($form->columns(2))) + ->relationship(($tenant = Filament::getTenant()) ? fn (): Relation => static::getResource()::getTenantRelationship($tenant) : null); if ($resource::hasPage('create')) { $action->url(fn (): string => $resource::getUrl('create')); @@ -221,6 +224,7 @@ class ListRecords extends Page implements Forms\Contracts\HasForms, Tables\Contr { return $this->makeBaseTable() ->query(fn (): Builder => $this->getTableQuery()) + ->relationship(($tenant = Filament::getTenant()) ? fn (): Relation => static::getResource()::getTenantRelationship($tenant) : null) ->modelLabel($this->getModelLabel() ?? static::getResource()::getModelLabel()) ->pluralModelLabel($this->getPluralModelLabel() ?? static::getResource()::getPluralModelLabel()) ->recordAction(function (Model $record, Table $table): ?string { diff --git a/packages/panels/src/Resources/Pages/ViewRecord.php b/packages/panels/src/Resources/Pages/ViewRecord.php index 0921b21aba..f7efa1a8bc 100644 --- a/packages/panels/src/Resources/Pages/ViewRecord.php +++ b/packages/panels/src/Resources/Pages/ViewRecord.php @@ -87,7 +87,7 @@ class ViewRecord extends Page implements HasInfolists /** * @internal Never override or call this method. If you completely override `fillForm()`, copy the contents of this method into your override. * - * @param array $data + * @param array $data */ protected function fillFormWithDataAndCallHooks(array $data): void { diff --git a/packages/panels/src/Resources/RelationManagers/RelationManager.php b/packages/panels/src/Resources/RelationManagers/RelationManager.php index 6f95b54964..e5a6755461 100644 --- a/packages/panels/src/Resources/RelationManagers/RelationManager.php +++ b/packages/panels/src/Resources/RelationManagers/RelationManager.php @@ -16,8 +16,8 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Str; -use Livewire\Component; use Livewire\Attributes\Locked; +use Livewire\Component; class RelationManager extends Component implements Forms\Contracts\HasForms, Tables\Contracts\HasTable { diff --git a/packages/panels/src/Resources/Resource.php b/packages/panels/src/Resources/Resource.php index 22c3697f94..f9f8437b5b 100644 --- a/packages/panels/src/Resources/Resource.php +++ b/packages/panels/src/Resources/Resource.php @@ -2,6 +2,7 @@ namespace Filament\Resources; +use Exception; use function Filament\authorize; use Filament\Facades\Filament; use Filament\Forms\Form; @@ -21,6 +22,8 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Route; @@ -74,6 +77,10 @@ abstract class Resource protected static ?string $slug = null; + protected static ?string $tenantOwnershipRelationshipName = null; + + protected static ?string $tenantRelationshipName = null; + /** * @var string | array */ @@ -299,9 +306,23 @@ abstract class Resource return $query; } - public static function scopeEloquentQueryToTenant(Builder $query, Model $tenant): Builder + public static function scopeEloquentQueryToTenant(Builder $query, ?Model $tenant): Builder { - return $query->whereBelongsTo($tenant); + $tenant ??= Filament::getTenant(); + + $tenantOwnershipRelationship = static::getTenantOwnershipRelationship($query->getModel()); + $tenantOwnershipRelationshipName = static::getTenantOwnershipRelationshipName(); + + return match (true) { + $tenantOwnershipRelationship instanceof BelongsTo => $query->whereBelongsTo( + $tenant, + $tenantOwnershipRelationshipName, + ), + default => $query->whereHas( + $tenantOwnershipRelationshipName, + fn (Builder $query) => $query->whereKey($tenant->getKey()), + ), + }; } /** @@ -708,4 +729,45 @@ abstract class Resource { return static::$isDiscovered; } + + public static function getTenantOwnershipRelationshipName(): string + { + return static::$tenantOwnershipRelationshipName ?? Filament::getTenantOwnershipRelationshipName(); + } + + public static function getTenantOwnershipRelationship(Model $record): Relation + { + $relationshipName = static::getTenantOwnershipRelationshipName(); + + if (! $record->isRelation($relationshipName)) { + $resourceClass = static::class; + $recordClass = $record::class; + + throw new Exception("The model [{$recordClass}] does not have a relationship named [{$relationshipName}]. You can change the relationship being used by passing it to the [ownershipRelationship] argument of the [tenant()] method in configuration. You can change the relationship being used per-resource by setting it as the [\$tenantOwnershipRelationshipName] static property on the [{$resourceClass}] resource class."); + } + + return $record->{$relationshipName}(); + } + + public static function getTenantRelationshipName(): string + { + return static::$tenantRelationshipName ?? (string) str(static::getModel()) + ->classBasename() + ->pluralStudly() + ->camel(); + } + + public static function getTenantRelationship(Model $tenant): Relation + { + $relationshipName = static::getTenantRelationshipName(); + + if (! $tenant->isRelation($relationshipName)) { + $resourceClass = static::class; + $tenantClass = $tenant::class; + + throw new Exception("The model [{$tenantClass}] does not have a relationship named [{$relationshipName}]. You can change the relationship being used by setting it as the [\$tenantRelationshipName] static property on the [{$resourceClass}] resource class."); + } + + return $tenant->{$relationshipName}(); + } } diff --git a/packages/panels/src/Widgets/Concerns/InteractsWithPageTable.php b/packages/panels/src/Widgets/Concerns/InteractsWithPageTable.php index fa11064dda..ef2a7dbd0a 100644 --- a/packages/panels/src/Widgets/Concerns/InteractsWithPageTable.php +++ b/packages/panels/src/Widgets/Concerns/InteractsWithPageTable.php @@ -7,9 +7,7 @@ use Filament\Tables\Contracts\HasTable; use Illuminate\Contracts\Pagination\Paginator; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Support\Arr; use Livewire\Attributes\Reactive; -use function Livewire\store; use function Livewire\trigger; trait InteractsWithPageTable diff --git a/packages/spatie-laravel-translatable-plugin/src/Actions/LocaleSwitcher.php b/packages/spatie-laravel-translatable-plugin/src/Actions/LocaleSwitcher.php index 052c3c6ad6..f2168049d6 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Actions/LocaleSwitcher.php +++ b/packages/spatie-laravel-translatable-plugin/src/Actions/LocaleSwitcher.php @@ -2,8 +2,6 @@ namespace Filament\Actions; -use Filament\SpatieLaravelTranslatablePlugin; - class LocaleSwitcher extends SelectAction { use Concerns\HasTranslatableLocaleOptions; diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php index 68c7a2584d..b011bebad1 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php @@ -2,8 +2,6 @@ namespace Filament\Resources\Pages\Concerns; -use Illuminate\Database\Eloquent\Model; - trait HasTranslatableFormWithExistingRecordData { protected function fillForm(): void diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php index cdfb6b4faf..08dc881b08 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php @@ -3,7 +3,6 @@ namespace Filament\Resources\Pages\CreateRecord\Concerns; use Filament\Resources\Concerns\HasActiveLocaleSwitcher; -use Filament\Resources\Pages\Concerns\HasTranslatableRecordTitle; use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php index ca11ea1775..cfc9c6b830 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php @@ -5,7 +5,6 @@ namespace Filament\Resources\Pages\EditRecord\Concerns; use Filament\Resources\Concerns\HasActiveLocaleSwitcher; use Filament\Resources\Pages\Concerns\HasTranslatableFormWithExistingRecordData; use Filament\Resources\Pages\Concerns\HasTranslatableRecord; -use Filament\Resources\Pages\Concerns\HasTranslatableRecordTitle; use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; @@ -77,6 +76,7 @@ trait Translatable $this->form->validate(); } catch (ValidationException $exception) { $this->activeLocale = $this->oldActiveLocale; + throw $exception; } diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php index c8cc2283e4..154906266f 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php @@ -3,11 +3,6 @@ namespace Filament\Resources\Pages\ListRecords\Concerns; use Filament\Resources\Concerns\HasActiveLocaleSwitcher; -use Filament\SpatieLaravelTranslatableContentDriver; -use Filament\Support\Contracts\TranslatableContentDriver; -use Illuminate\Contracts\Pagination\Paginator; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Model; trait Translatable { diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ManageRecords/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ManageRecords/Concerns/Translatable.php index b01dbaf8a0..3a2ff1d576 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ManageRecords/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ManageRecords/Concerns/Translatable.php @@ -2,13 +2,7 @@ namespace Filament\Resources\Pages\ManageRecords\Concerns; -use Filament\Resources\Concerns\HasActiveLocaleSwitcher; use Filament\Resources\Pages\ListRecords\Concerns\Translatable as ListRecordsTranslatable; -use Filament\SpatieLaravelTranslatableContentDriver; -use Filament\Support\Contracts\TranslatableContentDriver; -use Illuminate\Contracts\Pagination\Paginator; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Model; trait Translatable { diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php index f9829e4a31..ea558fadf1 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php @@ -5,9 +5,6 @@ namespace Filament\Resources\Pages\ViewRecord\Concerns; use Filament\Resources\Concerns\HasActiveLocaleSwitcher; use Filament\Resources\Pages\Concerns\HasTranslatableFormWithExistingRecordData; use Filament\Resources\Pages\Concerns\HasTranslatableRecord; -use Filament\Resources\Pages\Concerns\HasTranslatableRecordTitle; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Validation\ValidationException; trait Translatable { diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/RelationManagers/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/RelationManagers/Concerns/Translatable.php index f934e3659e..82d831af96 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/RelationManagers/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/RelationManagers/Concerns/Translatable.php @@ -3,11 +3,6 @@ namespace Filament\Resources\RelationManagers\Concerns; use Filament\Resources\Concerns\HasActiveLocaleSwitcher; -use Filament\SpatieLaravelTranslatableContentDriver; -use Filament\Support\Contracts\TranslatableContentDriver; -use Illuminate\Contracts\Pagination\Paginator; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Model; trait Translatable { diff --git a/packages/spatie-laravel-translatable-plugin/src/Tables/Actions/LocaleSwitcher.php b/packages/spatie-laravel-translatable-plugin/src/Tables/Actions/LocaleSwitcher.php index 6593aad4f7..04108389c0 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Tables/Actions/LocaleSwitcher.php +++ b/packages/spatie-laravel-translatable-plugin/src/Tables/Actions/LocaleSwitcher.php @@ -3,8 +3,6 @@ namespace Filament\Tables\Actions; use Filament\Actions\Concerns\HasTranslatableLocaleOptions; -use Filament\Tables\Actions\SelectAction; -use Filament\SpatieLaravelTranslatablePlugin; class LocaleSwitcher extends SelectAction { diff --git a/packages/tables/.stubs.php b/packages/tables/.stubs.php index d19f1253ca..3ce79e500a 100644 --- a/packages/tables/.stubs.php +++ b/packages/tables/.stubs.php @@ -1,6 +1,6 @@ { - succeed(({ snapshot, effect }) => { - if (component.id !== @js($this->getId())) { - return - } + Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => { + succeed(({ snapshot, effect }) => { + if (component.id !== @js($this->getId())) { + return + } - if (! $refs.newState) { - return - } + if (! $refs.newState) { + return + } - let newState = $refs.newState.value === '1' ? true : false + let newState = $refs.newState.value === '1' ? true : false - if (state === newState) { - return - } + if (state === newState) { + return + } - state = newState - }) - }, - ) + state = newState + }) + }) " {{ $attributes diff --git a/packages/tables/resources/views/columns/select-column.blade.php b/packages/tables/resources/views/columns/select-column.blade.php index 77293ab4d9..446c70e740 100644 --- a/packages/tables/resources/views/columns/select-column.blade.php +++ b/packages/tables/resources/views/columns/select-column.blade.php @@ -10,28 +10,25 @@ isLoading: false, }" x-init=" - Livewire.hook( - 'commit', - ({ component, commit, succeed, fail, respond }) => { - succeed(({ snapshot, effect }) => { - if (component.id !== @js($this->getId())) { - return - } + Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => { + succeed(({ snapshot, effect }) => { + if (component.id !== @js($this->getId())) { + return + } - if (! $refs.newState) { - return - } + if (! $refs.newState) { + return + } - let newState = $refs.newState.value + let newState = $refs.newState.value - if (state === newState) { - return - } + if (state === newState) { + return + } - state = newState - }) - }, - ) + state = newState + }) + }) " {{ $attributes diff --git a/packages/tables/resources/views/columns/text-input-column.blade.php b/packages/tables/resources/views/columns/text-input-column.blade.php index 3195f1ba35..890d3b34b0 100644 --- a/packages/tables/resources/views/columns/text-input-column.blade.php +++ b/packages/tables/resources/views/columns/text-input-column.blade.php @@ -11,32 +11,29 @@ isEditing: false, }" x-init=" - Livewire.hook( - 'commit', - ({ component, commit, succeed, fail, respond }) => { - succeed(({ snapshot, effect }) => { - if (component.id !== @js($this->getId())) { - return - } + Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => { + succeed(({ snapshot, effect }) => { + if (component.id !== @js($this->getId())) { + return + } - if (isEditing) { - return - } + if (isEditing) { + return + } - if (! $refs.newState) { - return - } + if (! $refs.newState) { + return + } - let newState = $refs.newState.value + let newState = $refs.newState.value - if (state === newState) { - return - } + if (state === newState) { + return + } - state = newState - }) - }, - ) + state = newState + }) + }) " {{ $attributes diff --git a/packages/tables/resources/views/index.blade.php b/packages/tables/resources/views/index.blade.php index 3b87ff45b2..ecd62b0430 100644 --- a/packages/tables/resources/views/index.blade.php +++ b/packages/tables/resources/views/index.blade.php @@ -119,7 +119,9 @@ shouldCheckUniqueSelection: true, init: function () { - $el.addEventListener('deselectAllTableRecords', () => this.deselectAllRecords()) + $el.addEventListener('deselectAllTableRecords', () => + this.deselectAllRecords(), + ) $watch('selectedRecords', () => { if (! this.shouldCheckUniqueSelection) { diff --git a/packages/tables/src/Actions/Contracts/HasTable.php b/packages/tables/src/Actions/Contracts/HasTable.php index 8f88dfc623..fe682af4f3 100644 --- a/packages/tables/src/Actions/Contracts/HasTable.php +++ b/packages/tables/src/Actions/Contracts/HasTable.php @@ -2,7 +2,6 @@ namespace Filament\Tables\Actions\Contracts; -use Filament\Support\Contracts\TranslatableContentDriver; use Filament\Tables\Table; interface HasTable diff --git a/packages/tables/src/Actions/SelectAction.php b/packages/tables/src/Actions/SelectAction.php index bce0c87dce..70169433e3 100644 --- a/packages/tables/src/Actions/SelectAction.php +++ b/packages/tables/src/Actions/SelectAction.php @@ -2,12 +2,7 @@ namespace Filament\Tables\Actions; -use Closure; -use Filament\Tables\Actions\Action; use Filament\Actions\Concerns; -use Filament\Support\Contracts\HasLabel as LabelInterface; -use Illuminate\Contracts\Support\Arrayable; -use Illuminate\Support\Collection; class SelectAction extends Action { diff --git a/packages/tables/src/Concerns/InteractsWithTable.php b/packages/tables/src/Concerns/InteractsWithTable.php index c06eb20e42..94125f70d0 100644 --- a/packages/tables/src/Concerns/InteractsWithTable.php +++ b/packages/tables/src/Concerns/InteractsWithTable.php @@ -4,14 +4,12 @@ namespace Filament\Tables\Concerns; use Closure; use Filament\Forms; -use Filament\Support\Contracts\TranslatableContentDriver; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\BulkAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; -use Livewire\Features\SupportPagination\HandlesPagination; use Livewire\WithPagination; trait InteractsWithTable diff --git a/packages/tables/src/Contracts/HasTable.php b/packages/tables/src/Contracts/HasTable.php index 7b1befc952..5c23dff9af 100644 --- a/packages/tables/src/Contracts/HasTable.php +++ b/packages/tables/src/Contracts/HasTable.php @@ -2,7 +2,6 @@ namespace Filament\Tables\Contracts; -use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; use Filament\Support\Contracts\TranslatableContentDriver; use Filament\Tables\Actions\Action; diff --git a/packages/tables/src/TablesServiceProvider.php b/packages/tables/src/TablesServiceProvider.php index abac8ab706..1bf48b161f 100644 --- a/packages/tables/src/TablesServiceProvider.php +++ b/packages/tables/src/TablesServiceProvider.php @@ -11,7 +11,7 @@ use Filament\Tables\Testing\TestsFilters; use Filament\Tables\Testing\TestsRecords; use Filament\Tables\Testing\TestsSummaries; use Illuminate\Filesystem\Filesystem; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; diff --git a/packages/tables/src/Testing/TestsActions.php b/packages/tables/src/Testing/TestsActions.php index bb1e644780..d4be7b0469 100644 --- a/packages/tables/src/Testing/TestsActions.php +++ b/packages/tables/src/Testing/TestsActions.php @@ -9,7 +9,7 @@ use Filament\Tables\Contracts\HasTable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; use function Livewire\store; /** diff --git a/packages/tables/src/Testing/TestsBulkActions.php b/packages/tables/src/Testing/TestsBulkActions.php index 504ef10b83..7f95d91df6 100644 --- a/packages/tables/src/Testing/TestsBulkActions.php +++ b/packages/tables/src/Testing/TestsBulkActions.php @@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; use function Livewire\store; /** diff --git a/packages/tables/src/Testing/TestsColumns.php b/packages/tables/src/Testing/TestsColumns.php index 66f2d5cf22..c692bdc3dc 100644 --- a/packages/tables/src/Testing/TestsColumns.php +++ b/packages/tables/src/Testing/TestsColumns.php @@ -7,7 +7,7 @@ use Filament\Tables\Columns\Column; use Filament\Tables\Contracts\HasTable; use Illuminate\Database\Eloquent\Model; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; /** * @method HasTable instance() diff --git a/packages/tables/src/Testing/TestsFilters.php b/packages/tables/src/Testing/TestsFilters.php index 62231069a5..768899e039 100644 --- a/packages/tables/src/Testing/TestsFilters.php +++ b/packages/tables/src/Testing/TestsFilters.php @@ -10,7 +10,7 @@ use Filament\Tables\Filters\TernaryFilter; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; /** * @method HasTable instance() diff --git a/packages/tables/src/Testing/TestsRecords.php b/packages/tables/src/Testing/TestsRecords.php index 91ebc3cfca..0cff006dd9 100644 --- a/packages/tables/src/Testing/TestsRecords.php +++ b/packages/tables/src/Testing/TestsRecords.php @@ -7,7 +7,7 @@ use Filament\Tables\Contracts\HasTable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; /** * @method HasTable instance() diff --git a/packages/tables/src/Testing/TestsSummaries.php b/packages/tables/src/Testing/TestsSummaries.php index 6d5a9d887d..27cdc9b4a0 100644 --- a/packages/tables/src/Testing/TestsSummaries.php +++ b/packages/tables/src/Testing/TestsSummaries.php @@ -6,7 +6,7 @@ use Closure; use Filament\Tables\Columns\Summarizers\Summarizer; use Filament\Tables\Contracts\HasTable; use Illuminate\Testing\Assert; -use Livewire\Features\SupportUnitTesting\Testable; +use Livewire\Features\SupportTesting\Testable; /** * @method HasTable instance() diff --git a/tests/src/Panels/Auth/PasswordReset/RequestPasswordResetTest.php b/tests/src/Panels/Auth/PasswordReset/RequestPasswordResetTest.php index 85409f14cb..fef0ab6183 100644 --- a/tests/src/Panels/Auth/PasswordReset/RequestPasswordResetTest.php +++ b/tests/src/Panels/Auth/PasswordReset/RequestPasswordResetTest.php @@ -23,7 +23,9 @@ it('can request password reset', function () { $userToResetPassword = User::factory()->create(); livewire(RequestPasswordReset::class) - ->set('email', $userToResetPassword->email) + ->fillForm([ + 'email' => $userToResetPassword->email, + ]) ->call('request') ->assertNotified(); @@ -39,7 +41,9 @@ it('can throttle requests', function () { $userToResetPassword = User::factory()->create(); livewire(RequestPasswordReset::class) - ->set('email', $userToResetPassword->email) + ->fillForm([ + 'email' => $userToResetPassword->email, + ]) ->call('request') ->assertNotified(); @@ -49,7 +53,9 @@ it('can throttle requests', function () { $userToResetPassword = User::factory()->create(); livewire(RequestPasswordReset::class) - ->set('email', $userToResetPassword->email) + ->fillForm([ + 'email' => $userToResetPassword->email, + ]) ->call('request') ->assertNotified(); @@ -58,14 +64,18 @@ it('can throttle requests', function () { it('can validate `email` is required', function () { livewire(RequestPasswordReset::class) - ->set('email', '') + ->fillForm([ + 'email' => '', + ]) ->call('request') - ->assertHasErrors(['email' => ['required']]); + ->assertHasFormErrors(['email' => ['required']]); }); it('can validate `email` is valid email', function () { livewire(RequestPasswordReset::class) - ->set('email', 'invalid-email') + ->fillForm([ + 'email' => 'invalid-email', + ]) ->call('request') - ->assertHasErrors(['email' => ['email']]); + ->assertHasFormErrors(['email' => ['email']]); });