From ec749da05128290fb2a50ec1a5e01fd954be5647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=2E=20Nagy=20Gerg=C5=91?= Date: Fri, 28 May 2021 15:13:46 +0200 Subject: [PATCH] wip --- composer.json | 2 +- src/Cart/CookieDriver.php | 25 +++++++------- src/Cart/Driver.php | 35 ++++++++++++++----- src/Cart/SessionDriver.php | 25 +++++++------- src/Models/User.php | 14 ++++++-- src/Models/Variant.php | 1 - tests/Feature/CartManagerTest.php | 57 ++++++++++++++++++------------- 7 files changed, 97 insertions(+), 62 deletions(-) diff --git a/composer.json b/composer.json index f965cc05..481ca36f 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "ext-gd": "*", "ext-exif": "*", "php": "^7.4 || ^8.0", - "laravel/framework": "^8.40", + "laravel/framework": "^8.43", "inertiajs/inertia-laravel": "^0.3.6" }, "require-dev": { diff --git a/src/Cart/CookieDriver.php b/src/Cart/CookieDriver.php index b3f7197b..7eb6168c 100644 --- a/src/Cart/CookieDriver.php +++ b/src/Cart/CookieDriver.php @@ -16,22 +16,21 @@ class CookieDriver extends Driver */ protected function resolve(Request $request): Cart { - $user = $request->user(); - - $cart = Cart::proxy() + return Cart::proxy() ->newQuery() - ->firstOrCreate(['id' => $request->cookie('cart_id')]) - ->setRelation('user', $user) - ->loadMissing(['items', 'items.buyable']); - - if ($user && $cart->user_id !== $user->id) { - Cart::proxy()->newQuery()->where('user_id', $user->id)->delete(); + ->firstOrNew(['id' => $request->cookie('cart_id')]); + } - $cart->user()->associate($user)->save(); - } + /** + * The callback after the cart instance is resolved. + * + * @param \Illuminate\Http\Request $request + * @return \Bazar\Models\Cart + */ + protected function resolved(Request $request, Cart $cart): void + { + parent::resolved($request, $cart); Cookie::queue('cart_id', $cart->id, $this->config['expiration'] ?? 4320); - - return $cart; } } diff --git a/src/Cart/Driver.php b/src/Cart/Driver.php index 2bb4a4ec..fb0c3657 100644 --- a/src/Cart/Driver.php +++ b/src/Cart/Driver.php @@ -49,6 +49,21 @@ public function __construct(array $config = []) */ abstract protected function resolve(Request $request): Cart; + /** + * The callback after the cart instance is resolved. + * + * @param \Illuminate\Http\Request $request + * @return \Bazar\Models\Cart + */ + protected function resolved(Request $request, Cart $cart): void + { + if (! $cart->exists || ($request->user() && $cart->user_id !== $request->user()->id)) { + $cart->user()->associate($request->user())->save(); + } + + $cart->loadMissing(['items', 'items.buyable']); + } + /** * Get the cart model. * @@ -58,19 +73,21 @@ public function getModel(): Cart { if (is_null($this->cart)) { $this->cart = App::call(function (Request $request): Cart { - return tap($this->resolve($request), function (Cart $cart): void { - if (! $cart->wasRecentlyCreated && ! $cart->locked && $cart->currency !== Bazar::getCurrency()) { - $cart->setAttribute('currency', Bazar::getCurrency()); - $cart->syncItems(); - $cart->shipping->calculateCost(false); - $cart->shipping->calculateTax(); - $cart->calculateDiscount(); - } + return tap($this->resolve($request), function (Cart $cart) use ($request): void { + $this->resolved($request, $cart); }); }); } - return $this->cart; + return tap($this->cart, static function (Cart $cart): void { + if (! $cart->locked && $cart->currency !== Bazar::getCurrency()) { + $cart->setAttribute('currency', Bazar::getCurrency()); + $cart->syncItems(); + $cart->shipping->calculateCost(false); + $cart->shipping->calculateTax(); + $cart->calculateDiscount(); + } + }); } /** diff --git a/src/Cart/SessionDriver.php b/src/Cart/SessionDriver.php index f0393ce1..8e4c68f0 100644 --- a/src/Cart/SessionDriver.php +++ b/src/Cart/SessionDriver.php @@ -15,22 +15,21 @@ class SessionDriver extends Driver */ protected function resolve(Request $request): Cart { - $user = $request->user(); - - $cart = Cart::proxy() + return Cart::proxy() ->newQuery() - ->firstOrCreate(['id' => $request->session()->get('cart_id')]) - ->setRelation('user', $user) - ->loadMissing(['items', 'items.buyable']); - - if ($user && $cart->user_id !== $user->id) { - Cart::proxy()->newQuery()->where('user_id', $user->id)->delete(); + ->firstOrNew(['id' => $request->session()->get('cart_id')]); + } - $cart->user()->associate($user)->save(); - } + /** + * The callback after the cart instance is resolved. + * + * @param \Illuminate\Http\Request $request + * @return \Bazar\Models\Cart + */ + protected function resolved(Request $request, Cart $cart): void + { + parent::resolved($request, $cart); $request->session()->put('cart_id', $cart->id); - - return $cart; } } diff --git a/src/Models/User.php b/src/Models/User.php index 7f47b6d1..f4a3dd77 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -114,13 +114,23 @@ protected static function newFactory(): ?UserFactory } /** - * Get the cart for the user. + * Get the active cart for the user. * * @return \Illuminate\Database\Eloquent\Relations\HasOne */ public function cart(): HasOne { - return $this->hasOne(Cart::getProxiedClass()); + return $this->hasOne(Cart::getProxiedClass())->latestOfMany(); + } + + /** + * Get the carts for the user. + * + * @return \Illuminate\Database\Eloquent\Relations\v + */ + public function carts(): HasMany + { + return $this->hasMany(Cart::getProxiedClass()); } /** diff --git a/src/Models/Variant.php b/src/Models/Variant.php index 59911b85..f9412388 100644 --- a/src/Models/Variant.php +++ b/src/Models/Variant.php @@ -11,7 +11,6 @@ use Bazar\Concerns\InteractsWithItemables; use Bazar\Concerns\InteractsWithProxy; use Bazar\Concerns\InteractsWithStock; -use Bazar\Contracts\Buyable; use Bazar\Contracts\Itemable; use Bazar\Contracts\Models\Variant as Contract; use Bazar\Database\Factories\VariantFactory; diff --git a/tests/Feature/CartManagerTest.php b/tests/Feature/CartManagerTest.php index 66866381..19e64047 100644 --- a/tests/Feature/CartManagerTest.php +++ b/tests/Feature/CartManagerTest.php @@ -2,6 +2,7 @@ namespace Bazar\Tests\Feature; +use Bazar\Bazar; use Bazar\Cart\CookieDriver; use Bazar\Cart\Manager; use Bazar\Cart\SessionDriver; @@ -25,10 +26,12 @@ public function setUp(): void parent::setUp(); $this->manager = $this->app->make(Manager::class); - $this->product = Product::factory()->create(['prices' => ['usd' => ['default' => 100]]]); + $this->product = Product::factory()->create([ + 'prices' => ['usd' => ['default' => 100], 'eur' => ['default' => 2000]], + ]); $this->variant = $this->product->variants()->save(Variant::factory()->make([ 'variation' => ['Size' => 'S'], - 'prices' => ['usd' => ['default' => 150]], + 'prices' => ['usd' => ['default' => 150], 'eur' => ['default' => 2500]], ])); $this->manager->addItem($this->product, 2, ['Size' => 'L']); @@ -36,7 +39,7 @@ public function setUp(): void } /** @test */ - public function it_can_be_resolved_via_facade() + public function a_manager_can_be_resolved_via_facade() { $this->mock(Manager::class, function ($mock) { return $mock->shouldReceive('getModel') @@ -48,14 +51,14 @@ public function it_can_be_resolved_via_facade() } /** @test */ - public function it_has_cookie_driver() + public function a_manager_has_cookie_driver() { $this->assertInstanceOf(CookieDriver::class, $this->manager->driver('cookie')); $this->assertInstanceOf(Cart::class, $this->manager->driver('cookie')->getModel()); } /** @test */ - public function it_has_session_driver() + public function a_manager_has_session_driver() { $this->session([]); @@ -66,7 +69,7 @@ public function it_has_session_driver() } /** @test */ - public function it_can_add_products() + public function a_manager_can_add_products() { $this->manager->addItem($this->product, 2, ['Size' => 'L']); @@ -74,16 +77,12 @@ public function it_can_add_products() $this->assertEquals(2, $this->manager->getItems()->count()); $product = $this->manager->getModel()->findItem([ - 'buyable_id' => $this->product->id, - 'buyable_type' => Product::class, 'properties' => ['Size' => 'L'], ]); $this->assertEquals(100, $product->price); $this->assertEquals(4, $product->quantity); $variant = $this->manager->getModel()->findItem([ - 'buyable_id' => $this->variant->id, - 'buyable_type' => Variant::class, 'properties' => ['Size' => 'S'], ]); @@ -92,10 +91,9 @@ public function it_can_add_products() } /** @test */ - public function it_can_remove_items() + public function a_manager_can_remove_items() { $item = $this->manager->getModel()->findItem([ - 'product_id' => $this->product->id, 'properties' => ['Size' => 'L'], ]); $this->manager->removeItem($item->id); @@ -109,10 +107,9 @@ public function it_can_remove_items() } /** @test */ - public function it_can_update_items() + public function a_manager_can_update_items() { $item = $this->manager->getModel()->findItem([ - 'product_id' => $this->product->id, 'properties' => ['Size' => 'L'], ]); $this->manager->updateItem($item->id, ['quantity' => 10]); @@ -130,7 +127,7 @@ public function it_can_update_items() } /** @test */ - public function it_can_be_emptied() + public function a_manager_can_be_emptied() { $this->assertTrue($this->manager->isNotEmpty()); $this->manager->empty(); @@ -138,13 +135,13 @@ public function it_can_be_emptied() } /** @test */ - public function it_has_shipping() + public function a_manager_has_shipping() { $this->assertInstanceOf(Shipping::class, $this->manager->getShipping()); } /** @test */ - public function it_updates_shipping() + public function a_manager_updates_shipping() { $this->manager->updateShipping(['first_name' => 'Test'], 'local-pickup'); @@ -152,13 +149,13 @@ public function it_updates_shipping() } /** @test */ - public function it_has_billing() + public function a_manager_has_billing() { $this->assertInstanceOf(Address::class, $this->manager->getBilling()); } /** @test */ - public function it_updates_billing() + public function a_manager_updates_billing() { $this->manager->updateBilling(['first_name' => 'Test']); @@ -166,7 +163,7 @@ public function it_updates_billing() } /** @test */ - public function it_has_getTotal() + public function a_manager_has_getTotal() { $this->assertEquals( $this->manager->getModel()->total, $this->manager->getTotal() @@ -174,7 +171,7 @@ public function it_has_getTotal() } /** @test */ - public function it_has_calculates_tax() + public function a_manager_has_calculates_tax() { $this->assertEquals( $this->manager->getModel()->tax, $this->manager->calculateTax() @@ -182,7 +179,7 @@ public function it_has_calculates_tax() } /** @test */ - public function it_has_calculates_discount() + public function a_manager_has_calculates_discount() { $this->assertEquals( $this->manager->getModel()->discount, $this->manager->calculateDiscount() @@ -190,7 +187,7 @@ public function it_has_calculates_discount() } /** @test */ - public function it_can_checkout() + public function a_manager_can_checkout() { Event::fake([CheckoutProcessing::class, CheckoutProcessed::class]); @@ -199,4 +196,18 @@ public function it_can_checkout() Event::assertDispatched(CheckoutProcessing::class); Event::assertDispatched(CheckoutProcessed::class); } + + /** @test */ + public function a_manager_can_sync_items() + { + $this->assertEquals(350, $this->manager->getTotal()); + + Bazar::setCurrency('eur'); + + $this->assertEquals(6500, $this->manager->getTotal()); + + Bazar::setCurrency('usd'); + + $this->assertEquals(350, $this->manager->getTotal()); + } }