From 55b45291b7057cb6d8a4f406e8eaaaf4917a4da7 Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Mon, 4 Dec 2023 15:57:57 +0000 Subject: [PATCH 01/10] Update package.json --- docs/package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/package.json b/docs/package.json index 8e351840d2..3289b08a2a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,10 +1,11 @@ { "devDependencies": { - "vitepress": "^1.0.0-beta.7" + "vitepress": "^1.0.0-rc.31" }, "scripts": { "docs:dev": "vitepress dev", "docs:build": "vitepress build", "docs:preview": "vitepress preview" - } -} \ No newline at end of file + }, + "type": "module" +} From 79c0779a0a33e2a77663f45a4895f9030c43150c Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Fri, 22 Dec 2023 21:05:34 +0800 Subject: [PATCH 02/10] add listener to hub activityLogFeed (#1410) using same listener name as filament panel --- .../admin/src/Http/Livewire/Components/ActivityLogFeed.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/admin/src/Http/Livewire/Components/ActivityLogFeed.php b/packages/admin/src/Http/Livewire/Components/ActivityLogFeed.php index 17266a5a7c..c32ce1db7a 100644 --- a/packages/admin/src/Http/Livewire/Components/ActivityLogFeed.php +++ b/packages/admin/src/Http/Livewire/Components/ActivityLogFeed.php @@ -22,7 +22,9 @@ class ActivityLogFeed extends Component * The new comment for the subject. */ public ?string $comment = null; - + + protected $listeners = ['activityUpdated' => '$refresh']; + /** * {@inheritDoc} */ From d7197603dc212b227332a8fa79e0b35ddaf9d1f5 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Fri, 22 Dec 2023 13:53:32 +0000 Subject: [PATCH 03/10] Chore - Merge 07 to 08 (#1418) --- .github/ISSUE_TEMPLATE/bug-report.md | 2 +- README.md | 2 +- .../admin/src/AdminHubServiceProvider.php | 8 +- .../Components/Discounts/AbstractDiscount.php | 39 ++----- .../Pages/Products/ProductShowTest.php | 34 ++++++ .../Product/ProductOptionCreateTest.php | 45 ++++++++ .../Product/ProductOptionValueCreateTest.php | 49 +++++++++ .../database/state/ConvertTaxbreakdown.php | 88 +++++++-------- .../Base/Traits/CanScheduleAvailability.php | 5 +- packages/core/src/Base/Traits/HasPrices.php | 12 +-- packages/core/src/Base/Traits/HasTags.php | 5 +- packages/core/src/Base/Traits/HasUrls.php | 6 +- packages/core/src/Base/Traits/LunarUser.php | 5 +- packages/core/src/Models/Address.php | 9 +- packages/core/src/Models/Asset.php | 5 +- packages/core/src/Models/AttributeGroup.php | 5 +- packages/core/src/Models/Brand.php | 5 +- packages/core/src/Models/Cart.php | 100 +++++------------- packages/core/src/Models/CartAddress.php | 11 +- packages/core/src/Models/CartLine.php | 21 ++-- packages/core/src/Models/Channel.php | 8 +- packages/core/src/Models/Collection.php | 15 +-- packages/core/src/Models/CollectionGroup.php | 6 +- packages/core/src/Models/Country.php | 5 +- packages/core/src/Models/Currency.php | 8 +- packages/core/src/Models/Customer.php | 24 ++--- packages/core/src/Models/CustomerGroup.php | 5 +- packages/core/src/Models/Discount.php | 53 +++++----- .../core/src/Models/DiscountCollection.php | 12 +-- .../core/src/Models/DiscountPurchasable.php | 18 ++-- packages/core/src/Models/Language.php | 4 +- packages/core/src/Models/Order.php | 75 ++++--------- packages/core/src/Models/OrderAddress.php | 9 +- packages/core/src/Models/OrderLine.php | 15 ++- packages/core/src/Models/Price.php | 26 ++--- packages/core/src/Models/Product.php | 57 +++------- .../core/src/Models/ProductAssociation.php | 34 ++---- packages/core/src/Models/ProductOption.php | 9 +- .../core/src/Models/ProductOptionValue.php | 14 +-- packages/core/src/Models/ProductType.php | 18 ++-- packages/core/src/Models/ProductVariant.php | 32 +++--- packages/core/src/Models/State.php | 5 +- packages/core/src/Models/Tag.php | 4 +- packages/core/src/Models/TaxClass.php | 9 +- packages/core/src/Models/TaxRate.php | 10 +- packages/core/src/Models/TaxRateAmount.php | 9 +- packages/core/src/Models/TaxZone.php | 26 ++--- packages/core/src/Models/TaxZoneCountry.php | 9 +- .../core/src/Models/TaxZoneCustomerGroup.php | 9 +- packages/core/src/Models/TaxZonePostcode.php | 9 +- packages/core/src/Models/TaxZoneState.php | 9 +- packages/core/src/Models/Transaction.php | 10 +- packages/core/src/Models/Url.php | 16 ++- 53 files changed, 473 insertions(+), 555 deletions(-) create mode 100644 packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php create mode 100644 packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 8a4d7affaf..a4433edf11 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -2,7 +2,7 @@ name: "\U0001F41B Bug report" about: Report something that's broken. title: '' -labels: bug +labels: bug,unconfirmed assignees: '' --- diff --git a/README.md b/README.md index da4a8de7d7..7fecaf3ee4 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ This repository serves as a monorepo for the main packages that make up Lunar. ## Community - [Join our discord server](https://discord.gg/v6qVWaf) and chat to the developers and people using Lunar. -- [We have a roadmap](https://github.com/orgs/lunarphp/projects/1) where we will be detailing which features are next. +- [We have a roadmap](https://github.com/orgs/lunarphp/projects/8) where we will be detailing which features are next. ## Packages in this monorepo diff --git a/packages/admin/src/AdminHubServiceProvider.php b/packages/admin/src/AdminHubServiceProvider.php index 762fb9b7c4..129e3a7e1d 100644 --- a/packages/admin/src/AdminHubServiceProvider.php +++ b/packages/admin/src/AdminHubServiceProvider.php @@ -219,8 +219,12 @@ public function boot() $this->registerPublishables(); $this->registerStateListeners(); - Route::bind('product', function ($id) { - return Product::withTrashed()->findOrFail($id); + Route::bind('product', function (mixed $value, \Illuminate\Routing\Route $route) { + if (in_array(\Lunar\Hub\Http\Middleware\Authenticate::class, $route->middleware())) { + return Product::withTrashed()->findOrFail($value); + } + + return $value; }); // Commands diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php b/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php index 9705c60068..b2f5f3fcc8 100644 --- a/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php +++ b/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php @@ -51,7 +51,7 @@ abstract class AbstractDiscount extends Component * @var array */ public Collection $selectedProducts; - + /** * The product variants to restrict the coupon for. * @@ -122,32 +122,29 @@ public function mount() $this->selectedProducts = $this->discount->purchasables() ->whereIn('type', ['limitation', 'exclusion']) ->wherePurchasableType(Product::class) + ->whereHas('purchasable') ->get() ->map(function ($limitation) { return array_merge($this->mapProductToArray($limitation->purchasable), ['type' => $limitation->type]); }); - + $this->selectedProductVariants = $this->discount->purchasables() ->whereIn('type', ['limitation', 'exclusion']) ->wherePurchasableType(ProductVariant::class) + ->whereHas('purchasable') ->get() ->map(function ($limitation) { return array_merge($this->mapProductVariantToArray($limitation->purchasable), ['type' => $limitation->type]); }); - - $this->selectedProductVariants = $this->discount->purchasableLimitations() - ->wherePurchasableType(ProductVariant::class) - ->get() - ->map(function ($limitation) { - return $this->mapProductVariantToArray($limitation->purchasable); - }); $this->selectedConditions = $this->discount->purchasableConditions() ->wherePurchasableType(Product::class) + ->whereHas('purchasable') ->pluck('purchasable_id')->values()->toArray(); $this->selectedRewards = $this->discount->purchasableRewards() ->wherePurchasableType(Product::class) + ->whereHas('purchasable') ->pluck('purchasable_id')->values()->toArray(); $this->syncAvailability(); @@ -258,7 +255,7 @@ public function selectProducts(array $ids) ? $this->selectedProducts->merge($selectedProducts) : $selectedProducts; } - + /** * Select product variants given an array of IDs * @@ -345,7 +342,7 @@ public function removeProduct($index) { $this->selectedProducts->forget($index); } - + /** * Remove the product variant by it's index. * @@ -414,7 +411,7 @@ public function save() $this->discount->collections()->sync( $this->selectedCollections->mapWithKeys(fn ($collection) => [$collection['id'] => ['type' => $collection['type']]]) ); - + $this->discount->purchasables() ->whereIn('type', ['exclusion', 'limitation']) ->where('purchasable_type', Product::class) @@ -434,7 +431,7 @@ public function save() ]) ->save(); } - + $this->discount->purchasables() ->whereIn('type', ['exclusion', 'limitation']) ->where('purchasable_type', ProductVariant::class) @@ -454,20 +451,6 @@ public function save() ]) ->save(); } - - $this->discount->purchasableLimitations() - ->where('purchasable_type', ProductVariant::class) - ->whereNotIn('purchasable_id', $this->selectedProductVariants->pluck('id')) - ->delete(); - - foreach ($this->selectedProductVariants as $variant) { - $this->discount->purchasableLimitations()->firstOrCreate([ - 'discount_id' => $this->discount->id, - 'type' => 'limitation', - 'purchasable_type' => ProductVariant::class, - 'purchasable_id' => $variant['id'], - ]); - } }); $this->emit('discount.saved', $this->discount->id); @@ -579,7 +562,7 @@ private function mapProductToArray($product) 'thumbnail' => optional($product->thumbnail)->getUrl('small'), ]; } - + /** * Return the data we need from a product variant * diff --git a/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php b/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php index 394bb192c6..86d9334d74 100644 --- a/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php +++ b/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php @@ -99,6 +99,40 @@ public function can_view_page_with_correct_permission() ->assertSeeLivewire('hub.components.products.show'); } + /** @test */ + public function cant_view_soft_deleted_products() + { + $this->setupRolesPermissions(); + + $staff = Staff::factory()->create([ + 'admin' => false, + ]); + + $staff->givePermissionTo('catalogue:manage-products'); + + $this->actingAs($staff, 'staff'); + + $product = Product::factory()->create([ + 'deleted_at' => now(), + ]); + + $variant = ProductVariant::factory()->create([ + 'product_id' => $product->id, + ]); + + foreach (Currency::get() as $currency) { + Price::factory()->create([ + 'priceable_type' => ProductVariant::class, + 'priceable_id' => $variant->id, + 'currency_id' => $currency->id, + 'tier' => 1, + ]); + } + + $this->get(route('hub.products.show', $product->id)) + ->assertSeeLivewire('hub.components.products.show'); + } + /** @test */ public function product_with_one_variant_has_variant_components_visible() { diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php new file mode 100644 index 0000000000..d06bb3639a --- /dev/null +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php @@ -0,0 +1,45 @@ +create([ + 'default' => true, + 'code' => 'en', + ]); + } + + /** + * @test + * */ + public function can_populate_product_option_data() + { + $staff = Staff::factory()->create([ + 'admin' => true, + ]); + + LiveWire::actingAs($staff, 'staff') + ->test(OptionsIndex::class) + ->set('newProductOption.name.' . Language::getDefault()->code, 'Size') + ->call('createOption'); + + $this->assertDatabaseHas((new ProductOption())->getTable(), [ + 'name' => json_encode([Language::getDefault()->code => 'Size']), + ]); + } +} diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php new file mode 100644 index 0000000000..46ac803a35 --- /dev/null +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php @@ -0,0 +1,49 @@ +create([ + 'default' => true, + 'code' => 'en', + ]); + } + + /** + * @test + * */ + public function can_populate_product_option_data() + { + ProductOption::factory(1)->create()->each(function ($option) { + $staff = Staff::factory()->create([ + 'admin' => true, + ]); + + LiveWire::actingAs($staff, 'staff') + ->test(OptionEdit::class, ['productOption' => $option]) + ->set('newProductOptionValue.name.' . Language::getDefault()->code, 'Size') + ->call('createOptionValue'); + + $this->assertDatabaseHas((new ProductOptionValue())->getTable(), [ + 'product_option_id' => $option->id, + 'name' => json_encode([Language::getDefault()->code => 'Size']) + ]); + }); + } +} diff --git a/packages/core/database/state/ConvertTaxbreakdown.php b/packages/core/database/state/ConvertTaxbreakdown.php index c7df120ac6..e3fbf6a505 100644 --- a/packages/core/database/state/ConvertTaxbreakdown.php +++ b/packages/core/database/state/ConvertTaxbreakdown.php @@ -14,49 +14,20 @@ public function prepare() public function run() { - $prefix = config('lunar.database.table_prefix'); - $updateTime = now(); - - if ($this->canRunOnOrders()) { - DB::table("{$prefix}orders") - ->whereJsonContainsKey("${prefix}orders.tax_breakdown->[0]->total") - ->orderBy('id') - ->chunk(500, function ($rows) use ($prefix, $updateTime) { - foreach ($rows as $row) { - $originalBreakdown = json_decode($row->tax_breakdown, true); - - DB::table("{$prefix}orders")->where('id', '=', $row->id)->update([ - 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { - return [ - 'description' => $breakdown['description'], - 'identifier' => $breakdown['identifier'] ?? $breakdown['description'], - 'percentage' => $breakdown['percentage'], - 'value' => $breakdown['total'], - 'currency_code' => $row->currency_code, - ]; - })->toJson(), - 'updated_at' => $updateTime, - ]); - } - }); - } - - if ($this->canRunOnOrderLines()) { - DB::table("{$prefix}order_lines") - ->whereJsonContainsKey("${prefix}order_lines.tax_breakdown->[0]->total") - ->orderBy("${prefix}order_lines.id") - ->select( - "${prefix}order_lines.id", - "${prefix}order_lines.tax_breakdown", - "${prefix}orders.currency_code", - ) - ->join("${prefix}orders", "${prefix}order_lines.order_id", '=', "${prefix}orders.id") - ->chunk(500, function ($rows) use ($prefix, $updateTime) { - DB::transaction(function () use ($prefix, $updateTime, $rows) { + DB::usingConnection(config('lunar.database.connection') ?: DB::getDefaultConnection(), function () { + + $prefix = config('lunar.database.table_prefix'); + $updateTime = now(); + + if ($this->canRunOnOrders()) { + DB::table("{$prefix}orders") + ->whereJsonContainsKey("{$prefix}orders.tax_breakdown->[0]->total") + ->orderBy('id') + ->chunk(500, function ($rows) use ($prefix, $updateTime) { foreach ($rows as $row) { $originalBreakdown = json_decode($row->tax_breakdown, true); - DB::table("{$prefix}order_lines")->where('id', '=', $row->id)->update([ + DB::table("{$prefix}orders")->where('id', '=', $row->id)->update([ 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { return [ 'description' => $breakdown['description'], @@ -70,8 +41,41 @@ public function run() ]); } }); - }); - } + } + + if ($this->canRunOnOrderLines()) { + DB::table("{$prefix}order_lines") + ->whereJsonContainsKey("{$prefix}order_lines.tax_breakdown->[0]->total") + ->orderBy("{$prefix}order_lines.id") + ->select( + "{$prefix}order_lines.id", + "{$prefix}order_lines.tax_breakdown", + "{$prefix}orders.currency_code", + ) + ->join("{$prefix}orders", "{$prefix}order_lines.order_id", '=', "{$prefix}orders.id") + ->chunk(500, function ($rows) use ($prefix, $updateTime) { + DB::transaction(function () use ($prefix, $updateTime, $rows) { + foreach ($rows as $row) { + $originalBreakdown = json_decode($row->tax_breakdown, true); + + DB::table("{$prefix}order_lines")->where('id', '=', $row->id)->update([ + 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { + return [ + 'description' => $breakdown['description'], + 'identifier' => $breakdown['identifier'] ?? $breakdown['description'], + 'percentage' => $breakdown['percentage'], + 'value' => $breakdown['total'], + 'currency_code' => $row->currency_code, + ]; + })->toJson(), + 'updated_at' => $updateTime, + ]); + } + }); + }); + } + + }); } protected function canRunOnOrders() diff --git a/packages/core/src/Base/Traits/CanScheduleAvailability.php b/packages/core/src/Base/Traits/CanScheduleAvailability.php index 0ab9743bf6..b7a9fb7f46 100644 --- a/packages/core/src/Base/Traits/CanScheduleAvailability.php +++ b/packages/core/src/Base/Traits/CanScheduleAvailability.php @@ -83,11 +83,8 @@ protected function unschedule(Relation $relation, $models, array $pivotData = [] /** * Returns the data for the sync update. - * - * @param \Illuminate\Support\Collection $models - * @return \Illuminate\Support\Collection */ - private function getScheduleMapping($models, array $pivotData = null) + private function getScheduleMapping(Collection $models, array $pivotData = null): Collection { return $models->mapWithKeys(function ($model) use ($pivotData) { return [ diff --git a/packages/core/src/Base/Traits/HasPrices.php b/packages/core/src/Base/Traits/HasPrices.php index 7760ac3cf3..b72065b51c 100644 --- a/packages/core/src/Base/Traits/HasPrices.php +++ b/packages/core/src/Base/Traits/HasPrices.php @@ -2,7 +2,9 @@ namespace Lunar\Base\Traits; +use Illuminate\Database\Eloquent\Relations\MorphMany; use Lunar\Facades\Pricing; +use Lunar\Managers\PricingManager; use Lunar\Models\Price; trait HasPrices @@ -10,7 +12,7 @@ trait HasPrices /** * Get all of the models prices. */ - public function prices() + public function prices(): MorphMany { return $this->morphMany( Price::class, @@ -20,20 +22,16 @@ public function prices() /** * Return base prices query. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphMany */ - public function basePrices() + public function basePrices(): MorphMany { return $this->prices()->whereTier(1)->whereNull('customer_group_id'); } /** * Return a PricingManager for this model. - * - * @return \Lunar\Managers\PricingManager */ - public function pricing() + public function pricing(): PricingManager { return Pricing::for($this); } diff --git a/packages/core/src/Base/Traits/HasTags.php b/packages/core/src/Base/Traits/HasTags.php index 5554ee6b35..27a1e35a36 100644 --- a/packages/core/src/Base/Traits/HasTags.php +++ b/packages/core/src/Base/Traits/HasTags.php @@ -2,6 +2,7 @@ namespace Lunar\Base\Traits; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Support\Collection; use Lunar\Jobs\SyncTags; use Lunar\Models\Tag; @@ -10,10 +11,8 @@ trait HasTags { /** * Get the tags - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function tags() + public function tags(): MorphToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Base/Traits/HasUrls.php b/packages/core/src/Base/Traits/HasUrls.php index 642c999a33..a8de3b653f 100644 --- a/packages/core/src/Base/Traits/HasUrls.php +++ b/packages/core/src/Base/Traits/HasUrls.php @@ -3,6 +3,8 @@ namespace Lunar\Base\Traits; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphOne; use Lunar\Models\Url; trait HasUrls @@ -31,7 +33,7 @@ public static function bootHasUrls() /** * Get all of the models urls. */ - public function urls() + public function urls(): MorphMany { return $this->morphMany( Url::class, @@ -39,7 +41,7 @@ public function urls() ); } - public function defaultUrl() + public function defaultUrl(): MorphOne { return $this->morphOne( Url::class, diff --git a/packages/core/src/Base/Traits/LunarUser.php b/packages/core/src/Base/Traits/LunarUser.php index a6171d8762..c365752cd0 100644 --- a/packages/core/src/Base/Traits/LunarUser.php +++ b/packages/core/src/Base/Traits/LunarUser.php @@ -2,20 +2,21 @@ namespace Lunar\Base\Traits; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Models\Customer; use Lunar\Models\Order; trait LunarUser { - public function customers() + public function customers(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); return $this->belongsToMany(Customer::class, "{$prefix}customer_user"); } - public function latestCustomer() + public function latestCustomer(): ?Customer { return $this->customers()->orderBy('created_at', 'desc')->orderBy('id', 'desc')->first(); } diff --git a/packages/core/src/Models/Address.php b/packages/core/src/Models/Address.php index 3baf3bdd9b..0f75f97e1a 100644 --- a/packages/core/src/Models/Address.php +++ b/packages/core/src/Models/Address.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\Addressable; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; @@ -66,20 +67,16 @@ protected static function newFactory(): AddressFactory /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } /** * Return the customer relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customer() + public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } diff --git a/packages/core/src/Models/Asset.php b/packages/core/src/Models/Asset.php index 260de9817d..1c76200e9c 100644 --- a/packages/core/src/Models/Asset.php +++ b/packages/core/src/Models/Asset.php @@ -2,6 +2,7 @@ namespace Lunar\Models; +use Illuminate\Database\Eloquent\Relations\MorphOne; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMedia as TraitsHasMedia; use Spatie\MediaLibrary\HasMedia; @@ -25,10 +26,8 @@ class Asset extends BaseModel implements HasMedia /** * Get the associated file. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphOne */ - public function file() + public function file(): MorphOne { return $this->morphOne(config('media-library.media_model'), 'model'); } diff --git a/packages/core/src/Models/AttributeGroup.php b/packages/core/src/Models/AttributeGroup.php index 54ceab15cf..5dfdffdb62 100644 --- a/packages/core/src/Models/AttributeGroup.php +++ b/packages/core/src/Models/AttributeGroup.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Base\Traits\HasTranslations; @@ -51,10 +52,8 @@ protected static function newFactory(): AttributeGroupFactory /** * Return the attributes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function attributes() + public function attributes(): HasMany { return $this->hasMany(Attribute::class)->orderBy('position'); } diff --git a/packages/core/src/Models/Brand.php b/packages/core/src/Models/Brand.php index d1aff03b85..3c74434e60 100644 --- a/packages/core/src/Models/Brand.php +++ b/packages/core/src/Models/Brand.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; use Lunar\Base\Traits\HasAttributes; @@ -56,10 +57,8 @@ protected static function newFactory(): BrandFactory /** * Get the mapped attributes relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function mappedAttributes() + public function mappedAttributes(): MorphToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/Cart.php b/packages/core/src/Models/Cart.php index 1cebeb8c81..a536616b84 100644 --- a/packages/core/src/Models/Cart.php +++ b/packages/core/src/Models/Cart.php @@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Foundation\Auth\User; use Illuminate\Pipeline\Pipeline; use Illuminate\Support\Collection; @@ -194,40 +197,32 @@ protected static function newFactory(): CartFactory /** * Return the cart lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function lines() + public function lines(): HasMany { return $this->hasMany(CartLine::class, 'cart_id', 'id'); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function currency() + public function currency(): BelongsTo { return $this->belongsTo(Currency::class); } /** * Return the user relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(config('auth.providers.users.model')); } /** * Return the customer relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customer() + public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } @@ -239,40 +234,32 @@ public function scopeUnmerged($query) /** * Return the addresses relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function addresses() + public function addresses(): HasMany { return $this->hasMany(CartAddress::class, 'cart_id'); } /** * Return the shipping address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function shippingAddress() + public function shippingAddress(): HasOne { return $this->hasOne(CartAddress::class, 'cart_id')->whereType('shipping'); } /** * Return the billing address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function billingAddress() + public function billingAddress(): HasOne { return $this->hasOne(CartAddress::class, 'cart_id')->whereType('billing'); } /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function orders() + public function orders(): HasMany { return $this->hasMany(Order::class); } @@ -291,10 +278,8 @@ public function scopeActive(Builder $query) /** * Return the draft order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function draftOrder(int $draftOrderId = null) + public function draftOrder(int $draftOrderId = null): HasOne { return $this->hasOne(Order::class) ->when($draftOrderId, function (Builder $query, int $draftOrderId) { @@ -304,10 +289,8 @@ public function draftOrder(int $draftOrderId = null) /** * Return the completed order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function completedOrder(int $completedOrderId = null) + public function completedOrder(int $completedOrderId = null): HasOne { return $this->hasOne(Order::class) ->when($completedOrderId, function (Builder $query, int $completedOrderId) { @@ -317,10 +300,8 @@ public function completedOrder(int $completedOrderId = null) /** * Return the carts completed order. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function completedOrders() + public function completedOrders(): HasMany { return $this->hasMany(Order::class) ->whereNotNull('placed_at'); @@ -328,10 +309,8 @@ public function completedOrders() /** * Return whether the cart has any completed order. - * - * @return bool */ - public function hasCompletedOrders() + public function hasCompletedOrders(): bool { return (bool) $this->completedOrders()->count(); } @@ -375,10 +354,8 @@ public function add(Purchasable $purchasable, int $quantity = 1, array $meta = [ /** * Add cart lines. - * - * @return bool */ - public function addLines(iterable $lines) + public function addLines(iterable $lines): Cart { DB::transaction(function () use ($lines) { collect($lines)->each(function ($line) { @@ -414,10 +391,8 @@ public function remove(int $cartLineId, bool $refresh = true): Cart /** * Update cart line - * - * @param array $meta */ - public function updateLine(int $cartLineId, int $quantity, $meta = null, bool $refresh = true): Cart + public function updateLine(int $cartLineId, int $quantity, array $meta = null, bool $refresh = true): Cart { foreach (config('lunar.cart.validators.update_cart_line', []) as $action) { app($action)->using( @@ -436,10 +411,8 @@ public function updateLine(int $cartLineId, int $quantity, $meta = null, bool $r /** * Update cart lines. - * - * @return \Lunar\Models\Cart */ - public function updateLines(Collection $lines) + public function updateLines(Collection $lines): Cart { DB::transaction(function () use ($lines) { $lines->each(function ($line) { @@ -458,7 +431,7 @@ public function updateLines(Collection $lines) /** * Deletes all cart lines. */ - public function clear() + public function clear(): Cart { $this->lines()->delete(); @@ -467,12 +440,8 @@ public function clear() /** * Associate a user to the cart - * - * @param string $policy - * @param bool $refresh - * @return Cart */ - public function associate(User $user, $policy = 'merge', $refresh = true) + public function associate(User $user, string $policy = 'merge', bool $refresh = true): Cart { if ($this->customer()->exists()) { if (! $user->query() @@ -527,20 +496,16 @@ public function addAddress(array|Addressable $address, string $type, bool $refre /** * Set the shipping address. - * - * @return \Lunar\Models\Cart */ - public function setShippingAddress(array|Addressable $address) + public function setShippingAddress(array|Addressable $address): Cart { return $this->addAddress($address, 'shipping'); } /** * Set the billing address. - * - * @return self */ - public function setBillingAddress(array|Addressable $address) + public function setBillingAddress(array|Addressable $address): Cart { return $this->addAddress($address, 'billing'); } @@ -548,7 +513,7 @@ public function setBillingAddress(array|Addressable $address) /** * Set the shipping option to the shipping address. */ - public function setShippingOption(ShippingOption $option, $refresh = true): Cart + public function setShippingOption(ShippingOption $option, bool $refresh = true): Cart { foreach (config('lunar.cart.validators.set_shipping_option', []) as $action) { app($action)->using( @@ -573,10 +538,8 @@ public function getShippingOption(): ?ShippingOption /** * Returns whether the cart has shippable items. - * - * @return bool */ - public function isShippable() + public function isShippable(): bool { return (bool) $this->lines->filter(function ($line) { return $line->purchasable->isShippable(); @@ -585,8 +548,6 @@ public function isShippable() /** * Create an order from the Cart. - * - * @return Cart */ public function createOrder( bool $allowMultipleOrders = false, @@ -611,10 +572,8 @@ public function createOrder( /** * Returns whether a cart has enough info to create an order. - * - * @return bool */ - public function canCreateOrder() + public function canCreateOrder(): bool { $passes = true; @@ -635,10 +594,8 @@ public function canCreateOrder() /** * Get a unique fingerprint for the cart to identify if the contents have changed. - * - * @return string */ - public function fingerprint() + public function fingerprint(): string { $generator = config('lunar.cart.fingerprint_generator', GenerateFingerprint::class); @@ -648,12 +605,9 @@ public function fingerprint() /** * Check whether a given fingerprint matches the one being generated for the cart. * - * @param string $fingerprint - * @return bool - * * @throws FingerprintMismatchException */ - public function checkFingerprint($fingerprint) + public function checkFingerprint(string $fingerprint): bool { return tap($fingerprint == $this->fingerprint(), function ($result) { throw_unless( diff --git a/packages/core/src/Models/CartAddress.php b/packages/core/src/Models/CartAddress.php index 83c210b317..3843d59105 100644 --- a/packages/core/src/Models/CartAddress.php +++ b/packages/core/src/Models/CartAddress.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\Addressable; use Lunar\Base\BaseModel; use Lunar\Base\Traits\CachesProperties; @@ -79,8 +80,6 @@ class CartAddress extends BaseModel implements Addressable /** * The tax breakdown. - * - * @var TaxBreakdown */ public ?TaxBreakdown $taxBreakdown = null; @@ -129,20 +128,16 @@ protected static function newFactory(): CartAddressFactory /** * Return the cart relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function cart() + public function cart(): BelongsTo { return $this->belongsTo(Cart::class); } /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/CartLine.php b/packages/core/src/Models/CartLine.php index eea2fb39a7..5a3dc99935 100644 --- a/packages/core/src/Models/CartLine.php +++ b/packages/core/src/Models/CartLine.php @@ -4,6 +4,10 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\CachesProperties; use Lunar\Base\Traits\HasMacros; @@ -112,20 +116,16 @@ protected static function newFactory(): CartLineFactory /** * Return the cart relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function cart() + public function cart(): BelongsTo { return $this->belongsTo(Cart::class); } /** * Return the tax class relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough */ - public function taxClass() + public function taxClass(): HasOneThrough { return $this->hasOneThrough( TaxClass::class, @@ -135,7 +135,10 @@ public function taxClass() ); } - public function discounts() + /** + * Return the cart line discount. + */ + public function discounts(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -147,10 +150,8 @@ public function discounts() /** * Return the polymorphic relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function purchasable() + public function purchasable(): MorphTo { return $this->morphTo(); } diff --git a/packages/core/src/Models/Channel.php b/packages/core/src/Models/Channel.php index 996a9c82af..a89b613eb3 100644 --- a/packages/core/src/Models/Channel.php +++ b/packages/core/src/Models/Channel.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Str; use Lunar\Base\BaseModel; @@ -47,11 +48,8 @@ protected static function newFactory(): ChannelFactory /** * Mutator for formatting the handle to a slug. - * - * @param string $val - * @return void */ - public function setHandleAttribute($val) + public function setHandleAttribute(?string $val): void { $this->attributes['handle'] = Str::slug($val); } @@ -59,7 +57,7 @@ public function setHandleAttribute($val) /** * Get the parent channelable model. */ - public function channelable() + public function channelable(): MorphTo { return $this->morphTo(); } diff --git a/packages/core/src/Models/Collection.php b/packages/core/src/Models/Collection.php index d80e2505af..830573992a 100644 --- a/packages/core/src/Models/Collection.php +++ b/packages/core/src/Models/Collection.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Kalnoy\Nestedset\NodeTrait; use Lunar\Base\BaseModel; @@ -66,25 +67,21 @@ protected static function newFactory(): CollectionFactory /** * Return the group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function group() + public function group(): BelongsTo { return $this->belongsTo(CollectionGroup::class, 'collection_group_id'); } - public function scopeInGroup(Builder $builder, $id) + public function scopeInGroup(Builder $builder, int $id): Builder { return $builder->where('collection_group_id', $id); } /** * Return the products relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function products() + public function products(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -98,10 +95,8 @@ public function products() /** * Get the translated name of ancestor collections. - * - * @return Illuminate\Support\Collection */ - public function getBreadcrumbAttribute() + public function getBreadcrumbAttribute(): \Illuminate\Support\Collection { return $this->ancestors->map(function ($ancestor) { return $ancestor->translateAttribute('name'); diff --git a/packages/core/src/Models/CollectionGroup.php b/packages/core/src/Models/CollectionGroup.php index 05b23737be..1b93149dee 100644 --- a/packages/core/src/Models/CollectionGroup.php +++ b/packages/core/src/Models/CollectionGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\CollectionGroupFactory; @@ -29,7 +30,10 @@ protected static function newFactory(): CollectionGroupFactory return CollectionGroupFactory::new(); } - public function collections() + /** + * Return the collections relationship. + */ + public function collections(): HasMany { return $this->hasMany(Collection::class); } diff --git a/packages/core/src/Models/Country.php b/packages/core/src/Models/Country.php index 7c8eb492d0..3b5247d03d 100644 --- a/packages/core/src/Models/Country.php +++ b/packages/core/src/Models/Country.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\CountryFactory; @@ -44,10 +45,8 @@ protected static function newFactory(): CountryFactory /** * Return the states relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function states() + public function states(): HasMany { return $this->hasMany(State::class); } diff --git a/packages/core/src/Models/Currency.php b/packages/core/src/Models/Currency.php index 9a8cd3e646..416bd511ba 100644 --- a/packages/core/src/Models/Currency.php +++ b/packages/core/src/Models/Currency.php @@ -46,10 +46,8 @@ protected static function newFactory(): CurrencyFactory /** * Return the prices relationship - * - * @return HasMany */ - public function prices() + public function prices(): HasMany { return $this->hasMany(Price::class); } @@ -57,10 +55,8 @@ public function prices() /** * Returns the amount we need to multiply or divide the price * for the cents/pence. - * - * @return string */ - public function getFactorAttribute() + public function getFactorAttribute(): string { /** * If we figure out how many decimal places we need, we can work diff --git a/packages/core/src/Models/Customer.php b/packages/core/src/Models/Customer.php index 5acbfafa23..f03c8dbddc 100644 --- a/packages/core/src/Models/Customer.php +++ b/packages/core/src/Models/Customer.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; use Lunar\Base\Traits\HasAttributes; @@ -60,10 +63,8 @@ protected static function newFactory(): CustomerFactory /** * Return the customer group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function customerGroups() + public function customerGroups(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -75,10 +76,8 @@ public function customerGroups() /** * Return the customer group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function users() + public function users(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -90,25 +89,24 @@ public function users() /** * Return the addresses relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function addresses() + public function addresses(): HasMany { return $this->hasMany(Address::class); } - public function orders() + /** + * Return the orders relationship. + */ + public function orders(): HasMany { return $this->hasMany(Order::class); } /** * Get the mapped attributes relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function mappedAttributes() + public function mappedAttributes(): MorphToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/CustomerGroup.php b/packages/core/src/Models/CustomerGroup.php index 5994b92899..b785109082 100644 --- a/packages/core/src/Models/CustomerGroup.php +++ b/packages/core/src/Models/CustomerGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasDefaultRecord; use Lunar\Base\Traits\HasMacros; @@ -37,10 +38,8 @@ protected static function newFactory(): CustomerGroupFactory /** * Return the customer's relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function customers() + public function customers(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/Discount.php b/packages/core/src/Models/Discount.php index 3dce32b662..88471e58e7 100644 --- a/packages/core/src/Models/Discount.php +++ b/packages/core/src/Models/Discount.php @@ -55,7 +55,7 @@ protected static function newFactory(): DiscountFactory return DiscountFactory::new(); } - public function users() + public function users(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -67,30 +67,40 @@ public function users() /** * Return the purchasables relationship. - * - * @return HasMany */ - public function purchasables() + public function purchasables(): HasMany { return $this->hasMany(DiscountPurchasable::class); } - public function purchasableConditions() + /** + * Return the purchasable conditions relationship. + */ + public function purchasableConditions(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('condition'); } - - public function purchasableExclusions() + + /** + * Return the purchasable exclusions relationship. + */ + public function purchasableExclusions(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('exclusion'); } - public function purchasableLimitations() + /** + * Return the purchasable limitations relationship. + */ + public function purchasableLimitations(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('limitation'); } - public function purchasableRewards() + /** + * Return the purchasable rewards relationship. + */ + public function purchasableRewards(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('reward'); } @@ -102,10 +112,8 @@ public function getType() /** * Return the collections relationship. - * - * @return HasMany */ - public function collections() + public function collections(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -133,7 +141,7 @@ public function customerGroups(): BelongsToMany ])->withTimestamps(); } - public function brands() + public function brands(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -145,10 +153,8 @@ public function brands() /** * Return the active scope. - * - * @return Builder */ - public function scopeActive(Builder $query) + public function scopeActive(Builder $query): Builder { return $query->whereNotNull('starts_at') ->where('starts_at', '<=', now()) @@ -160,10 +166,8 @@ public function scopeActive(Builder $query) /** * Return the products scope. - * - * @return Builder */ - public function scopeProducts(Builder $query, iterable $productIds = [], string $type = null) + public function scopeProducts(Builder $query, iterable $productIds = [], string $type = null): Builder { if (is_array($productIds)) { $productIds = collect($productIds); @@ -181,13 +185,11 @@ public function scopeProducts(Builder $query, iterable $productIds = [], string ) ); } - + /** * Return the product variants scope. - * - * @return Builder */ - public function scopeProductVariants(Builder $query, iterable $variantIds = [], string $type = null) + public function scopeProductVariants(Builder $query, iterable $variantIds = [], string $type = null): Builder { if (is_array($variantIds)) { $variantIds = collect($variantIds); @@ -206,7 +208,10 @@ public function scopeProductVariants(Builder $query, iterable $variantIds = [], ); } - public function scopeUsable(Builder $query) + /** + * Return when the discount is usable. + */ + public function scopeUsable(Builder $query): Builder { return $query->where(function ($subQuery) { $subQuery->whereRaw('uses < max_uses') diff --git a/packages/core/src/Models/DiscountCollection.php b/packages/core/src/Models/DiscountCollection.php index 07c37170ae..ee971e23a8 100644 --- a/packages/core/src/Models/DiscountCollection.php +++ b/packages/core/src/Models/DiscountCollection.php @@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Database\Factories\DiscountPurchasableFactory; -use Lunar\Discounts\Database\Factories\DiscountFactory; class DiscountCollection extends BaseModel { @@ -26,8 +25,6 @@ class DiscountCollection extends BaseModel /** * Return a new factory instance for the model. - * - * @return DiscountFactory */ protected static function newFactory(): DiscountPurchasableFactory { @@ -36,15 +33,16 @@ protected static function newFactory(): DiscountPurchasableFactory /** * Return the discount relationship. - * - * @return BelongsTo */ - public function discount() + public function discount(): BelongsTo { return $this->belongsTo(Discount::class); } - public function collection() + /** + * Return the collection relationship. + */ + public function collection(): BelongsTo { return $this->belongsTo(Collection::class); } diff --git a/packages/core/src/Models/DiscountPurchasable.php b/packages/core/src/Models/DiscountPurchasable.php index 02c8a79e4b..9c2ac7ef16 100644 --- a/packages/core/src/Models/DiscountPurchasable.php +++ b/packages/core/src/Models/DiscountPurchasable.php @@ -4,9 +4,10 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Database\Factories\DiscountPurchasableFactory; -use Lunar\Discounts\Database\Factories\DiscountFactory; /** * @property int $id @@ -36,8 +37,6 @@ class DiscountPurchasable extends BaseModel /** * Return a new factory instance for the model. - * - * @return DiscountFactory */ protected static function newFactory(): DiscountPurchasableFactory { @@ -46,25 +45,24 @@ protected static function newFactory(): DiscountPurchasableFactory /** * Return the discount relationship. - * - * @return BelongsTo */ - public function discount() + public function discount(): BelongsTo { return $this->belongsTo(Discount::class); } /** * Return the priceable relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function purchasable() + public function purchasable(): MorphTo { return $this->morphTo(); } - public function scopeCondition(Builder $query) + /** + * Scope a query where type is condition. + */ + public function scopeCondition(Builder $query): void { $query->whereType('condition'); } diff --git a/packages/core/src/Models/Language.php b/packages/core/src/Models/Language.php index 5d0e9d2448..4e14d09742 100644 --- a/packages/core/src/Models/Language.php +++ b/packages/core/src/Models/Language.php @@ -41,10 +41,8 @@ protected static function newFactory(): LanguageFactory /** * Return the URLs relationship - * - * @return HasMany */ - public function urls() + public function urls(): HasMany { return $this->hasMany(Url::class); } diff --git a/packages/core/src/Models/Order.php b/packages/core/src/Models/Order.php index b33be914bc..0ec0318acc 100644 --- a/packages/core/src/Models/Order.php +++ b/packages/core/src/Models/Order.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; use Lunar\Base\BaseModel; use Lunar\Base\Casts\DiscountBreakdown; use Lunar\Base\Casts\Price; @@ -80,10 +83,8 @@ protected static function newFactory(): OrderFactory /** * Getter for status label. - * - * @return string */ - public function getStatusLabelAttribute() + public function getStatusLabelAttribute(): string { $statuses = config('lunar.orders.statuses'); @@ -92,170 +93,136 @@ public function getStatusLabelAttribute() /** * Return the channel relationship. - * - * @return void */ - public function channel() + public function channel(): BelongsTo { return $this->belongsTo(Channel::class); } /** * Return the cart relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function cart() + public function cart(): BelongsTo { return $this->belongsTo(Cart::class); } /** * Return the lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function lines() + public function lines(): HasMany { return $this->hasMany(OrderLine::class); } /** * Return physical product lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function physicalLines() + public function physicalLines(): HasMany { return $this->lines()->whereType('physical'); } /** * Return digital product lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function digitalLines() + public function digitalLines(): HasMany { return $this->lines()->whereType('digital'); } /** * Return shipping lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function shippingLines() + public function shippingLines(): HasMany { return $this->lines()->whereType('shipping'); } /** * Return product lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function productLines() + public function productLines(): HasMany { return $this->lines()->where('type', '!=', 'shipping'); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function currency() + public function currency(): BelongsTo { return $this->belongsTo(Currency::class, 'currency_code', 'code'); } /** * Return the addresses relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function addresses() + public function addresses(): HasMany { return $this->hasMany(OrderAddress::class, 'order_id'); } /** * Return the shipping address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function shippingAddress() + public function shippingAddress(): HasOne { return $this->hasOne(OrderAddress::class, 'order_id')->whereType('shipping'); } /** * Return the billing address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function billingAddress() + public function billingAddress(): HasOne { return $this->hasOne(OrderAddress::class, 'order_id')->whereType('billing'); } /** * Return the transactions relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function transactions() + public function transactions(): HasMany { return $this->hasMany(Transaction::class); } /** * Return the charges relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function captures() + public function captures(): HasMany { return $this->transactions()->whereType('capture'); } /** * Return the charges relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function intents() + public function intents(): HasMany { return $this->transactions()->whereType('intent'); } /** * Return the refunds relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function refunds() + public function refunds(): HasMany { return $this->transactions()->whereType('refund'); } /** * Return the customer relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customer() + public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } /** * Return the user relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function user() + public function user(): BelongsTo { return $this->belongsTo( config('auth.providers.users.model') diff --git a/packages/core/src/Models/OrderAddress.php b/packages/core/src/Models/OrderAddress.php index 4c94a49ced..e5e285e5a4 100644 --- a/packages/core/src/Models/OrderAddress.php +++ b/packages/core/src/Models/OrderAddress.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\Addressable; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; @@ -86,20 +87,16 @@ protected static function newFactory(): OrderAddressFactory /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function order() + public function order(): BelongsTo { return $this->belongsTo(Order::class); } /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/OrderLine.php b/packages/core/src/Models/OrderLine.php index ca8ba65176..46890e1849 100644 --- a/packages/core/src/Models/OrderLine.php +++ b/packages/core/src/Models/OrderLine.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Casts\Price; use Lunar\Base\Casts\TaxBreakdown; @@ -74,30 +77,24 @@ protected static function newFactory(): OrderLineFactory /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function order() + public function order(): BelongsTo { return $this->belongsTo(Order::class); } /** * Return the polymorphic relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function purchasable() + public function purchasable(): MorphTo { return $this->morphTo(); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough */ - public function currency() + public function currency(): HasOneThrough { return $this->hasOneThrough( Currency::class, diff --git a/packages/core/src/Models/Price.php b/packages/core/src/Models/Price.php index 47bcdb726c..5554ea0e26 100644 --- a/packages/core/src/Models/Price.php +++ b/packages/core/src/Models/Price.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Casts\Price as CastsPrice; use Lunar\Base\Traits\HasMacros; @@ -49,40 +51,32 @@ protected static function newFactory(): PriceFactory /** * Return the priceable relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function priceable() + public function priceable(): MorphTo { return $this->morphTo(); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function currency() + public function currency(): BelongsTo { return $this->belongsTo(Currency::class); } /** * Return the customer group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customerGroup() + public function customerGroup(): BelongsTo { return $this->belongsTo(CustomerGroup::class); } /** * Return the price exclusive of tax. - * - * @return \Lunar\DataTypes\Price */ - public function priceExTax() + public function priceExTax(): \Lunar\DataTypes\Price { if (! prices_inc_tax()) { return $this->price; @@ -97,10 +91,8 @@ public function priceExTax() /** * Return the price inclusive of tax. - * - * @return \Lunar\DataTypes\Price */ - public function priceIncTax() + public function priceIncTax(): int|\Lunar\DataTypes\Price { if (prices_inc_tax()) { return $this->price; @@ -114,10 +106,8 @@ public function priceIncTax() /** * Return the total tax rate amount within the predefined tax zone for the related priceable - * - * @return int|float */ - protected function getPriceableTaxRate() + protected function getPriceableTaxRate(): int|float { return Blink::once('price_tax_rate_'.$this->priceable->getTaxClass()->id, function () { $taxZone = TaxZone::where('default', '=', 1)->first(); diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php index 8ff5e753de..795bc197f9 100644 --- a/packages/core/src/Models/Product.php +++ b/packages/core/src/Models/Product.php @@ -4,8 +4,12 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; +use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; @@ -79,50 +83,40 @@ protected static function newFactory(): ProductFactory /** * Returns the attributes to be stored against this model. - * - * @return array */ - public function mappedAttributes() + public function mappedAttributes(): Collection { return $this->productType->mappedAttributes; } /** * Return the product type relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function productType() + public function productType(): BelongsTo { return $this->belongsTo(ProductType::class); } /** * Return the product images relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphMany */ - public function images() + public function images(): MorphMany { return $this->media()->where('collection_name', 'images'); } /** * Return the product variants relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function variants() + public function variants(): HasMany { return $this->hasMany(ProductVariant::class); } /** * Return the product collections relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function collections() + public function collections(): BelongsToMany { return $this->belongsToMany( Collection::class, @@ -132,44 +126,32 @@ public function collections() /** * Return the associations relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function associations() + public function associations(): HasMany { return $this->hasMany(ProductAssociation::class, 'product_parent_id'); } /** * Return the associations relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function inverseAssociations() + public function inverseAssociations(): HasMany { return $this->hasMany(ProductAssociation::class, 'product_target_id'); } /** * Associate a product to another with a type. - * - * @param mixed $product - * @param string $type - * @return void */ - public function associate($product, $type) + public function associate(mixed $product, string $type): void { Associate::dispatch($this, $product, $type); } /** * Dissociate a product to another with a type. - * - * @param mixed $product - * @param string $type - * @return void */ - public function dissociate($product, $type = null) + public function dissociate(mixed $product, string $type = null): void { Dissociate::dispatch($this, $product, $type); } @@ -195,31 +177,24 @@ public function customerGroups(): BelongsToMany /** * Return the brand relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function brand() + public function brand(): BelongsTo { return $this->belongsTo(Brand::class); } /** * Apply the status scope. - * - * @param string $status - * @return Builder */ - public function scopeStatus(Builder $query, $status) + public function scopeStatus(Builder $query, string $status): Builder { return $query->whereStatus($status); } /** * Return the prices relationship. - * - * @return HasManyThrough */ - public function prices() + public function prices(): HasManyThrough { return $this->hasManyThrough( Price::class, diff --git a/packages/core/src/Models/ProductAssociation.php b/packages/core/src/Models/ProductAssociation.php index c2b6d3f896..285b1623be 100644 --- a/packages/core/src/Models/ProductAssociation.php +++ b/packages/core/src/Models/ProductAssociation.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\ProductAssociationFactory; @@ -22,12 +23,12 @@ class ProductAssociation extends BaseModel use HasMacros; /** - * Define the cross sell type. + * Define the cross-sell type. */ const CROSS_SELL = 'cross-sell'; /** - * Define the up sell type. + * Define the upsell type. */ const UP_SELL = 'up-sell'; @@ -57,61 +58,48 @@ protected static function newFactory(): ProductAssociationFactory /** * Return the parent relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function parent() + public function parent(): BelongsTo { return $this->belongsTo(Product::class, 'product_parent_id'); } /** * Return the parent relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function target() + public function target(): BelongsTo { return $this->belongsTo(Product::class, 'product_target_id'); } /** - * Apply the cross sell scope. - * - * @return void + * Apply the cross-sell scope. */ - public function scopeCrossSell(Builder $query) + public function scopeCrossSell(Builder $query): void { $query->type(self::CROSS_SELL); } /** - * Apply the up sell scope. - * - * @return void + * Apply the upsell scope. */ - public function scopeUpSell(Builder $query) + public function scopeUpSell(Builder $query): void { $query->type(self::UP_SELL); } /** * Apply the up alternate scope. - * - * @return void */ - public function scopeAlternate(Builder $query) + public function scopeAlternate(Builder $query): void { $query->type(self::ALTERNATE); } /** * Apply the type scope. - * - * @param string $type - * @return void */ - public function scopeType(Builder $query, $type) + public function scopeType(Builder $query, string $type): Builder { return $query->whereType($type); } diff --git a/packages/core/src/Models/ProductOption.php b/packages/core/src/Models/ProductOption.php index bb90f21709..bbc05abf6c 100644 --- a/packages/core/src/Models/ProductOption.php +++ b/packages/core/src/Models/ProductOption.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Base\Traits\HasMedia; @@ -48,12 +49,12 @@ protected static function newFactory(): ProductOptionFactory return ProductOptionFactory::new(); } - public function getNameAttribute($value) + public function getNameAttribute(string $value = null): mixed { return json_decode($value); } - protected function setNameAttribute($value) + protected function setNameAttribute(mixed $value): void { $this->attributes['name'] = json_encode($value); } @@ -77,9 +78,9 @@ protected function label(): Attribute /** * Get the values. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function values() + public function values(): HasMany { return $this->hasMany(ProductOptionValue::class)->orderBy('position'); } diff --git a/packages/core/src/Models/ProductOptionValue.php b/packages/core/src/Models/ProductOptionValue.php index cb450274c9..d9f164ab7b 100644 --- a/packages/core/src/Models/ProductOptionValue.php +++ b/packages/core/src/Models/ProductOptionValue.php @@ -4,6 +4,8 @@ use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Base\Traits\HasMedia; @@ -51,22 +53,22 @@ protected static function newFactory(): ProductOptionValueFactory */ protected $guarded = []; - protected function setNameAttribute($value) + public function getNameAttribute(string $value = null): mixed { - $this->attributes['name'] = json_encode($value); + return json_decode($value); } - public function getNameAttribute($value) + protected function setNameAttribute(mixed $value): void { - return json_decode($value); + $this->attributes['name'] = json_encode($value); } - public function option() + public function option(): BelongsTo { return $this->belongsTo(ProductOption::class, 'product_option_id'); } - public function variants() + public function variants(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/ProductType.php b/packages/core/src/Models/ProductType.php index 02106b0baa..3f0baea3df 100644 --- a/packages/core/src/Models/ProductType.php +++ b/packages/core/src/Models/ProductType.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasAttributes; use Lunar\Base\Traits\HasMacros; @@ -38,10 +40,8 @@ protected static function newFactory(): ProductTypeFactory /** * Get the mapped attributes relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function mappedAttributes() + public function mappedAttributes(): MorphToMany { $prefix = config('lunar.database.table_prefix'); @@ -54,30 +54,24 @@ public function mappedAttributes() /** * Return the product attributes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function productAttributes() + public function productAttributes(): MorphToMany { return $this->mappedAttributes()->whereAttributeType(Product::class); } /** * Return the variant attributes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function variantAttributes() + public function variantAttributes(): MorphToMany { return $this->mappedAttributes()->whereAttributeType(ProductVariant::class); } /** * Get the products relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function products() + public function products(): HasMany { return $this->hasMany(Product::class); } diff --git a/packages/core/src/Models/ProductVariant.php b/packages/core/src/Models/ProductVariant.php index 53f16d66cb..61c78212cd 100644 --- a/packages/core/src/Models/ProductVariant.php +++ b/packages/core/src/Models/ProductVariant.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Collection; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; @@ -79,30 +81,24 @@ protected static function newFactory(): ProductVariantFactory /** * The related product. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function product() + public function product(): BelongsTo { return $this->belongsTo(Product::class)->withTrashed(); } /** * Return the tax class relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxClass() + public function taxClass(): BelongsTo { return $this->belongsTo(TaxClass::class); } /** * Return the related product option values. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function values() + public function values(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -137,7 +133,7 @@ public function getTaxClass(): TaxClass }); } - public function getTaxReference() + public function getTaxReference(): ?string { return $this->tax_ref; } @@ -145,7 +141,7 @@ public function getTaxReference() /** * {@inheritDoc} */ - public function getType() + public function getType(): string { return $this->shippable ? 'physical' : 'digital'; } @@ -153,7 +149,7 @@ public function getType() /** * {@inheritDoc} */ - public function isShippable() + public function isShippable(): bool { return $this->shippable; } @@ -161,7 +157,7 @@ public function isShippable() /** * {@inheritDoc} */ - public function getDescription() + public function getDescription(): string { return $this->product->translateAttribute('name'); } @@ -169,7 +165,7 @@ public function getDescription() /** * {@inheritDoc} */ - public function getOption() + public function getOption(): string { return $this->values->map(fn ($value) => $value->translate('name'))->join(', '); } @@ -177,7 +173,7 @@ public function getOption() /** * {@inheritDoc} */ - public function getOptions() + public function getOptions(): Collection { return $this->values->map(fn ($value) => $value->translate('name')); } @@ -185,12 +181,12 @@ public function getOptions() /** * {@inheritDoc} */ - public function getIdentifier() + public function getIdentifier(): string { return $this->sku; } - public function images() + public function images(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -200,7 +196,7 @@ public function images() ->withTimestamps(); } - public function getThumbnail() + public function getThumbnail(): ?Media { return $this->images->first(function ($media) { return (bool) $media->pivot?->primary; diff --git a/packages/core/src/Models/State.php b/packages/core/src/Models/State.php index 87a943ace8..362abf7deb 100644 --- a/packages/core/src/Models/State.php +++ b/packages/core/src/Models/State.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\StateFactory; @@ -38,10 +39,8 @@ protected static function newFactory(): StateFactory /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/Tag.php b/packages/core/src/Models/Tag.php index 7b50089504..6b69397ff0 100644 --- a/packages/core/src/Models/Tag.php +++ b/packages/core/src/Models/Tag.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TagFactory; @@ -34,9 +35,8 @@ protected static function newFactory(): TagFactory */ protected $guarded = []; - public function taggable() + public function taggable(): MorphTo { return $this->morphTo(); } - } diff --git a/packages/core/src/Models/TaxClass.php b/packages/core/src/Models/TaxClass.php index 5331adc650..9c54609291 100644 --- a/packages/core/src/Models/TaxClass.php +++ b/packages/core/src/Models/TaxClass.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasDefaultRecord; use Lunar\Base\Traits\HasMacros; @@ -58,20 +59,16 @@ protected static function newFactory(): TaxClassFactory /** * Return the tax rate amounts relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function taxRateAmounts() + public function taxRateAmounts(): HasMany { return $this->hasMany(TaxRateAmount::class); } /** * Return the ProductVariants relationship. - * - * @return HasMany */ - public function productVariants() + public function productVariants(): HasMany { return $this->hasMany(ProductVariant::class); } diff --git a/packages/core/src/Models/TaxRate.php b/packages/core/src/Models/TaxRate.php index 7faebfb098..1e04eb33b1 100644 --- a/packages/core/src/Models/TaxRate.php +++ b/packages/core/src/Models/TaxRate.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxRateFactory; @@ -38,20 +40,16 @@ protected static function newFactory(): TaxRateFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the tax rate amounts relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function taxRateAmounts() + public function taxRateAmounts(): HasMany { return $this->hasMany(TaxRateAmount::class); } diff --git a/packages/core/src/Models/TaxRateAmount.php b/packages/core/src/Models/TaxRateAmount.php index 90ad50d962..6113145653 100644 --- a/packages/core/src/Models/TaxRateAmount.php +++ b/packages/core/src/Models/TaxRateAmount.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxRateAmountFactory; @@ -45,20 +46,16 @@ protected static function newFactory(): TaxRateAmountFactory /** * Return the tax rate relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxRate() + public function taxRate(): BelongsTo { return $this->belongsTo(TaxRate::class); } /** * Return the tax class relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxClass() + public function taxClass(): BelongsTo { return $this->belongsTo(TaxClass::class); } diff --git a/packages/core/src/Models/TaxZone.php b/packages/core/src/Models/TaxZone.php index 0f653a7c99..0e64d550c1 100644 --- a/packages/core/src/Models/TaxZone.php +++ b/packages/core/src/Models/TaxZone.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasDefaultRecord; use Lunar\Base\Traits\HasMacros; @@ -52,60 +54,48 @@ protected static function newFactory(): TaxZoneFactory /** * Return the countries relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function countries() + public function countries(): HasMany { return $this->hasMany(TaxZoneCountry::class); } /** * Return the states relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function states() + public function states(): HasMany { return $this->hasMany(TaxZoneState::class); } /** * Return the postcodes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function postcodes() + public function postcodes(): HasMany { return $this->hasMany(TaxZonePostcode::class); } /** * Return the customer groups relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function customerGroups() + public function customerGroups(): HasMany { return $this->hasMany(TaxZoneCustomerGroup::class); } /** * Return the tax rates relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function taxRates() + public function taxRates(): HasMany { return $this->hasMany(TaxRate::class); } /** * Return the tax amounts relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough */ - public function taxAmounts() + public function taxAmounts(): HasManyThrough { return $this->hasManyThrough(TaxRateAmount::class, TaxRate::class); } diff --git a/packages/core/src/Models/TaxZoneCountry.php b/packages/core/src/Models/TaxZoneCountry.php index 517ca82548..49fa7f4cd2 100644 --- a/packages/core/src/Models/TaxZoneCountry.php +++ b/packages/core/src/Models/TaxZoneCountry.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZoneCountryFactory; @@ -37,20 +38,16 @@ protected static function newFactory(): TaxZoneCountryFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the country relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/TaxZoneCustomerGroup.php b/packages/core/src/Models/TaxZoneCustomerGroup.php index 1f94965117..1bd4fa3bcc 100644 --- a/packages/core/src/Models/TaxZoneCustomerGroup.php +++ b/packages/core/src/Models/TaxZoneCustomerGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZoneCustomerGroupFactory; @@ -37,20 +38,16 @@ protected static function newFactory(): TaxZoneCustomerGroupFactory /** * Return the customer group relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customerGroup() + public function customerGroup(): BelongsTo { return $this->belongsTo(CustomerGroup::class); } /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } diff --git a/packages/core/src/Models/TaxZonePostcode.php b/packages/core/src/Models/TaxZonePostcode.php index ad2b1c9fa2..a5ce608e09 100644 --- a/packages/core/src/Models/TaxZonePostcode.php +++ b/packages/core/src/Models/TaxZonePostcode.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZonePostcodeFactory; @@ -38,20 +39,16 @@ protected static function newFactory(): TaxZonePostcodeFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the country relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/TaxZoneState.php b/packages/core/src/Models/TaxZoneState.php index 18ae418b55..e0fe32bf52 100644 --- a/packages/core/src/Models/TaxZoneState.php +++ b/packages/core/src/Models/TaxZoneState.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZoneStateFactory; @@ -37,20 +38,16 @@ protected static function newFactory(): TaxZoneStateFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the state relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function state() + public function state(): BelongsTo { return $this->belongsTo(State::class); } diff --git a/packages/core/src/Models/Transaction.php b/packages/core/src/Models/Transaction.php index 6e3f03d22c..0386c5396e 100644 --- a/packages/core/src/Models/Transaction.php +++ b/packages/core/src/Models/Transaction.php @@ -4,6 +4,8 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Lunar\Base\BaseModel; use Lunar\Base\Casts\Price; use Lunar\Base\Traits\HasMacros; @@ -59,20 +61,16 @@ protected static function newFactory(): TransactionFactory /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function order() + public function order(): BelongsTo { return $this->belongsTo(Order::class); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough */ - public function currency() + public function currency(): HasOneThrough { return $this->hasOneThrough( Currency::class, diff --git a/packages/core/src/Models/Url.php b/packages/core/src/Models/Url.php index 4b4bed8cf5..caa9c1e8dd 100644 --- a/packages/core/src/Models/Url.php +++ b/packages/core/src/Models/Url.php @@ -3,6 +3,9 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; +use Illuminate\Database\Query\Builder; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\UrlFactory; @@ -49,31 +52,24 @@ protected static function newFactory(): UrlFactory /** * Return the element relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function element() + public function element(): MorphTo { return $this->morphTo(); } /** * Return the language relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function language() + public function language(): BelongsTo { return $this->belongsTo(Language::class); } /** * Return the query scope for default. - * - * @param \Illuminate\Database\Query\Builder $query - * @return \Illuminate\Database\Query\Builder */ - public function scopeDefault($query) + public function scopeDefault(Builder $query): Builder { return $query->whereDefault(true); } From 7c2e8cffb954f4a5a1bacd69363779c145340914 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Mon, 15 Jan 2024 08:58:59 +0000 Subject: [PATCH 04/10] Merge in 0.7 to 0.8 branch (#1474) --- docs/core/reference/carts.md | 2 +- docs/package.json | 1 + packages/admin/resources/lang/en/partials.php | 1 - .../Components/Orders/OrderStatus.php | 4 +- .../Attributes/AttributeGroupEdit.php | 5 +- .../Components/Orders/OrderShowTest.php | 2 +- .../Product/ProductOptionCreateTest.php | 60 +++++++++---------- .../Product/ProductOptionValueCreateTest.php | 4 +- ...00010_add_type_to_brand_discount_table.php | 2 +- ..._add_type_to_collection_discount_table.php | 2 +- .../database/state/ConvertTaxbreakdown.php | 8 +-- .../src/Actions/Taxes/GetTaxZoneCountry.php | 3 +- packages/core/src/Base/Casts/TaxBreakdown.php | 9 +-- .../core/src/Base/Traits/LogsActivity.php | 25 +++++++- packages/core/src/DiscountTypes/AmountOff.php | 22 +++---- .../core/src/Managers/DiscountManager.php | 18 ++++-- .../src/Managers/StorefrontSessionManager.php | 14 ++--- packages/core/src/Models/Order.php | 7 +++ packages/core/src/Models/OrderAddress.php | 3 +- packages/core/src/Models/Product.php | 1 - .../src/Pipelines/Cart/CalculateLines.php | 2 +- .../Unit/Actions/Taxes/GetTaxZoneTest.php | 1 - .../Unit/DiscountTypes/AmountOffTest.php | 14 ++--- packages/core/tests/Unit/Models/CartTest.php | 1 + packages/core/tests/Unit/Models/OrderTest.php | 2 +- .../Pipelines/Cart/CalculateLinesTest.php | 4 +- .../tests/Unit/Search/OrderIndexerTest.php | 2 +- .../src/DatabaseEngine.php | 2 +- 28 files changed, 125 insertions(+), 96 deletions(-) diff --git a/docs/core/reference/carts.md b/docs/core/reference/carts.md index 2074df3e1b..b28bf3625c 100644 --- a/docs/core/reference/carts.md +++ b/docs/core/reference/carts.md @@ -279,7 +279,7 @@ CartSession::add($purchasable, $quantity); ```php CartSession::addLines([ [ - 'id' => 1, + 'purchasable' => \Lunar\Models\ProductVariant::find(123), 'quantity' => 25, 'meta' => ['foo' => 'bar'], ], diff --git a/docs/package.json b/docs/package.json index 3289b08a2a..806970f62c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,4 +1,5 @@ { + "type": "module", "devDependencies": { "vitepress": "^1.0.0-rc.31" }, diff --git a/packages/admin/resources/lang/en/partials.php b/packages/admin/resources/lang/en/partials.php index 1a40812a24..3440c54d23 100644 --- a/packages/admin/resources/lang/en/partials.php +++ b/packages/admin/resources/lang/en/partials.php @@ -97,7 +97,6 @@ 'discounts.limitations.limitation' => 'Limitation', 'discounts.limitations.exclusion' => 'Exclusion', /** - * Product Collections. */ 'products.collections.heading' => 'Collections', diff --git a/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php b/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php index ccbd82f88e..0ee274e773 100644 --- a/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php +++ b/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php @@ -133,7 +133,7 @@ public function getPreviewHtmlProperty() { $mailer = $this->availableMailers[$this->previewTemplate] ?? null; - if (!$mailer) { + if (! $mailer) { return 'Unable to load preview'; } @@ -169,7 +169,7 @@ public function updateStatus() if (method_exists($mailable, 'render')) { } - $storedPath = 'orders/activity/' . Str::random() . '.html'; + $storedPath = 'orders/activity/'.Str::random().'.html'; $storedMailer = Storage::put( $storedPath, diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php b/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php index 6c256b2fec..70b6128be3 100644 --- a/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php +++ b/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php @@ -76,16 +76,15 @@ public function create() $handle = Str::handle("{$this->typeHandle}_{$this->attributeGroup->translate('name')}"); $this->attributeGroup->handle = $handle; - $uniquenessConstraint = 'unique:' . get_class($this->attributeGroup) . ',handle'; + $uniquenessConstraint = 'unique:'.get_class($this->attributeGroup).',handle'; if ($this->attributeGroup->id) { - $uniquenessConstraint .= ',' . $this->attributeGroup->id; + $uniquenessConstraint .= ','.$this->attributeGroup->id; } $this->validate([ 'attributeGroup.handle' => $uniquenessConstraint, ]); - if ($this->attributeGroup->id) { $this->attributeGroup->save(); $this->emit('attribute-group-edit.updated', $this->attributeGroup->id); diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php index 3724884e98..111652e89f 100644 --- a/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php @@ -51,7 +51,7 @@ public function can_mount_component() 'currency_code' => Currency::getDefault()->code, 'meta' => [ 'foo' => 'bar', - ] + ], ]); $this->assertCount(0, $order->lines); diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php index d06bb3639a..19da7abd13 100644 --- a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php @@ -12,34 +12,34 @@ class ProductOptionCreateTest extends TestCase { - use RefreshDatabase; - - public function setUp(): void - { - parent::setUp(); - - Language::factory()->create([ - 'default' => true, - 'code' => 'en', - ]); - } - - /** - * @test - * */ - public function can_populate_product_option_data() - { - $staff = Staff::factory()->create([ - 'admin' => true, - ]); - - LiveWire::actingAs($staff, 'staff') - ->test(OptionsIndex::class) - ->set('newProductOption.name.' . Language::getDefault()->code, 'Size') - ->call('createOption'); - - $this->assertDatabaseHas((new ProductOption())->getTable(), [ - 'name' => json_encode([Language::getDefault()->code => 'Size']), - ]); - } + use RefreshDatabase; + + public function setUp(): void + { + parent::setUp(); + + Language::factory()->create([ + 'default' => true, + 'code' => 'en', + ]); + } + + /** + * @test + * */ + public function can_populate_product_option_data() + { + $staff = Staff::factory()->create([ + 'admin' => true, + ]); + + LiveWire::actingAs($staff, 'staff') + ->test(OptionsIndex::class) + ->set('newProductOption.name.'.Language::getDefault()->code, 'Size') + ->call('createOption'); + + $this->assertDatabaseHas((new ProductOption())->getTable(), [ + 'name' => json_encode([Language::getDefault()->code => 'Size']), + ]); + } } diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php index 46ac803a35..21fb1b0e36 100644 --- a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php @@ -37,12 +37,12 @@ public function can_populate_product_option_data() LiveWire::actingAs($staff, 'staff') ->test(OptionEdit::class, ['productOption' => $option]) - ->set('newProductOptionValue.name.' . Language::getDefault()->code, 'Size') + ->set('newProductOptionValue.name.'.Language::getDefault()->code, 'Size') ->call('createOptionValue'); $this->assertDatabaseHas((new ProductOptionValue())->getTable(), [ 'product_option_id' => $option->id, - 'name' => json_encode([Language::getDefault()->code => 'Size']) + 'name' => json_encode([Language::getDefault()->code => 'Size']), ]); }); } diff --git a/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php b/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php index e6e75585a9..0155fec8ae 100644 --- a/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php +++ b/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php @@ -17,6 +17,6 @@ public function down() { Schema::table($this->prefix.'brand_discount', function ($table) { $table->dropColumn('type'); - }); + }); } } diff --git a/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php b/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php index ffd424e2b8..ee6e60477e 100644 --- a/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php +++ b/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php @@ -17,6 +17,6 @@ public function down() { Schema::table($this->prefix.'collection_discount', function ($table) { $table->dropColumn('type'); - }); + }); } } diff --git a/packages/core/database/state/ConvertTaxbreakdown.php b/packages/core/database/state/ConvertTaxbreakdown.php index e3fbf6a505..2613af1c48 100644 --- a/packages/core/database/state/ConvertTaxbreakdown.php +++ b/packages/core/database/state/ConvertTaxbreakdown.php @@ -15,10 +15,9 @@ public function prepare() public function run() { DB::usingConnection(config('lunar.database.connection') ?: DB::getDefaultConnection(), function () { - $prefix = config('lunar.database.table_prefix'); $updateTime = now(); - + if ($this->canRunOnOrders()) { DB::table("{$prefix}orders") ->whereJsonContainsKey("{$prefix}orders.tax_breakdown->[0]->total") @@ -42,7 +41,7 @@ public function run() } }); } - + if ($this->canRunOnOrderLines()) { DB::table("{$prefix}order_lines") ->whereJsonContainsKey("{$prefix}order_lines.tax_breakdown->[0]->total") @@ -57,7 +56,7 @@ public function run() DB::transaction(function () use ($prefix, $updateTime, $rows) { foreach ($rows as $row) { $originalBreakdown = json_decode($row->tax_breakdown, true); - + DB::table("{$prefix}order_lines")->where('id', '=', $row->id)->update([ 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { return [ @@ -74,7 +73,6 @@ public function run() }); }); } - }); } diff --git a/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php b/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php index 892097a4fc..a73c444e90 100644 --- a/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php +++ b/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php @@ -14,7 +14,7 @@ public function execute($countryId) return $taxZone; } - if (!$taxZone) { + if (! $taxZone) { return null; } } @@ -22,7 +22,6 @@ public function execute($countryId) /** * Return the zone or zones which match this country. * - * @param int $countryId * @return TaxZoneCountry|null */ protected function getZone(int $countryId) diff --git a/packages/core/src/Base/Casts/TaxBreakdown.php b/packages/core/src/Base/Casts/TaxBreakdown.php index 06faf834f2..fd61b3cd6b 100644 --- a/packages/core/src/Base/Casts/TaxBreakdown.php +++ b/packages/core/src/Base/Casts/TaxBreakdown.php @@ -26,9 +26,9 @@ public function get($model, $key, $value, $attributes) $breakdown->amounts = collect( json_decode($value, false) - )->mapWithKeys(function ($amount, $key) use ($model) { + )->mapWithKeys(function ($amount, $key) { $currency = BlinkFacade::once("currency_{$amount->currency_code}", function () use ($amount) { - return Currency::whereCode($amount->currency_code)->first(); + return Currency::whereCode($amount->currency_code)->first(); }); return [ @@ -51,8 +51,9 @@ public function get($model, $key, $value, $attributes) * @param string $key * @param Price $value * @param array $attributes - * @throws \Exception * @return array + * + * @throws \Exception */ public function set($model, $key, $value, $attributes) { @@ -82,7 +83,7 @@ public function set($model, $key, $value, $attributes) * * @param \Illuminate\Database\Eloquent\Model $model * @param string $key - * @param mixed $value + * @param mixed $value * @param array $attributes */ public function serialize($model, $key, $value, $attributes) diff --git a/packages/core/src/Base/Traits/LogsActivity.php b/packages/core/src/Base/Traits/LogsActivity.php index c43da2754f..72a81a9eb8 100644 --- a/packages/core/src/Base/Traits/LogsActivity.php +++ b/packages/core/src/Base/Traits/LogsActivity.php @@ -2,6 +2,7 @@ namespace Lunar\Base\Traits; +use Illuminate\Support\Arr; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity as SpatieLogsActivity; @@ -9,6 +10,8 @@ trait LogsActivity { use SpatieLogsActivity; + public static array $logExcept = []; + /** * Get the log options for the activity log. */ @@ -17,7 +20,25 @@ public function getActivitylogOptions(): LogOptions return LogOptions::defaults() ->useLogName('lunar') ->logAll() - ->dontSubmitEmptyLogs() - ->logExcept(['updated_at']); + ->logExcept(array_merge(['updated_at'], static::getActivitylogExcept())) + ->logOnlyDirty() + ->dontSubmitEmptyLogs(); + } + + public static function addActivitylogExcept(array|string $fields) + { + $fields = Arr::wrap($fields); + + static::$logExcept = array_merge(static::$logExcept, $fields); + } + + public static function getDefaultLogExcept(): array + { + return []; + } + + public static function getActivitylogExcept(): array + { + return array_merge(static::getDefaultLogExcept(), static::$logExcept); } } diff --git a/packages/core/src/DiscountTypes/AmountOff.php b/packages/core/src/DiscountTypes/AmountOff.php index 7219a809a7..2c098e4f95 100644 --- a/packages/core/src/DiscountTypes/AmountOff.php +++ b/packages/core/src/DiscountTypes/AmountOff.php @@ -110,28 +110,28 @@ private function applyFixedValue(array $values, Cart $cart): Cart $lines->filter(function ($line) { return $line->subTotalDiscounted->value > 0; }) - ->each(function($line) use ($affectedLines, $cart, &$remaining) { + ->each(function ($line) use ($affectedLines, $cart, &$remaining) { if ($remaining <= 0) { return; } - + $amountAvailable = min($line->subTotalDiscounted->value, $remaining); $remaining -= $amountAvailable; $newDiscountTotal = $line->discountTotal->value + $amountAvailable; - + $line->discountTotal = new Price( $newDiscountTotal, $cart->currency, 1 ); - + $line->subTotalDiscounted = new Price( $line->subTotal->value - $newDiscountTotal, $cart->currency, 1 ); - + if (! $affectedLines->first(function ($breakdownLine) use ($line) { return $breakdownLine->line == $line; })) { @@ -165,14 +165,14 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection { $collectionIds = $this->discount->collections->where('pivot.type', 'limitation')->pluck('id'); $collectionExclusionIds = $this->discount->collections->where('pivot.type', 'exclusion')->pluck('id'); - + $brandIds = $this->discount->brands->where('pivot.type', 'limitation')->pluck('id'); $brandExclusionIds = $this->discount->brands->where('pivot.type', 'exclusion')->pluck('id'); - + $productIds = $this->discount->purchasableLimitations ->reject(fn ($limitation) => ! $limitation->purchasable) ->map(fn ($limitation) => get_class($limitation->purchasable).'::'.$limitation->purchasable->id); - + $productExclusionIds = $this->discount->purchasableExclusions ->reject(fn ($limitation) => ! $limitation->purchasable) ->map(fn ($limitation) => get_class($limitation->purchasable).'::'.$limitation->purchasable->id); @@ -186,7 +186,7 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection })->exists(); }); } - + if ($collectionExclusionIds->count()) { $lines = $lines->reject(function ($line) use ($collectionExclusionIds) { return $line->purchasable->product()->whereHas('collections', function ($query) use ($collectionExclusionIds) { @@ -200,7 +200,7 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection return ! $brandIds->contains($line->purchasable->product->brand_id); }); } - + if ($brandExclusionIds->count()) { $lines = $lines->reject(function ($line) use ($brandExclusionIds) { return $brandExclusionIds->contains($line->purchasable->product->brand_id); @@ -212,7 +212,7 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection return $productIds->contains(get_class($line->purchasable).'::'.$line->purchasable->id) || $productIds->contains(get_class($line->purchasable->product).'::'.$line->purchasable->product->id); }); } - + if ($productExclusionIds->count()) { $lines = $lines->reject(function ($line) use ($productExclusionIds) { return $productExclusionIds->contains(get_class($line->purchasable).'::'.$line->purchasable->id) || $productExclusionIds->contains(get_class($line->purchasable->product).'::'.$line->purchasable->product->id); diff --git a/packages/core/src/Managers/DiscountManager.php b/packages/core/src/Managers/DiscountManager.php index 153883304c..9337b57a61 100644 --- a/packages/core/src/Managers/DiscountManager.php +++ b/packages/core/src/Managers/DiscountManager.php @@ -138,18 +138,24 @@ public function getDiscounts(Cart $cart = null): Collection function ($query, $value) { return $query->where(function ($query) use ($value) { return $query->where(fn ($query) => $query->products( - $value->lines->pluck('purchasable.product_id')->filter()->values() - ) - ) + $value->lines->pluck('purchasable.product_id')->filter()->values() + ) + ) ->orWhere(fn ($query) => $query->productVariants( - $value->lines->pluck('purchasable.id')->filter()->values() - ) + $value->lines->pluck('purchasable.id')->filter()->values() + ) ); }); } )->when( $cart?->coupon_code, - fn ($query, $value) => $query->where('coupon', '=', $value)->orWhere(fn ($query) => $query->whereNull('coupon')->orWhere('coupon', '')), + function ($query, $value) { + return $query->where(function ($query) use ($value) { + $query->where('coupon', $value) + ->orWhereNull('coupon') + ->orWhere('coupon', ''); + }); + }, fn ($query, $value) => $query->whereNull('coupon')->orWhere('coupon', '') )->orderBy('priority', 'desc') ->orderBy('id') diff --git a/packages/core/src/Managers/StorefrontSessionManager.php b/packages/core/src/Managers/StorefrontSessionManager.php index 04b8bc93db..9e3fa9e04a 100644 --- a/packages/core/src/Managers/StorefrontSessionManager.php +++ b/packages/core/src/Managers/StorefrontSessionManager.php @@ -80,7 +80,7 @@ public function initCustomerGroups() ); if ($this->customerGroups?->count()) { - if (! $groupHandles) { + if ($groupHandles->isEmpty()) { return $this->setCustomerGroups( $this->customerGroups ); @@ -89,16 +89,14 @@ public function initCustomerGroups() return $this->customerGroups; } - if (! $this->customerGroups?->count()) { - return $this->setCustomerGroups( - collect([ - CustomerGroup::getDefault(), - ]) - ); + if (! $groupHandles->isEmpty()) { + return $this->customerGroups = CustomerGroup::whereIn('handle', $groupHandles)->get(); } return $this->setCustomerGroups( - CustomerGroup::whereIn('handle', $groupHandles)->get() + collect([ + CustomerGroup::getDefault(), + ]) ); } diff --git a/packages/core/src/Models/Order.php b/packages/core/src/Models/Order.php index 0ec0318acc..e2f3a25023 100644 --- a/packages/core/src/Models/Order.php +++ b/packages/core/src/Models/Order.php @@ -244,4 +244,11 @@ public function isPlaced(): bool { return ! blank($this->placed_at); } + + public static function getDefaultLogExcept(): array + { + return [ + 'status', + ]; + } } diff --git a/packages/core/src/Models/OrderAddress.php b/packages/core/src/Models/OrderAddress.php index e5e285e5a4..59bb73908f 100644 --- a/packages/core/src/Models/OrderAddress.php +++ b/packages/core/src/Models/OrderAddress.php @@ -72,8 +72,9 @@ protected static function newFactory(): OrderAddressFactory 'delivery_instructions', 'contact_email', 'contact_phone', - 'meta', 'type', + 'shipping_option', + 'meta', ]; /** diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php index 795bc197f9..01d4ea17a8 100644 --- a/packages/core/src/Models/Product.php +++ b/packages/core/src/Models/Product.php @@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\MorphMany; -use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; diff --git a/packages/core/src/Pipelines/Cart/CalculateLines.php b/packages/core/src/Pipelines/Cart/CalculateLines.php index 04b7806872..06599eb189 100644 --- a/packages/core/src/Pipelines/Cart/CalculateLines.php +++ b/packages/core/src/Pipelines/Cart/CalculateLines.php @@ -26,7 +26,7 @@ public function handle(Cart $cart, Closure $next) return $cartLine; }); - + $unitPrice = $cartLine->unitPrice->unitDecimal(false) * $cart->currency->factor; $subTotal = (int) round($unitPrice * $cartLine->quantity, $cart->currency->decimal_places); diff --git a/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php index 632888a346..94e0c3781f 100644 --- a/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php +++ b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php @@ -4,7 +4,6 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Lunar\Actions\Taxes\GetTaxZone; -use Lunar\Actions\Taxes\GetTaxZoneCountry; use Lunar\Models\Address; use Lunar\Models\Country; use Lunar\Models\State; diff --git a/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php b/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php index 55c9b944c7..857ac3b068 100644 --- a/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php +++ b/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php @@ -147,7 +147,7 @@ public function will_only_apply_to_lines_with_correct_brand() $this->assertEquals(100, $cart->discountTotal->value); $this->assertEquals(2280, $cart->total->value); } - + /** @test */ public function will_not_apply_to_lines_with_excluded_brand() { @@ -350,7 +350,7 @@ public function will_only_apply_to_lines_with_correct_product() $this->assertEquals(100, $cart->discountTotal->value); $this->assertEquals(2280, $cart->total->value); } - + /** @test */ public function will_only_apply_to_lines_with_correct_product_variant() { @@ -449,7 +449,7 @@ public function will_only_apply_to_lines_with_correct_product_variant() $this->assertEquals(100, $cart->discountTotal->value); $this->assertEquals(2280, $cart->total->value); } - + /** @test */ public function will_not_apply_to_lines_with_excluded_product() { @@ -544,11 +544,11 @@ public function will_not_apply_to_lines_with_excluded_product() ]); $cart = $cart->calculate(); - + $this->assertEquals(200, $cart->discountTotal->value); $this->assertEquals(3360, $cart->total->value); } - + /** @test */ public function will_not_apply_to_lines_with_excluded_product_variant() { @@ -643,7 +643,7 @@ public function will_not_apply_to_lines_with_excluded_product_variant() ]); $cart = $cart->calculate(); - + $this->assertEquals(200, $cart->discountTotal->value); $this->assertEquals(3360, $cart->total->value); } @@ -1619,7 +1619,7 @@ public function cannot_apply_discount_with_max_user_uses() $this->assertEquals(2400, $cart->total->value); $this->assertEquals(2000, $cart->subTotal->value); } - + /** * @test */ diff --git a/packages/core/tests/Unit/Models/CartTest.php b/packages/core/tests/Unit/Models/CartTest.php index 5d992f6952..411fd1ccbf 100644 --- a/packages/core/tests/Unit/Models/CartTest.php +++ b/packages/core/tests/Unit/Models/CartTest.php @@ -966,6 +966,7 @@ public function can_override_shipping_calculation() /** * @test + * * @group foofoo */ public function can_get_estimated_shipping() diff --git a/packages/core/tests/Unit/Models/OrderTest.php b/packages/core/tests/Unit/Models/OrderTest.php index 933c036366..5f693bf887 100644 --- a/packages/core/tests/Unit/Models/OrderTest.php +++ b/packages/core/tests/Unit/Models/OrderTest.php @@ -105,7 +105,7 @@ public function can_create_lines() 'placed_at' => now(), 'meta' => [ 'foo' => 'bar', - ] + ], ]); $this->assertCount(0, $order->lines); diff --git a/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php b/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php index 04ce64e440..c57d8f607b 100644 --- a/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php +++ b/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php @@ -19,6 +19,7 @@ class CalculateLinesTest extends TestCase /** * @test + * * @dataProvider providePurchasableData */ public function can_calculate_lines($expectedUnitPrice, $incomingUnitPrice, $unitQuantity) @@ -47,7 +48,6 @@ public function can_calculate_lines($expectedUnitPrice, $incomingUnitPrice, $uni 'quantity' => 1, ]); - $cart = app(CalculateLines::class)->handle($cart, function ($cart) { return $cart; }); @@ -79,7 +79,7 @@ public function providePurchasableData() '0.55', '5503', '100', - ] + ], ]; } } diff --git a/packages/core/tests/Unit/Search/OrderIndexerTest.php b/packages/core/tests/Unit/Search/OrderIndexerTest.php index 1ffaa3387a..722041e782 100644 --- a/packages/core/tests/Unit/Search/OrderIndexerTest.php +++ b/packages/core/tests/Unit/Search/OrderIndexerTest.php @@ -29,7 +29,7 @@ public function can_return_correct_searchable_data() 'placed_at' => now(), 'meta' => [ 'foo' => 'bar', - ] + ], ]); $data = app(OrderIndexer::class)->toSearchableArray($order); diff --git a/utils/scout-database-engine/src/DatabaseEngine.php b/utils/scout-database-engine/src/DatabaseEngine.php index d23f78b729..9448e67bf3 100644 --- a/utils/scout-database-engine/src/DatabaseEngine.php +++ b/utils/scout-database-engine/src/DatabaseEngine.php @@ -121,7 +121,7 @@ protected function getSearchQuery(Builder $builder) return SearchIndex::where('index', '=', $index) ->when( $builder->query, - fn ($query) => $query ->whereFullText('content', $builder->query.'*', ['mode' => 'boolean']) + fn ($query) => $query->whereFullText('content', $builder->query.'*', ['mode' => 'boolean']) ); } From ad25097134b30e311fb813159e0dd44b6266a835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9as=20Lundgren?= <1066486+adevade@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:01:17 +0100 Subject: [PATCH 05/10] Update dotfiles (#1349) --- .editorconfig | 15 +++++++++++++++ .gitattributes | 19 +++++++++++++++++++ .gitignore | 19 +++++++++++-------- packages/admin/.gitattributes | 7 +++++++ packages/core/.gitattributes | 7 +++++++ utils/livewire-tables/.gitattributes | 7 +++++++ utils/scout-database-engine/.gitattributes | 6 ++++++ 7 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 packages/admin/.gitattributes create mode 100644 packages/core/.gitattributes create mode 100644 utils/livewire-tables/.gitattributes create mode 100644 utils/scout-database-engine/.gitattributes diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..d5f28a4669 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_size = 4 +indent_style = space +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..2a32f9a50f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +* text=auto eol=lf + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +/docs export-ignore +/packages/**/tests export-ignore +/utils/**/tests export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/monorepo-builder.php export-ignore +/phpstan.neon.dist export-ignore +/phpunit.xml export-ignore +/pint.json export-ignore diff --git a/.gitignore b/.gitignore index 20283ccc21..cdcd513659 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,15 @@ -/vendor/ -composer.lock -/vendor -.phpunit.result.cache +/.DS_Store +/.fleet /.idea +/.nova +/.phpunit.cache /.vscode -node_modules/ -yarn.lock +/node_modules +/vendor + +.phpunit.result.cache +composer.lock package-lock.json -.DS_Store -.nova phpstan.neon +Thumbs.db +yarn.lock diff --git a/packages/admin/.gitattributes b/packages/admin/.gitattributes new file mode 100644 index 0000000000..7461527da1 --- /dev/null +++ b/packages/admin/.gitattributes @@ -0,0 +1,7 @@ +* text=auto eol=lf + +/.github export-ignore +/tests export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/phpunit.xml export-ignore diff --git a/packages/core/.gitattributes b/packages/core/.gitattributes new file mode 100644 index 0000000000..7461527da1 --- /dev/null +++ b/packages/core/.gitattributes @@ -0,0 +1,7 @@ +* text=auto eol=lf + +/.github export-ignore +/tests export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/phpunit.xml export-ignore diff --git a/utils/livewire-tables/.gitattributes b/utils/livewire-tables/.gitattributes new file mode 100644 index 0000000000..a982359967 --- /dev/null +++ b/utils/livewire-tables/.gitattributes @@ -0,0 +1,7 @@ +* text=auto eol=lf + +/tests export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/phpunit.xml export-ignore +/pint.json export-ignore diff --git a/utils/scout-database-engine/.gitattributes b/utils/scout-database-engine/.gitattributes new file mode 100644 index 0000000000..8462d18200 --- /dev/null +++ b/utils/scout-database-engine/.gitattributes @@ -0,0 +1,6 @@ +* text=auto eol=lf + +/tests export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/phpunit.xml.dist export-ignore From a243a9188aa597b30867f333046b037ebbaa7aec Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Mon, 15 Jan 2024 09:05:28 +0000 Subject: [PATCH 06/10] Add command for cart pruning (#1303) This PR adds a command `lunar:prune:carts` and some new config params under `lunar.cart.prune_tables` to determine how pruning should be carried out. I opted for using a pipeline for amending the query, as we ultimately always seem to end up there. I've tried to default to some sensible settings (90 days, dont prune carts with orders associated). If pruning is enabled we automatically add a daily task rather then needing the developer to do it. --------- Co-authored-by: Glenn Jacobs --- docs/core/reference/carts.md | 30 +++++++++++ packages/core/config/cart.php | 22 ++++++++ .../core/src/Console/Commands/PruneCarts.php | 54 +++++++++++++++++++ packages/core/src/LunarServiceProvider.php | 9 ++++ .../src/Pipelines/CartPrune/PruneAfter.php | 21 ++++++++ .../src/Pipelines/CartPrune/WithoutOrders.php | 16 ++++++ .../core/tests/Unit/Console/CartPruneTest.php | 45 ++++++++++++++++ 7 files changed, 197 insertions(+) create mode 100644 packages/core/src/Console/Commands/PruneCarts.php create mode 100644 packages/core/src/Pipelines/CartPrune/PruneAfter.php create mode 100644 packages/core/src/Pipelines/CartPrune/WithoutOrders.php create mode 100644 packages/core/tests/Unit/Console/CartPruneTest.php diff --git a/docs/core/reference/carts.md b/docs/core/reference/carts.md index b28bf3625c..d45dbe17d3 100644 --- a/docs/core/reference/carts.md +++ b/docs/core/reference/carts.md @@ -466,3 +466,33 @@ return [ ``` In most cases you won't need to change this. + +## Pruning cart data + +Over time you will experience a build up of carts in your database that you may want to regularly remove. + +You can enable automatic removal of these carts using the `lunar.carts.prune_tables.enabled` config. By setting this to `true` any carts without an order associated will be removed after 90 days. + +You can change the number of days carts are retained for using the `lunar.carts.prune_tables. prune_interval` config. + +If you have specific needs around pruning you can also change the `lunar.carts.prune_tables.pipelines` array to determine what carts should be removed. + + + +```php +return [ + // ... + 'prune_tables' => [ + + 'enabled' => false, + + 'pipelines' => [ + Lunar\Pipelines\CartPrune\PruneAfter::class, + Lunar\Pipelines\CartPrune\WithoutOrders::class, + ], + + 'prune_interval' => 90, // days + + ], +]; +``` diff --git a/packages/core/config/cart.php b/packages/core/config/cart.php index d444562051..d6e4abfe82 100644 --- a/packages/core/config/cart.php +++ b/packages/core/config/cart.php @@ -150,4 +150,26 @@ 'lines.purchasable.product', 'lines.cart.currency', ], + + /* + |-------------------------------------------------------------------------- + | Prune carts + |-------------------------------------------------------------------------- + | + | Should the cart models be pruned to prevent data build up and + | some settings controlling how pruning should be determined + | + */ + 'prune_tables' => [ + + 'enabled' => false, + + 'pipelines' => [ + Lunar\Pipelines\CartPrune\PruneAfter::class, + Lunar\Pipelines\CartPrune\WithoutOrders::class, + ], + + 'prune_interval' => 90, // days + + ], ]; diff --git a/packages/core/src/Console/Commands/PruneCarts.php b/packages/core/src/Console/Commands/PruneCarts.php new file mode 100644 index 0000000000..a950777e13 --- /dev/null +++ b/packages/core/src/Console/Commands/PruneCarts.php @@ -0,0 +1,54 @@ +info('Beginning prune'); + + $query = Cart::query(); + + $carts = app(Pipeline::class) + ->send($query) + ->through( + config('lunar.cart.prune_tables.pipelines', []) + )->then(function ($query) { + $query->chunk(200, function ($carts) { + $carts->each(function ($cart) { + Cart::where('merged_id', $cart->id)->update(['merged_id' => null]); + + $cart->lines()->delete(); + $cart->addresses()->delete(); + $cart->delete(); + }); + }); + }); + + $this->info('Prune complete'); + } +} diff --git a/packages/core/src/LunarServiceProvider.php b/packages/core/src/LunarServiceProvider.php index e74400fca4..b651a7c8a7 100644 --- a/packages/core/src/LunarServiceProvider.php +++ b/packages/core/src/LunarServiceProvider.php @@ -5,6 +5,7 @@ use Cartalyst\Converter\Laravel\Facades\Converter; use Illuminate\Auth\Events\Login; use Illuminate\Auth\Events\Logout; +use Illuminate\Console\Scheduling\Schedule; use Illuminate\Database\Events\MigrationsEnded; use Illuminate\Database\Events\MigrationsStarted; use Illuminate\Database\Events\NoPendingMigrations; @@ -39,6 +40,7 @@ use Lunar\Console\Commands\Import\AddressData; use Lunar\Console\Commands\MigrateGetCandy; use Lunar\Console\Commands\Orders\SyncNewCustomerOrders; +use Lunar\Console\Commands\PruneCarts; use Lunar\Console\Commands\ScoutIndexerCommand; use Lunar\Console\InstallLunar; use Lunar\Database\State\ConvertProductTypeAttributesToProducts; @@ -204,7 +206,14 @@ public function boot(): void ScoutIndexerCommand::class, MigrateGetCandy::class, SyncNewCustomerOrders::class, + PruneCarts::class, ]); + + if (config('lunar.cart.prune_tables.enabled', false)) { + $this->callAfterResolving(Schedule::class, function (Schedule $schedule) { + $schedule->command('lunar:prune:carts')->daily(); + }); + } } Arr::macro('permutate', [\Lunar\Utils\Arr::class, 'permutate']); diff --git a/packages/core/src/Pipelines/CartPrune/PruneAfter.php b/packages/core/src/Pipelines/CartPrune/PruneAfter.php new file mode 100644 index 0000000000..9efa40aca3 --- /dev/null +++ b/packages/core/src/Pipelines/CartPrune/PruneAfter.php @@ -0,0 +1,21 @@ +where('updated_at', '<=', now()->subDays($days)) + ->whereDoesntHave('lines', function ($query) use ($days) { + $query->where('updated_at', '>', now()->subDays($days)); + }); + + return $next($query); + } +} diff --git a/packages/core/src/Pipelines/CartPrune/WithoutOrders.php b/packages/core/src/Pipelines/CartPrune/WithoutOrders.php new file mode 100644 index 0000000000..1b2de9c63f --- /dev/null +++ b/packages/core/src/Pipelines/CartPrune/WithoutOrders.php @@ -0,0 +1,16 @@ +whereDoesntHave('orders'); + + return $next($query); + } +} diff --git a/packages/core/tests/Unit/Console/CartPruneTest.php b/packages/core/tests/Unit/Console/CartPruneTest.php new file mode 100644 index 0000000000..0d278afb6f --- /dev/null +++ b/packages/core/tests/Unit/Console/CartPruneTest.php @@ -0,0 +1,45 @@ +create(); + $channel = Channel::factory()->create(); + + $cart = Cart::create([ + 'currency_id' => $currency->id, + 'channel_id' => $channel->id, + 'meta' => ['foo' => 'bar'], + 'updated_at' => Carbon::now()->subDay(120), + ]); + + $cart = Cart::create([ + 'currency_id' => $currency->id, + 'channel_id' => $channel->id, + 'meta' => ['foo' => 'bar'], + 'updated_at' => Carbon::now()->subDay(20), + ]); + + $this->assertCount(2, Cart::query()->get()); + + $this->artisan('lunar:prune:carts'); + + $this->assertCount(1, Cart::query()->get()); + } +} From 23fce74314826ec42a0bf80699d25205caa59204 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:04:02 +0800 Subject: [PATCH 07/10] Allow non Lunar model to use StandardMediaConversions (#1494) --- packages/core/src/Base/StandardMediaConversions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/Base/StandardMediaConversions.php b/packages/core/src/Base/StandardMediaConversions.php index f31e3b820d..db364e2386 100644 --- a/packages/core/src/Base/StandardMediaConversions.php +++ b/packages/core/src/Base/StandardMediaConversions.php @@ -2,11 +2,12 @@ namespace Lunar\Base; +use Illuminate\Database\Eloquent\Model; use Spatie\Image\Manipulations; class StandardMediaConversions { - public function apply(BaseModel $model) + public function apply(Model $model) { $conversions = [ 'zoom' => [ From cbf08ebfb2b33b585eac1ca877627312aca021c7 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 30 Jan 2024 08:39:40 +0000 Subject: [PATCH 08/10] Fix discount product and variants purchasables query (#1487) --- .../core/src/Managers/DiscountManager.php | 15 +++++++------ packages/core/src/Models/Discount.php | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/core/src/Managers/DiscountManager.php b/packages/core/src/Managers/DiscountManager.php index 9337b57a61..baad221de9 100644 --- a/packages/core/src/Managers/DiscountManager.php +++ b/packages/core/src/Managers/DiscountManager.php @@ -138,16 +138,19 @@ public function getDiscounts(Cart $cart = null): Collection function ($query, $value) { return $query->where(function ($query) use ($value) { return $query->where(fn ($query) => $query->products( - $value->lines->pluck('purchasable.product_id')->filter()->values() - ) - ) - ->orWhere(fn ($query) => $query->productVariants( - $value->lines->pluck('purchasable.id')->filter()->values() + $value->lines->pluck('purchasable.product_id')->filter()->values(), + ['condition', 'limitation'] + ) ) + ->orWhere(fn ($query) => $query->productVariants( + $value->lines->pluck('purchasable.id')->filter()->values(), + ['condition', 'limitation'] + ) ); }); } - )->when( + ) + ->when( $cart?->coupon_code, function ($query, $value) { return $query->where(function ($query) use ($value) { diff --git a/packages/core/src/Models/Discount.php b/packages/core/src/Models/Discount.php index 88471e58e7..a756d4f658 100644 --- a/packages/core/src/Models/Discount.php +++ b/packages/core/src/Models/Discount.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Support\Arr; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasChannels; use Lunar\Base\Traits\HasCustomerGroups; @@ -167,20 +168,22 @@ public function scopeActive(Builder $query): Builder /** * Return the products scope. */ - public function scopeProducts(Builder $query, iterable $productIds = [], string $type = null): Builder + public function scopeProducts(Builder $query, iterable $productIds = [], array|string $types = []): Builder { if (is_array($productIds)) { $productIds = collect($productIds); } + $types = Arr::wrap($types); + return $query->where( - fn ($subQuery) => $subQuery->whereDoesntHave('purchasables') + fn ($subQuery) => $subQuery->whereDoesntHave('purchasables', fn ($query) => $query->when($types, fn ($query) => $query->whereIn('type', $types))) ->orWhereHas('purchasables', fn ($relation) => $relation->whereIn('purchasable_id', $productIds) ->wherePurchasableType(Product::class) ->when( - $type, - fn ($query) => $query->whereType($type) + $types, + fn ($query) => $query->whereIn('type', $types) ) ) ); @@ -189,20 +192,22 @@ public function scopeProducts(Builder $query, iterable $productIds = [], string /** * Return the product variants scope. */ - public function scopeProductVariants(Builder $query, iterable $variantIds = [], string $type = null): Builder + public function scopeProductVariants(Builder $query, iterable $variantIds = [], array|string $types = []): Builder { if (is_array($variantIds)) { $variantIds = collect($variantIds); } + $types = Arr::wrap($types); + return $query->where( - fn ($subQuery) => $subQuery->whereDoesntHave('purchasables') + fn ($subQuery) => $subQuery->whereDoesntHave('purchasables', fn ($query) => $query->when($types, fn ($query) => $query->whereIn('type', $types))) ->orWhereHas('purchasables', fn ($relation) => $relation->whereIn('purchasable_id', $variantIds) ->wherePurchasableType(ProductVariant::class) ->when( - $type, - fn ($query) => $query->whereType($type) + $types, + fn ($query) => $query->whereIn('type', $types) ) ) ); From d9cacea6fd4de4da43458bd23b990bd00ab4ceb9 Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Wed, 31 Jan 2024 16:34:03 +0100 Subject: [PATCH 09/10] Fix - Query scout database engine #1355 (#1484) This PR fix issue [#1355](https://github.com/lunarphp/lunar/issues/1355) DatabaseEngine no longer espace query on SQL The engine execute query without quote and generate syntax error on database server --- utils/scout-database-engine/src/DatabaseEngine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scout-database-engine/src/DatabaseEngine.php b/utils/scout-database-engine/src/DatabaseEngine.php index 9448e67bf3..b558fed1ab 100644 --- a/utils/scout-database-engine/src/DatabaseEngine.php +++ b/utils/scout-database-engine/src/DatabaseEngine.php @@ -121,7 +121,7 @@ protected function getSearchQuery(Builder $builder) return SearchIndex::where('index', '=', $index) ->when( $builder->query, - fn ($query) => $query->whereFullText('content', $builder->query.'*', ['mode' => 'boolean']) + fn ($query) => $query->whereFullText('content', '"'.$builder->query.'*"') ); } From 0cb016847fdfb9ff12a3d0e2be90bb0bf9b85bea Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 31 Jan 2024 15:37:57 +0000 Subject: [PATCH 10/10] Allow discount cache to be reset (#1486) This PR adds the ability to reset the DiscountManager query cache - this is necessary if you add a discount coupon and want to update the cart totals in the same request. --------- Co-authored-by: Glenn Jacobs --- docs/core/reference/discounts.md | 8 ++++++++ packages/core/src/Managers/DiscountManager.php | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/docs/core/reference/discounts.md b/docs/core/reference/discounts.md index 17a06e7e72..52a2782e5e 100644 --- a/docs/core/reference/discounts.md +++ b/docs/core/reference/discounts.md @@ -66,6 +66,14 @@ Discount::usable()->get(); Discount::products($productIds, $type = 'condition'); ``` +### Resetting the discount cache + +For performance reasons the applicable discounts are cached per request. If you need to reset this cache (for example after adding a discount code) you should call `resetDiscounts()`: + +```php +Discount::resetDiscounts(); +``` + ## Discount Purchasable You can relate a purchasable to a discount via this model. Each has a type for whether it's a `condition` or `reward`. diff --git a/packages/core/src/Managers/DiscountManager.php b/packages/core/src/Managers/DiscountManager.php index baad221de9..d3dc823185 100644 --- a/packages/core/src/Managers/DiscountManager.php +++ b/packages/core/src/Managers/DiscountManager.php @@ -212,6 +212,13 @@ public function apply(Cart $cart): Cart return $cart; } + public function resetDiscounts(): self + { + $this->discounts = null; + + return $this; + } + public function validateCoupon(string $coupon): bool { return app(