From 761be97f14a0da37bb9f67c5f226b1a623c61746 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:29:22 +0800 Subject: [PATCH 01/26] Display product variants' option values using flex-col (#1890) --- .../product-resource/widgets/product-options.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/admin/resources/views/resources/product-resource/widgets/product-options.blade.php b/packages/admin/resources/views/resources/product-resource/widgets/product-options.blade.php index c5e1c1db15..4d33260c27 100644 --- a/packages/admin/resources/views/resources/product-resource/widgets/product-options.blade.php +++ b/packages/admin/resources/views/resources/product-resource/widgets/product-options.blade.php @@ -122,7 +122,7 @@ @endif
- + @foreach($permutation['values'] as $option => $value) {{ $option }}: {{ $value }} @endforeach From d20f0937b357cb4bfca094cd2b0eb7593e031c0f Mon Sep 17 00:00:00 2001 From: Ryan McAllen Date: Mon, 12 Aug 2024 06:47:21 -0400 Subject: [PATCH 02/26] Comments: orders -> order's (#1865) --- packages/core/config/orders.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/config/orders.php b/packages/core/config/orders.php index ba9d9b5d07..7e522cc9f8 100644 --- a/packages/core/config/orders.php +++ b/packages/core/config/orders.php @@ -67,7 +67,7 @@ | Order Pipelines |-------------------------------------------------------------------------- | - | Define which pipelines should be run throughout an orders lifecycle. + | Define which pipelines should be run throughout an order's lifecycle. | The default ones provided should suit most needs, however you are | free to add your own as you see fit. | From fbfcf85fd691f3ee41bde8b71a84a16c0bf94a1d Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Mon, 12 Aug 2024 12:40:36 +0100 Subject: [PATCH 03/26] Fix test runners (#1898) --- .../Resources/StaffResource/Pages/EditStaffTest.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/admin/Feature/Filament/Resources/StaffResource/Pages/EditStaffTest.php b/tests/admin/Feature/Filament/Resources/StaffResource/Pages/EditStaffTest.php index f212ee5526..59c5c0df3d 100644 --- a/tests/admin/Feature/Filament/Resources/StaffResource/Pages/EditStaffTest.php +++ b/tests/admin/Feature/Filament/Resources/StaffResource/Pages/EditStaffTest.php @@ -75,13 +75,10 @@ ->assertHasNoFormErrors(); expect($staff->hasExactRoles($roles)) - ->toBeTrue(); - - // check assigned permissions does not include role's permissions - expect($permissions->reject(fn ($val, $handle) => $handle == $rolePermission)->toArray()) - ->toEqualCanonicalizing($staff->getDirectPermissions()->pluck('name')->toArray()); - - // check role's permission - expect($rolePermission) + ->toBeTrue() + ->and( + $permissions->reject(fn ($val, $handle) => $handle == $rolePermission)->keys()->toArray() + )->toEqualCanonicalizing($staff->getDirectPermissions()->pluck('name')->toArray()) + ->and($rolePermission) ->toEqualCanonicalizing($staff->getPermissionsViaRoles()->pluck('name')->toArray()); }); From 6e0fffa4e9bd6f2cc1f4ab62f76a11af4adf2809 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:07:52 +0800 Subject: [PATCH 04/26] Do not register Shipping addon resources if disabed (#1891) --- packages/table-rate-shipping/src/ShippingPlugin.php | 4 ++++ packages/table-rate-shipping/src/ShippingServiceProvider.php | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/table-rate-shipping/src/ShippingPlugin.php b/packages/table-rate-shipping/src/ShippingPlugin.php index 6ffd06719a..c81cc1371b 100644 --- a/packages/table-rate-shipping/src/ShippingPlugin.php +++ b/packages/table-rate-shipping/src/ShippingPlugin.php @@ -24,6 +24,10 @@ public function boot(Panel $panel): void public function register(Panel $panel): void { + if (! config('lunar.shipping-tables.enabled')) { + return; + } + $panel->navigationGroups([ NavigationGroup::make('shipping') ->label( diff --git a/packages/table-rate-shipping/src/ShippingServiceProvider.php b/packages/table-rate-shipping/src/ShippingServiceProvider.php index 384e3ac33c..246c9c663b 100644 --- a/packages/table-rate-shipping/src/ShippingServiceProvider.php +++ b/packages/table-rate-shipping/src/ShippingServiceProvider.php @@ -14,10 +14,13 @@ class ShippingServiceProvider extends ServiceProvider { - public function boot(ShippingModifiers $shippingModifiers) + public function register() { $this->mergeConfigFrom(__DIR__.'/../config/shipping-tables.php', 'lunar.shipping-tables'); + } + public function boot(ShippingModifiers $shippingModifiers) + { if (! config('lunar.shipping-tables.enabled')) { return; } From be449b047d663e21aaf0b6d499b46cff47f0eaed Mon Sep 17 00:00:00 2001 From: alecritson Date: Mon, 12 Aug 2024 13:10:27 +0000 Subject: [PATCH 05/26] chore: fix code style --- packages/table-rate-shipping/src/ShippingPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/table-rate-shipping/src/ShippingPlugin.php b/packages/table-rate-shipping/src/ShippingPlugin.php index c81cc1371b..671672eeef 100644 --- a/packages/table-rate-shipping/src/ShippingPlugin.php +++ b/packages/table-rate-shipping/src/ShippingPlugin.php @@ -27,7 +27,7 @@ public function register(Panel $panel): void if (! config('lunar.shipping-tables.enabled')) { return; } - + $panel->navigationGroups([ NavigationGroup::make('shipping') ->label( From 3759324fc3eb4e608313be51895c2ca4320d6c26 Mon Sep 17 00:00:00 2001 From: Justin Scott Date: Tue, 13 Aug 2024 04:56:34 -0500 Subject: [PATCH 06/26] Fixes postgres compatibility on database state `PopulateProductOptionLabelWithName` updater (#1852) fixes #1849 so that Lunar can be upgraded without issue using PostgreSQL. This has only been manually testing against Postgres 15. The intent of the original version was, no doubt, to be more robust than a simple null check. However the case of a non-valid, non-null value existing in the product_options.label seems to be beyond the scope of a simple script meant to backfill new columns with default data. Implementing a check for an empty object or non-object value is tricky without writting different checks for each DB engines. --- .../database/state/PopulateProductOptionLabelWithName.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core/database/state/PopulateProductOptionLabelWithName.php b/packages/core/database/state/PopulateProductOptionLabelWithName.php index 19d7cb1b8f..3fe46468b5 100644 --- a/packages/core/database/state/PopulateProductOptionLabelWithName.php +++ b/packages/core/database/state/PopulateProductOptionLabelWithName.php @@ -20,8 +20,7 @@ public function run() } DB::transaction(function () { - ProductOption::where('label', '') - ->orWhereNull('label') + ProductOption::whereNull('label') ->update([ 'label' => DB::raw('name'), ]); @@ -37,6 +36,6 @@ protected function canRun() protected function shouldRun() { - return ProductOption::whereJsonLength('label', 0)->count() > 0; + return ProductOption::whereNull('label')->count() > 0; } } From f133eea76d8808008ba33a4d1308bc227d4ef906 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Tue, 13 Aug 2024 14:07:34 +0100 Subject: [PATCH 07/26] Fix tests for Filament panel (#1900) --- .../ProductResource/Widgets/CollectionTreeViewTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php b/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php index e85a76ddf2..f90d523b99 100644 --- a/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php +++ b/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php @@ -111,8 +111,7 @@ ], ['id' => $collection->id]) ->assertCount('nodes', 1) ->assertSet('nodes.0.children.0.id', $child->id) - ->mountAction('makeRoot', ['id' => $child->id]) - ->callAction('makeRoot') + ->callAction('makeRoot', arguments: ['id' => $child->id]) ->assertCount('nodes.0.children', 0) ->assertCount('nodes', 2); }); From f2d6f51a1aa9399e186f29add9de22ef71a35ec4 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Tue, 13 Aug 2024 14:36:23 +0100 Subject: [PATCH 08/26] Add Postgres support for query sorting (#1899) --- .../src/Support/Pages/BaseListRecords.php | 2 +- .../src/Support/Resources/BaseResource.php | 2 +- packages/core/src/LunarServiceProvider.php | 31 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/admin/src/Support/Pages/BaseListRecords.php b/packages/admin/src/Support/Pages/BaseListRecords.php index dadf83c846..7c7432543b 100644 --- a/packages/admin/src/Support/Pages/BaseListRecords.php +++ b/packages/admin/src/Support/Pages/BaseListRecords.php @@ -45,7 +45,7 @@ protected function applySearchToTableQuery(Builder $query): Builder $query->when( ! $ids->isEmpty(), - fn ($query) => $query->orderByRaw("field(id, {$placeholders})", $ids->toArray()) // TODO: Only supports MySQL + fn ($query) => $query->orderBySequence($ids->toArray()) ); } diff --git a/packages/admin/src/Support/Resources/BaseResource.php b/packages/admin/src/Support/Resources/BaseResource.php index 68657d7b71..845642e2b8 100644 --- a/packages/admin/src/Support/Resources/BaseResource.php +++ b/packages/admin/src/Support/Resources/BaseResource.php @@ -76,7 +76,7 @@ protected static function applyGlobalSearchAttributeConstraints(Builder $query, $query->when( ! $ids->isEmpty(), - fn ($query) => $query->orderByRaw("field(id, {$placeholders})", $ids->toArray()) + fn ($query) => $query->orderBySequence($ids->toArray()) ); } else { diff --git a/packages/core/src/LunarServiceProvider.php b/packages/core/src/LunarServiceProvider.php index ced1c4b454..aa593e2d22 100644 --- a/packages/core/src/LunarServiceProvider.php +++ b/packages/core/src/LunarServiceProvider.php @@ -6,6 +6,7 @@ use Illuminate\Auth\Events\Login; use Illuminate\Auth\Events\Logout; use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Events\MigrationsEnded; use Illuminate\Database\Events\MigrationsStarted; use Illuminate\Database\Events\NoPendingMigrations; @@ -190,6 +191,7 @@ public function boot(): void } $this->registerObservers(); + $this->registerBuilderMacros(); $this->registerBlueprintMacros(); $this->registerStateListeners(); @@ -309,6 +311,35 @@ protected function registerObservers(): void } } + protected function registerBuilderMacros(): void + { + Builder::macro('orderBySequence', function (array $ids) { + /** @var Builder $this */ + $driver = $this->getConnection()->getDriverName(); + + if (empty($ids)) { + return $this; + } + + if ($driver === 'mysql') { + $placeholders = implode(',', array_fill(0, count($ids), '?')); + + return $this->orderByRaw("FIELD(id, {$placeholders})", $ids); + } + + if ($driver === 'pgsql') { + $orderCases = ''; + foreach ($ids as $index => $id) { + $orderCases .= "WHEN id = $id THEN $index "; + } + + return $this->orderByRaw("CASE $orderCases ELSE ".count($ids).' END'); + } + + return $this; + }); + } + /** * Register the blueprint macros. */ From 840e88c310a7228d2ff1168080473de9cbed0593 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:27:56 +0800 Subject: [PATCH 09/26] Check product option has values associated before attempting to map (#1887) --- .../ProductResource/Widgets/ProductOptionsWidget.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/admin/src/Filament/Resources/ProductResource/Widgets/ProductOptionsWidget.php b/packages/admin/src/Filament/Resources/ProductResource/Widgets/ProductOptionsWidget.php index 088a96ee1f..a082be186d 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Widgets/ProductOptionsWidget.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Widgets/ProductOptionsWidget.php @@ -105,7 +105,7 @@ public function configureBaseOptions(): void $options = []; foreach ($productOptions as $productOption) { - $values = $productOption->values->map(function ($value) { + $values = $productOption->values->count() ? $productOption->values->map(function ($value) { return $this->mapOptionValue($value, true); })->merge( $disabledSharedOptionValues->filter( @@ -113,7 +113,7 @@ public function configureBaseOptions(): void )->map( fn ($value) => $this->mapOptionValue($value, false) ) - )->sortBy('position')->values()->toArray(); + )->sortBy('position')->values()->toArray() : []; $options[] = $this->mapOption($productOption, $values); } From d5d480a11085b361ccfa3afa79138f709414ea87 Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Wed, 14 Aug 2024 09:34:13 +0200 Subject: [PATCH 10/26] Check if record exists on attribute component when fetching product type (#1884) --- packages/admin/src/Support/Forms/Components/Attributes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/admin/src/Support/Forms/Components/Attributes.php b/packages/admin/src/Support/Forms/Components/Attributes.php index 1ea605743d..ba2fd4beee 100644 --- a/packages/admin/src/Support/Forms/Components/Attributes.php +++ b/packages/admin/src/Support/Forms/Components/Attributes.php @@ -40,7 +40,7 @@ protected function setUp(): void } if ($modelClass == ProductVariant::class) { - $productTypeId = $record->product?->product_type_id ?: ProductType::first()->id; + $productTypeId = $record?->product?->product_type_id ?: ProductType::first()->id; // If we have a product type, the attributes should be based off that. if ($productTypeId) { From a230b75a4cc468ea7f5c62e754efe2a25198e2a8 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 14 Aug 2024 09:38:58 +0100 Subject: [PATCH 11/26] Support discounts specifying fields in the discount UI (#1653) --- docs/core/extending/discounts.md | 49 +++++++++++++++++++ .../src/Base/LunarPanelDiscountInterface.php | 21 ++++++++ .../Filament/Resources/DiscountResource.php | 14 ++++++ .../DiscountResource/Pages/EditDiscount.php | 22 +++++++++ 4 files changed, 106 insertions(+) create mode 100644 packages/admin/src/Base/LunarPanelDiscountInterface.php diff --git a/docs/core/extending/discounts.md b/docs/core/extending/discounts.md index f23987d199..3e98b70239 100644 --- a/docs/core/extending/discounts.md +++ b/docs/core/extending/discounts.md @@ -1,3 +1,4 @@ + # Discounts ## Overview @@ -45,3 +46,51 @@ class MyCustomDiscountType extends AbstractDiscountType } } ``` + + +## Adding form fields for your discount in the admin panel + +If you require fields in the Lunar admin for your discount type, ensure your discount implements `Lunar\Admin\Base\LunarPanelDiscountInterface`. You will need to provide the `lunarPanelSchema`, `lunarPanelOnFill` and `lunarPanelOnSave` methods. + +```php +label('My label') + ->required(), + ]; + } + + /** + * Mutate the model data before displaying it in the admin form. + */ + public function lunarPanelOnFill(array $data): array + { + // optionally do something with $data + return $data; + } + + /** + * Mutate the form data before saving it to the discount model. + */ + public function lunarPanelOnSave(array $data): array + { + // optionally do something with $data + return $data; + } +} +``` diff --git a/packages/admin/src/Base/LunarPanelDiscountInterface.php b/packages/admin/src/Base/LunarPanelDiscountInterface.php new file mode 100644 index 0000000000..936950cdee --- /dev/null +++ b/packages/admin/src/Base/LunarPanelDiscountInterface.php @@ -0,0 +1,21 @@ +map(function ($discount) { + if (! $discount instanceof LunarPanelDiscountInterface) { + return; + } + + return Forms\Components\Section::make(Str::slug(get_class($discount))) + ->heading($discount->getName()) + ->visible( + fn (Forms\Get $get) => $get('type') == get_class($discount) + )->schema($discount->lunarPanelSchema()); + })->filter(); + return $form->schema([ Forms\Components\Section::make('')->schema( static::getMainFormComponents() @@ -84,6 +97,7 @@ public static function getDefaultForm(Form $form): Form )->schema( static::getAmountOffFormComponents() ), + ...$discountSchemas, ]); } diff --git a/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php b/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php index 754c8fe12b..6859259c9d 100644 --- a/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php +++ b/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\DiscountResource\Pages; use Filament\Actions; +use Lunar\Admin\Base\LunarPanelDiscountInterface; use Lunar\Admin\Filament\Resources\DiscountResource; use Lunar\Admin\Support\Pages\BaseEditRecord; use Lunar\DiscountTypes\BuyXGetY; @@ -19,8 +20,29 @@ protected function getDefaultHeaderActions(): array ]; } + protected function mutateFormDataBeforeFill(array $data): array + { + if (class_exists($data['type'])) { + $type = new $data['type']; + + if ($type instanceof LunarPanelDiscountInterface) { + return $type->lunarPanelOnFill($data); + } + } + + return $data; + } + protected function mutateFormDataBeforeSave(array $data): array { + if (class_exists($data['type'])) { + $type = new $data['type']; + + if ($type instanceof LunarPanelDiscountInterface) { + return $type->lunarPanelOnSave($data); + } + } + $minPrices = $data['data']['min_prices'] ?? []; $fixedPrices = $data['data']['fixed_values'] ?? []; $currencies = Currency::enabled()->get(); From d08b73a09d5bc2c3132bee8b5665a9331a6d4186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9as=20Lundgren?= <1066486+adevade@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:24:44 +0200 Subject: [PATCH 12/26] Link to Laravel Herd in Starter Kit docs (#1901) Adds a link to Laravel Herd in the tip on the starter kit page of the docs. --- docs/core/starter-kits.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/core/starter-kits.md b/docs/core/starter-kits.md index eb014636b7..ae47161065 100644 --- a/docs/core/starter-kits.md +++ b/docs/core/starter-kits.md @@ -22,8 +22,7 @@ If you would prefer to install Lunar into your own Laravel application, please f ## Installation ::: tip -We assume you have a suitable local development environment in which to run Lunar. We would highly suggest Laravel Herd -for this purpose. +We assume you have a suitable local development environment in which to run Lunar. We would highly suggest [Laravel Herd](https://herd.laravel.com) for this purpose. ::: ### Create a New Project From 5682f0ba95dbc0865d83748b2c59a44bad35b8ad Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Wed, 14 Aug 2024 11:25:00 +0100 Subject: [PATCH 13/26] Ensure cart is calculated (#1879) --- packages/core/src/Models/Cart.php | 8 ++- packages/stripe/src/StripePaymentType.php | 3 +- .../Cart/ValidateCartForOrderCreationTest.php | 32 ++++++++- tests/shipping/TestUtils.php | 10 +-- tests/shipping/Unit/ShippingModifierTest.php | 72 +++++++++++++++++++ tests/stripe/Unit/StripePaymentTypeTest.php | 10 ++- 6 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 tests/shipping/Unit/ShippingModifierTest.php diff --git a/packages/core/src/Models/Cart.php b/packages/core/src/Models/Cart.php index e8ebd35e46..b700ecce2a 100644 --- a/packages/core/src/Models/Cart.php +++ b/packages/core/src/Models/Cart.php @@ -572,7 +572,7 @@ public function setShippingOption(ShippingOption $option, bool $refresh = true): */ public function getShippingOption(): ?ShippingOption { - return ShippingManifest::getShippingOption($this); + return ShippingManifest::getShippingOption($this->calculate()); } /** @@ -592,18 +592,20 @@ public function createOrder( bool $allowMultipleOrders = false, ?int $orderIdToUpdate = null ): Order { + $cart = $this->refresh()->recalculate(); + foreach (config('lunar.cart.validators.order_create', [ ValidateCartForOrderCreation::class, ]) as $action) { app($action)->using( - cart: $this, + cart: $cart, )->validate(); } return app( config('lunar.cart.actions.order_create', CreateOrder::class) )->execute( - $this->refresh()->recalculate(), + $cart, $allowMultipleOrders, $orderIdToUpdate )->then(fn ($order) => $order->refresh()); diff --git a/packages/stripe/src/StripePaymentType.php b/packages/stripe/src/StripePaymentType.php index 0e873e2205..b882a320fc 100644 --- a/packages/stripe/src/StripePaymentType.php +++ b/packages/stripe/src/StripePaymentType.php @@ -8,6 +8,7 @@ use Lunar\Base\DataTransferObjects\PaymentChecks; use Lunar\Base\DataTransferObjects\PaymentRefund; use Lunar\Events\PaymentAttemptEvent; +use Lunar\Exceptions\Carts\CartException; use Lunar\Exceptions\DisallowMultipleCartOrdersException; use Lunar\Models\Transaction; use Lunar\PaymentTypes\AbstractPayment; @@ -61,7 +62,7 @@ final public function authorize(): ?PaymentAuthorize if (! $this->order) { try { $this->order = $this->cart->createOrder(); - } catch (DisallowMultipleCartOrdersException $e) { + } catch (DisallowMultipleCartOrdersException|CartException $e) { $failure = new PaymentAuthorize( success: false, message: $e->getMessage(), diff --git a/tests/core/Unit/Validation/Cart/ValidateCartForOrderCreationTest.php b/tests/core/Unit/Validation/Cart/ValidateCartForOrderCreationTest.php index 5c0fb842ca..233430db2c 100644 --- a/tests/core/Unit/Validation/Cart/ValidateCartForOrderCreationTest.php +++ b/tests/core/Unit/Validation/Cart/ValidateCartForOrderCreationTest.php @@ -98,6 +98,13 @@ 'shippable' => true, ]); + \Lunar\Models\Price::factory()->create([ + 'currency_id' => $currency->id, + 'priceable_id' => $purchasable->id, + 'priceable_type' => get_class($purchasable), + 'price' => 500, + ]); + $cart->lines()->create([ 'purchasable_type' => get_class($purchasable), 'purchasable_id' => $purchasable->id, @@ -113,10 +120,8 @@ 'cart_id' => $cart->id, ]); - $this->expectException(CartException::class); - $this->expectExceptionMessage(__('lunar::exceptions.carts.shipping_option_missing')); + expect(fn () => $validator->validate())->toThrow(CartException::class); - $validator->validate(); }); test('can validate collection with partial shipping address', function () { @@ -131,6 +136,13 @@ 'shippable' => true, ]); + \Lunar\Models\Price::factory()->create([ + 'currency_id' => $currency->id, + 'priceable_id' => $purchasable->id, + 'priceable_type' => get_class($purchasable), + 'price' => 500, + ]); + $cart->lines()->create([ 'purchasable_type' => get_class($purchasable), 'purchasable_id' => $purchasable->id, @@ -183,6 +195,13 @@ 'shippable' => true, ]); + \Lunar\Models\Price::factory()->create([ + 'currency_id' => $currency->id, + 'priceable_id' => $purchasable->id, + 'priceable_type' => get_class($purchasable), + 'price' => 500, + ]); + $cart->lines()->create([ 'purchasable_type' => get_class($purchasable), 'purchasable_id' => $purchasable->id, @@ -246,6 +265,13 @@ 'shippable' => true, ]); + \Lunar\Models\Price::factory()->create([ + 'currency_id' => $currency->id, + 'priceable_id' => $purchasable->id, + 'priceable_type' => get_class($purchasable), + 'price' => 500, + ]); + $cart->lines()->create([ 'purchasable_type' => get_class($purchasable), 'purchasable_id' => $purchasable->id, diff --git a/tests/shipping/TestUtils.php b/tests/shipping/TestUtils.php index 663a9f33ad..9a2d82a721 100644 --- a/tests/shipping/TestUtils.php +++ b/tests/shipping/TestUtils.php @@ -9,7 +9,7 @@ trait TestUtils { - public function createCart($currency = null, $price = 100, $quantity = 1) + public function createCart($currency = null, $price = 100, $quantity = 1, $calculate = true) { if (! $currency) { $currency = Currency::factory()->create([ @@ -38,10 +38,10 @@ public function createCart($currency = null, $price = 100, $quantity = 1) 'quantity' => $quantity, ]); - $this->assertNull($cart->total); - $this->assertNull($cart->taxTotal); - $this->assertNull($cart->subTotal); + expect($cart->total)->toBeNull() + ->and($cart->taxTotal)->toBeNull() + ->and($cart->subTotal)->toBeNull(); - return $cart->calculate(); + return $calculate ? $cart->calculate() : $cart; } } diff --git a/tests/shipping/Unit/ShippingModifierTest.php b/tests/shipping/Unit/ShippingModifierTest.php new file mode 100644 index 0000000000..d1ed8e8b2c --- /dev/null +++ b/tests/shipping/Unit/ShippingModifierTest.php @@ -0,0 +1,72 @@ +create([ + 'default' => true, + ]); + + $country = Country::factory()->create(); + + TaxClass::factory()->create([ + 'default' => true, + ]); + + $shippingZone = ShippingZone::factory()->create([ + 'type' => 'countries', + ]); + + $shippingZone->countries()->attach($country); + + $shippingMethod = ShippingMethod::factory()->create([ + 'driver' => 'ship-by', + 'code' => 'BASEDEL', + 'data' => [ + 'minimum_spend' => [ + "{$currency->code}" => 200, + ], + ], + ]); + + $shippingRate = \Lunar\Shipping\Models\ShippingRate::factory()->create([ + 'shipping_method_id' => $shippingMethod->id, + 'shipping_zone_id' => $shippingZone->id, + ]); + + $shippingRate->prices()->createMany([ + [ + 'price' => 1000, + 'min_quantity' => 1, + 'currency_id' => $currency->id, + ], + [ + 'price' => 0, + 'min_quantity' => 500, + 'currency_id' => $currency->id, + ], + ]); + + $cart = $this->createCart($currency, 6000, calculate: false); + + $cart->shippingAddress()->create( + \Lunar\Models\CartAddress::factory()->make([ + 'country_id' => $country->id, + 'shipping_option' => 'BASEDEL', + 'state' => null, + 'type' => 'shipping', + ])->toArray() + ); + + $option = $cart->refresh()->getShippingOption(); + + expect($option->price->value)->toBe(0); +})->group('shipping-modifier'); diff --git a/tests/stripe/Unit/StripePaymentTypeTest.php b/tests/stripe/Unit/StripePaymentTypeTest.php index b33e66aa64..a4c8e6af43 100644 --- a/tests/stripe/Unit/StripePaymentTypeTest.php +++ b/tests/stripe/Unit/StripePaymentTypeTest.php @@ -65,6 +65,7 @@ it('will fail if cart already has an order', function () { $cart = CartBuilder::build(); $order = $cart->createOrder(); + $order->update([ 'placed_at' => now(), ]); @@ -75,9 +76,12 @@ 'payment_intent' => 'PI_CAPTURE', ])->authorize(); - expect($response)->toBeInstanceOf(PaymentAuthorize::class); - expect($response->success)->toBeFalse(); - expect($response->message)->toBe('Carts can only have one order associated to them.'); + expect($response)->toBeInstanceOf(PaymentAuthorize::class) + ->and($response->success)->toBeFalse() + ->and($response->message)->toBeIn([ + 'Carts can only have one order associated to them.', + __('lunar::exceptions.carts.order_exists'), + ]); }); it('will fail if payment intent status is requires_payment_method', function () { From b7554ec2d909b5b6fb7e3e8bf167dbe878c1838a Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Wed, 14 Aug 2024 15:06:17 +0100 Subject: [PATCH 14/26] Add cart stock validators to config (#1904) --- docs/core/reference/carts.md | 14 ++++++++++++++ packages/core/config/cart.php | 2 ++ .../Unit/Actions/Carts/RemovePurchasableTest.php | 4 +++- .../Unit/Actions/Carts/UpdateCartLineTest.php | 4 +++- tests/core/Unit/Models/CartTest.php | 16 ++++++++++++---- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/core/reference/carts.md b/docs/core/reference/carts.md index 1aa386b648..5a0a8c948e 100644 --- a/docs/core/reference/carts.md +++ b/docs/core/reference/carts.md @@ -69,6 +69,20 @@ $cartLine = new \Lunar\Models\CartLine([ $cart->lines()->create([/* .. */]); ``` +### Validation + +When adding items to a cart there are a series of validation actions which are run, which are defined in the `config/lunar/cart.php` config file. + +These actions will throw a `Lunar\Exceptions\Carts\CartException`. + +```php +try { + $cart->add($purchasable, 500); +} catch (\Lunar\Exceptions\Carts\CartException $e) { + $error = $e->getMessage(); +} +``` + Now you have a basic Cart up and running, it's time to show you how you would use the cart to get all the calculated totals and tax. diff --git a/packages/core/config/cart.php b/packages/core/config/cart.php index 371ab00698..f9f77b8f93 100644 --- a/packages/core/config/cart.php +++ b/packages/core/config/cart.php @@ -89,10 +89,12 @@ 'add_to_cart' => [ Lunar\Validation\CartLine\CartLineQuantity::class, + Lunar\Validation\CartLine\CartLineStock::class, ], 'update_cart_line' => [ Lunar\Validation\CartLine\CartLineQuantity::class, + Lunar\Validation\CartLine\CartLineStock::class, ], 'remove_from_cart' => [], diff --git a/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php b/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php index e21518130a..2f86030031 100644 --- a/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php +++ b/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php @@ -17,7 +17,9 @@ 'currency_id' => $currency->id, ]); - $purchasable = ProductVariant::factory()->create(); + $purchasable = ProductVariant::factory()->create([ + 'stock' => 1, + ]); Price::factory()->create([ 'price' => 100, diff --git a/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php b/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php index 8c219cfe05..279756221f 100644 --- a/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php +++ b/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php @@ -18,7 +18,9 @@ 'currency_id' => $currency->id, ]); - $purchasable = ProductVariant::factory()->create(); + $purchasable = ProductVariant::factory()->create([ + 'stock' => 1, + ]); Price::factory()->create([ 'price' => 100, diff --git a/tests/core/Unit/Models/CartTest.php b/tests/core/Unit/Models/CartTest.php index 1efe360c9b..1ce8c12855 100644 --- a/tests/core/Unit/Models/CartTest.php +++ b/tests/core/Unit/Models/CartTest.php @@ -538,7 +538,9 @@ 'currency_id' => $currency->id, ]); - $purchasable = ProductVariant::factory()->create(); + $purchasable = ProductVariant::factory()->create([ + 'stock' => 1, + ]); Price::factory()->create([ 'price' => 100, @@ -562,7 +564,9 @@ 'currency_id' => $currency->id, ]); - $purchasable = ProductVariant::factory()->create(); + $purchasable = ProductVariant::factory()->create([ + 'stock' => 1, + ]); Price::factory()->create([ 'price' => 100, @@ -614,7 +618,9 @@ 'currency_id' => $currency->id, ]); - $purchasable = ProductVariant::factory()->create(); + $purchasable = ProductVariant::factory()->create([ + 'stock' => 1, + ]); Price::factory()->create([ 'price' => 100, @@ -691,7 +697,9 @@ 'currency_id' => $currency->id, ]); - $purchasable = ProductVariant::factory()->create(); + $purchasable = ProductVariant::factory()->create([ + 'stock' => 1, + ]); Price::factory()->create([ 'price' => 100, From fd2f972c79f68814f26479ef6f1b56993c7fb724 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 15 Aug 2024 08:13:09 +0100 Subject: [PATCH 15/26] Set Fieldtype config to empty array when null (#1896) --- .../RelationManagers/AttributesRelationManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php index 9fe8526674..8159ef0bc0 100644 --- a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php +++ b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php @@ -133,6 +133,7 @@ public function table(Table $table): Table ]) ->headerActions([ Tables\Actions\CreateAction::make()->mutateFormDataUsing(function (array $data, RelationManager $livewire) { + $data['configuration'] = $data['configuration'] ?? []; $data['system'] = false; $data['attribute_type'] = $livewire->ownerRecord->attributable_type; $data['position'] = $livewire->ownerRecord->attributes()->count() + 1; From 64bcc07db8ad6db494e01196ff61bf1e4620123e Mon Sep 17 00:00:00 2001 From: Maurice Ellis Date: Thu, 15 Aug 2024 00:33:09 -0700 Subject: [PATCH 16/26] Fixed and added additional config for File Fieldtype (#1894) --- .../admin/resources/lang/en/fieldtypes.php | 15 +++++ .../admin/src/Support/FieldTypes/File.php | 63 ++++++++++++++++++- .../admin/src/Support/Forms/AttributeData.php | 6 ++ .../src/Support/Synthesizers/FileSynth.php | 3 +- packages/core/src/FieldTypes/File.php | 23 +++++-- 5 files changed, 102 insertions(+), 8 deletions(-) diff --git a/packages/admin/resources/lang/en/fieldtypes.php b/packages/admin/resources/lang/en/fieldtypes.php index 46329780fc..12284f0b05 100644 --- a/packages/admin/resources/lang/en/fieldtypes.php +++ b/packages/admin/resources/lang/en/fieldtypes.php @@ -53,5 +53,20 @@ ], 'file' => [ 'label' => 'File', + 'form' => [ + 'file_types' => [ + 'label' => 'Allowed File Types', + 'placeholder' => 'New MIME' + ], + 'multiple' => [ + 'label' => 'Allow Multiple Files', + ], + 'min_files' => [ + 'label' => 'Min. Files', + ], + 'max_files' => [ + 'label' => 'Max. Files', + ], + ], ], ]; diff --git a/packages/admin/src/Support/FieldTypes/File.php b/packages/admin/src/Support/FieldTypes/File.php index 19f4d83881..45b689a8b2 100644 --- a/packages/admin/src/Support/FieldTypes/File.php +++ b/packages/admin/src/Support/FieldTypes/File.php @@ -13,9 +13,70 @@ class File extends BaseFieldType public static function getFilamentComponent(Attribute $attribute): Component { - return FileUpload::make($attribute->handle) + $file_types = $attribute->configuration->get('file_types'); + $multiple = (bool) $attribute->configuration->get('multiple'); + $min_files = $attribute->configuration->get('min_files'); + $max_files = $attribute->configuration->get('max_files'); + + $input = FileUpload::make($attribute->handle) ->when(filled($attribute->validation_rules), fn (FileUpload $component) => $component->rules($attribute->validation_rules)) ->required((bool) $attribute->required) ->helperText($attribute->translate('description')); + + if (!blank($file_types) && is_array($file_types)) { + $input->acceptedFileTypes($file_types); + } + + if ($multiple) { + $input->multiple(); + } + + if ($min_files) { + $input->minFiles($min_files); + } + + if ($max_files) { + $input->maxFiles($max_files); + } + + return $input; + } + + public static function getConfigurationFields(): array + { + return [ + \Filament\Forms\Components\TagsInput::make('file_types') + ->label( + __('lunarpanel::fieldtypes.file.form.file_types.label') + )->suggestions([ + 'image/*', + 'image/jpeg', + 'image/png', + 'image/gif', + 'audio/*', + 'audio/mpeg', + 'audio/aac', + 'audio/wav', + 'video/*', + 'video/mp4', + 'video/mpeg', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/rtf', + 'application/pdf' + ]) + ->placeholder(__('lunarpanel::fieldtypes.file.form.file_types.placeholder')) + ->reorderable(), + \Filament\Forms\Components\Toggle::make('multiple')->label( + __('lunarpanel::fieldtypes.file.form.multiple.label') + ), + \Filament\Forms\Components\TextInput::make('min_files') + ->label( + __('lunarpanel::fieldtypes.file.form.min_files.label') + )->nullable()->numeric(), + \Filament\Forms\Components\TextInput::make('max_files')->label( + __('lunarpanel::fieldtypes.file.form.max_files.label') + )->nullable()->numeric(), + ]; } } diff --git a/packages/admin/src/Support/Forms/AttributeData.php b/packages/admin/src/Support/Forms/AttributeData.php index ba21380bd4..661e9d53d0 100644 --- a/packages/admin/src/Support/Forms/AttributeData.php +++ b/packages/admin/src/Support/Forms/AttributeData.php @@ -62,6 +62,12 @@ public function getFilamentComponent(Attribute $attribute): Component return $state; }) ->mutateDehydratedStateUsing(function ($state) use ($attribute) { + if ($attribute->type == FileFieldType::class) { + $instance = new $attribute->type; + $instance->setValue($state); + return $instance; + } + if ( ! $state || (get_class($state) != $attribute->type) diff --git a/packages/admin/src/Support/Synthesizers/FileSynth.php b/packages/admin/src/Support/Synthesizers/FileSynth.php index ac812d6a74..dd652beed9 100644 --- a/packages/admin/src/Support/Synthesizers/FileSynth.php +++ b/packages/admin/src/Support/Synthesizers/FileSynth.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Support\Synthesizers; use Lunar\FieldTypes\File; +use Illuminate\Support\Arr; class FileSynth extends AbstractFieldSynth { @@ -21,7 +22,7 @@ public function hydrate($value) $instance->setValue($value); - return $instance; + return Arr::wrap($value); } public function get(&$target, $key) diff --git a/packages/core/src/FieldTypes/File.php b/packages/core/src/FieldTypes/File.php index 123e2807b4..60e7f8c4e0 100644 --- a/packages/core/src/FieldTypes/File.php +++ b/packages/core/src/FieldTypes/File.php @@ -8,7 +8,7 @@ class File implements FieldType, JsonSerializable { /** - * @var string + * @var string|array|null */ protected $value; @@ -30,9 +30,9 @@ public function jsonSerialize(): mixed /** * Create a new instance of File field type. * - * @param string $value + * @param string|array|null $value */ - public function __construct($value = '') + public function __construct($value = null) { $this->setValue($value); } @@ -44,13 +44,17 @@ public function __construct($value = '') */ public function __toString() { - return $this->getValue(); + if (is_array($this->getValue())) { + return implode(", ", $this->getValue()); + } + + return $this->getValue() ?? ""; } /** * Return the value of this field. * - * @return string + * @return string|array|null */ public function getValue() { @@ -60,10 +64,14 @@ public function getValue() /** * Set the value of this field. * - * @param string $value + * @param string|array|null $value */ public function setValue($value) { + if (blank($value)) { + $value = null; + } + $this->value = $value; } @@ -74,7 +82,10 @@ public function getConfig(): array { return [ 'options' => [ + 'file_types' => 'array', + 'multiple' => 'boolean', 'max_files' => 'numeric', + 'min_files' => 'numeric' ], ]; } From f8eccddd0749f400e8d6c1138fa8250942878f80 Mon Sep 17 00:00:00 2001 From: alecritson Date: Thu, 15 Aug 2024 07:35:41 +0000 Subject: [PATCH 17/26] chore: fix code style --- packages/admin/resources/lang/en/fieldtypes.php | 2 +- packages/admin/src/Support/FieldTypes/File.php | 4 ++-- packages/admin/src/Support/Forms/AttributeData.php | 1 + packages/admin/src/Support/Synthesizers/FileSynth.php | 2 +- packages/core/src/FieldTypes/File.php | 6 +++--- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/admin/resources/lang/en/fieldtypes.php b/packages/admin/resources/lang/en/fieldtypes.php index 12284f0b05..e0b034d825 100644 --- a/packages/admin/resources/lang/en/fieldtypes.php +++ b/packages/admin/resources/lang/en/fieldtypes.php @@ -56,7 +56,7 @@ 'form' => [ 'file_types' => [ 'label' => 'Allowed File Types', - 'placeholder' => 'New MIME' + 'placeholder' => 'New MIME', ], 'multiple' => [ 'label' => 'Allow Multiple Files', diff --git a/packages/admin/src/Support/FieldTypes/File.php b/packages/admin/src/Support/FieldTypes/File.php index 45b689a8b2..95abf266b8 100644 --- a/packages/admin/src/Support/FieldTypes/File.php +++ b/packages/admin/src/Support/FieldTypes/File.php @@ -23,7 +23,7 @@ public static function getFilamentComponent(Attribute $attribute): Component ->required((bool) $attribute->required) ->helperText($attribute->translate('description')); - if (!blank($file_types) && is_array($file_types)) { + if (! blank($file_types) && is_array($file_types)) { $input->acceptedFileTypes($file_types); } @@ -63,7 +63,7 @@ public static function getConfigurationFields(): array 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/rtf', - 'application/pdf' + 'application/pdf', ]) ->placeholder(__('lunarpanel::fieldtypes.file.form.file_types.placeholder')) ->reorderable(), diff --git a/packages/admin/src/Support/Forms/AttributeData.php b/packages/admin/src/Support/Forms/AttributeData.php index 661e9d53d0..3d03ebef03 100644 --- a/packages/admin/src/Support/Forms/AttributeData.php +++ b/packages/admin/src/Support/Forms/AttributeData.php @@ -65,6 +65,7 @@ public function getFilamentComponent(Attribute $attribute): Component if ($attribute->type == FileFieldType::class) { $instance = new $attribute->type; $instance->setValue($state); + return $instance; } diff --git a/packages/admin/src/Support/Synthesizers/FileSynth.php b/packages/admin/src/Support/Synthesizers/FileSynth.php index dd652beed9..cbd95c87a3 100644 --- a/packages/admin/src/Support/Synthesizers/FileSynth.php +++ b/packages/admin/src/Support/Synthesizers/FileSynth.php @@ -2,8 +2,8 @@ namespace Lunar\Admin\Support\Synthesizers; -use Lunar\FieldTypes\File; use Illuminate\Support\Arr; +use Lunar\FieldTypes\File; class FileSynth extends AbstractFieldSynth { diff --git a/packages/core/src/FieldTypes/File.php b/packages/core/src/FieldTypes/File.php index 60e7f8c4e0..cd8c2b623f 100644 --- a/packages/core/src/FieldTypes/File.php +++ b/packages/core/src/FieldTypes/File.php @@ -45,10 +45,10 @@ public function __construct($value = null) public function __toString() { if (is_array($this->getValue())) { - return implode(", ", $this->getValue()); + return implode(', ', $this->getValue()); } - return $this->getValue() ?? ""; + return $this->getValue() ?? ''; } /** @@ -85,7 +85,7 @@ public function getConfig(): array 'file_types' => 'array', 'multiple' => 'boolean', 'max_files' => 'numeric', - 'min_files' => 'numeric' + 'min_files' => 'numeric', ], ]; } From 5e05dc6029cc1792f0cde122752ca4971c640ba0 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:48:05 +0800 Subject: [PATCH 18/26] Fix: Collection resource subnav extension (#1902) --- .../admin/src/Filament/Resources/CollectionResource.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/admin/src/Filament/Resources/CollectionResource.php b/packages/admin/src/Filament/Resources/CollectionResource.php index 6abb3cd209..c5621f30c1 100644 --- a/packages/admin/src/Filament/Resources/CollectionResource.php +++ b/packages/admin/src/Filament/Resources/CollectionResource.php @@ -4,7 +4,6 @@ use Filament\Forms; use Filament\Forms\Components\Component; -use Filament\Pages\Page; use Filament\Pages\SubNavigationPosition; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Builder; @@ -89,16 +88,16 @@ protected static function getDefaultRelations(): array return []; } - public static function getRecordSubNavigation(Page $page): array + public static function getDefaultSubNavigation(): array { - return $page->generateNavigationItems([ + return [ Pages\EditCollection::class, Pages\ManageCollectionChildren::class, Pages\ManageCollectionProducts::class, Pages\ManageCollectionAvailability::class, Pages\ManageCollectionMedia::class, Pages\ManageCollectionUrls::class, - ]); + ]; } public static function getDefaultPages(): array @@ -114,7 +113,7 @@ public static function getDefaultPages(): array ]; } - public static function getGlobalSearchResultTitle(Model $record): string|Htmlable + public static function getGlobalSearchResultTitle(Model $record): string | Htmlable { return $record->translateAttribute('name'); } From 46fe0d974f9e7a7b657fe652d420756983eb06a4 Mon Sep 17 00:00:00 2001 From: Georgi Kurian Date: Thu, 15 Aug 2024 03:48:52 -0400 Subject: [PATCH 19/26] Fixed an error in installation document (#1874) --- docs/core/installation.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/core/installation.md b/docs/core/installation.md index 4dd1862e15..9633b8b4dc 100644 --- a/docs/core/installation.md +++ b/docs/core/installation.md @@ -29,13 +29,14 @@ You may need to update your app's `composer.json` to set `"minimum-stability": " ### Add the LunarUser Trait -Some parts of the core rely on the `User` model having certain relationships set up. We've bundled these into a trait which you must add to any models that represent users in your database. +Some parts of the core rely on the User model having certain relationships set up. We have bundled these into a trait and an interface, which you must add to any models that represent users in your database. ```php use Lunar\Base\Traits\LunarUser; +use Lunar\Base\LunarUser as LunarUserInterface; // ... -class User extends Authenticatable +class User extends Authenticatable implements LunarUserInterface { use LunarUser; // ... From ea6652c00427d610bffc916328e79983146448f9 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:51:20 +0800 Subject: [PATCH 20/26] Fix: install command not publishing panel config (#1868) --- packages/core/src/Console/InstallLunar.php | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/Console/InstallLunar.php b/packages/core/src/Console/InstallLunar.php index 4bd3cc7070..cc7ec431b7 100644 --- a/packages/core/src/Console/InstallLunar.php +++ b/packages/core/src/Console/InstallLunar.php @@ -300,7 +300,6 @@ private function shouldOverwriteConfig(): bool private function publishConfiguration(bool $forcePublish = false): void { $params = [ - '--provider' => "Lunar\LunarServiceProvider", '--tag' => 'lunar', ]; From e4805d4bb201f0795a628319d248f003b744be7c Mon Sep 17 00:00:00 2001 From: alecritson Date: Thu, 15 Aug 2024 07:53:50 +0000 Subject: [PATCH 21/26] chore: fix code style --- packages/admin/src/Filament/Resources/CollectionResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/admin/src/Filament/Resources/CollectionResource.php b/packages/admin/src/Filament/Resources/CollectionResource.php index c5621f30c1..64bf446e6b 100644 --- a/packages/admin/src/Filament/Resources/CollectionResource.php +++ b/packages/admin/src/Filament/Resources/CollectionResource.php @@ -113,7 +113,7 @@ public static function getDefaultPages(): array ]; } - public static function getGlobalSearchResultTitle(Model $record): string | Htmlable + public static function getGlobalSearchResultTitle(Model $record): string|Htmlable { return $record->translateAttribute('name'); } From 338e4e1ef7bfc6a21d7b5ef08c569524a7690d70 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:09:33 +0800 Subject: [PATCH 22/26] Fix attribute empty translated description error (#1862) --- .../RelationManagers/AttributesRelationManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php index 8159ef0bc0..489f0f8355 100644 --- a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php +++ b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php @@ -50,6 +50,7 @@ public function form(Form $form): Form ->helperText( __('lunarpanel::attribute.form.description.helper') ) + ->afterStateHydrated(fn ($state, $component) => $state ?: $component->state([Language::getDefault()->code => null])) ->maxLength(255), Forms\Components\TextInput::make('handle') ->label( From 1a4d9e2b5fcd6a241455eece475d84ee761fc4c7 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 15 Aug 2024 10:25:54 +0100 Subject: [PATCH 23/26] Add action to check maintainer access to repo (#1905) Sometimes a PR will be created by an external contributor and this repo will not have sufficient access to allow the core team to help with any code changes and/or allow other required Github actions to run. This PR adds an action which checks access as part of it's approval process. --- .../workflows/check-pr-maintainer-access.yml | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/check-pr-maintainer-access.yml diff --git a/.github/workflows/check-pr-maintainer-access.yml b/.github/workflows/check-pr-maintainer-access.yml new file mode 100644 index 0000000000..1083fad081 --- /dev/null +++ b/.github/workflows/check-pr-maintainer-access.yml @@ -0,0 +1,68 @@ +# Copied from https://raw.githubusercontent.com/filamentphp/filament/3.x/.github/workflows/check-pr-maintainer-access.yml +name: check-pr-maintainer-access + +on: + pull_request_target: + types: + - opened + +permissions: + pull-requests: write + +jobs: + notify-when-maintainers-cannot-edit: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v3 + with: + script: | + const query = ` + query($number: Int!) { + repository(owner: "lunarphp", name: "lunar") { + pullRequest(number: $number) { + headRepositoryOwner { + login + } + maintainerCanModify + } + } + } + ` + + const pullNumber = context.issue.number + const variables = { number: pullNumber } + + try { + console.log(`Check #${pullNumber} for maintainer edit access...`) + const result = await github.graphql(query, variables) + + console.log(JSON.stringify(result, null, 2)) + + const pullRequest = result.repository.pullRequest + + if (pullRequest.headRepositoryOwner.login === 'lunarphp') { + console.log('PR owned by lunarphp') + + return + } + + if (! pullRequest.maintainerCanModify) { + console.log('PR not owned by lunarphp and does not have maintainer edits enabled') + + await github.issues.createComment({ + issue_number: pullNumber, + owner: 'lunarphp', + repo: 'lunar', + body: 'Thanks for submitting a PR!\n\nIn order to review and merge PRs most efficiently, we require that all PRs grant maintainer edit access before we review them. If your fork belongs to a GitHub organization, please move the repository to your personal account and try again. If you\'re already using a personal fork, you can learn how to enable maintainer access [in the GitHub documentation](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork).' + }) + + await github.issues.update({ + issue_number: pullNumber, + owner: 'lunarphp', + repo: context.repo.repo, + state: 'closed' + }) + } + } catch(error) { + console.log(error) + } From 69ca5520e6fcbf8bd9fc9d5c334ec4fbc5413864 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 15 Aug 2024 10:30:57 +0100 Subject: [PATCH 24/26] Documentation Fixes (#1906) Closes #1873 Closes #1872 --- docs/core/reference/products.md | 2 +- docs/core/reference/taxation.md | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/core/reference/products.md b/docs/core/reference/products.md index 995de86372..667fff4fe2 100644 --- a/docs/core/reference/products.md +++ b/docs/core/reference/products.md @@ -82,7 +82,7 @@ You can associate attributes to a product type like so (it's just a straight forward [Polymorphic relationship](https://laravel.com/docs/8.x/eloquent-relationships#many-to-many-polymorphic-relations)). ```php -$productType->mappedAttributes()->associate([ /* attribute ids ... */ ]); +$productType->mappedAttributes()->attach([ /* attribute ids ... */ ]); ``` You can associate both `Product` and `ProductVariant` attributes to a product type which will then display on either the diff --git a/docs/core/reference/taxation.md b/docs/core/reference/taxation.md index fa84669548..e93596149c 100644 --- a/docs/core/reference/taxation.md +++ b/docs/core/reference/taxation.md @@ -34,16 +34,16 @@ These specify a geographic zone for tax rates to be applied. Tax Zones can be ba Lunar\Models\TaxZone ``` -|Field|Description| -|:-|:-| -|id|| -|name|e.g. `UK`| -|zone_type|`country`, `state`, or `postcode`| -|price_display|`tax_inclusive` or `tax_exclusive`| -|active|true/false| -|default|true/false| -|created_at|| -|updated_at|| +|Field| Description | +|:-|:------------------------------------| +|id| | +|name| e.g. `UK` | +|zone_type| `country`, `states`, or `postcodes` | +|price_display| `tax_inclusive` or `tax_exclusive` | +|active| true/false | +|default| true/false | +|created_at| | +|updated_at| | ```php $taxZone = TaxZone::create([ From c343ac348984e0f6d60472785dc689f833627cf5 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 15 Aug 2024 12:03:43 +0100 Subject: [PATCH 25/26] Fix Postgres issue on create customer page (#1907) --- .../admin/src/Filament/Resources/CustomerResource.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/admin/src/Filament/Resources/CustomerResource.php b/packages/admin/src/Filament/Resources/CustomerResource.php index aa97eea5ae..c84b571cba 100644 --- a/packages/admin/src/Filament/Resources/CustomerResource.php +++ b/packages/admin/src/Filament/Resources/CustomerResource.php @@ -159,7 +159,13 @@ protected static function getCustomerGroupsFormComponent(): Component { return Forms\Components\CheckboxList::make('customerGroups') ->label(__('lunarpanel::customer.form.customer_groups.label')) - ->relationship(name: 'customerGroups', titleAttribute: 'name'); + ->relationship( + name: 'customerGroups', + titleAttribute: 'name', + modifyQueryUsing: fn (Builder $query) => $query->distinct( + ['id', 'name', 'handle', 'default'] + ) + ); } protected static function getDefaultTable(Table $table): Table From 5d32f3997d97cd5d1fc68e22c633d122b292a72e Mon Sep 17 00:00:00 2001 From: Justin Scott Date: Fri, 16 Aug 2024 01:53:19 -0500 Subject: [PATCH 26/26] Fixes attribute description migration in postgresql (#1851) --- .../2024_01_11_100000_add_description_to_attributes_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/database/migrations/2024_01_11_100000_add_description_to_attributes_table.php b/packages/core/database/migrations/2024_01_11_100000_add_description_to_attributes_table.php index 4c9cad4fb7..1ac6417209 100644 --- a/packages/core/database/migrations/2024_01_11_100000_add_description_to_attributes_table.php +++ b/packages/core/database/migrations/2024_01_11_100000_add_description_to_attributes_table.php @@ -9,7 +9,7 @@ public function up(): void { Schema::table($this->prefix.'attributes', function (Blueprint $table) { - $table->json('description')->after('name'); + $table->json('description')->after('name')->nullable(); }); }