diff --git a/packages/Webkul/CartRule/src/Helpers/CartRule.php b/packages/Webkul/CartRule/src/Helpers/CartRule.php index 35b3e81aa..64b0654a5 100644 --- a/packages/Webkul/CartRule/src/Helpers/CartRule.php +++ b/packages/Webkul/CartRule/src/Helpers/CartRule.php @@ -106,9 +106,9 @@ class CartRule $cart = Cart::getCart(); $appliedCartRuleIds = []; - $this->calculateCartItemTotals($cart->items()->get()); + $this->calculateCartItemTotals($cart->items); - foreach ($cart->items()->get() as $item) { + foreach ($cart->items as $item) { $itemCartRuleIds = $this->process($item); $appliedCartRuleIds = array_merge($appliedCartRuleIds, $itemCartRuleIds); diff --git a/packages/Webkul/Checkout/src/Cart.php b/packages/Webkul/Checkout/src/Cart.php index 5a645047e..93dddb541 100755 --- a/packages/Webkul/Checkout/src/Cart.php +++ b/packages/Webkul/Checkout/src/Cart.php @@ -323,7 +323,7 @@ class Cart if ($cartItem = $cart->items()->find($itemId)) { $cartItem->delete(); - if ($cart->items()->get()->count() == 0) { + if ($cart->items->count() == 0) { $this->cartRepository->delete($cart->id); if (session()->has('cart')) { @@ -412,8 +412,7 @@ class Cart 'customer_id' => $this->getCurrentCustomer()->user()->id, 'is_active' => 1, ]); - - } elseif (session()->has('cart')) { + } else if (session()->has('cart')) { $cart = $this->cartRepository->find(session()->get('cart')->id); } @@ -547,7 +546,7 @@ class Cart $cart->tax_total = $cart->base_tax_total = 0; $cart->discount_amount = $cart->base_discount_amount = 0; - foreach ($cart->items()->get() as $item) { + foreach ($cart->items as $item) { $cart->discount_amount += $item->discount_amount; $cart->base_discount_amount += $item->base_discount_amount; @@ -646,7 +645,7 @@ class Cart Event::dispatch('checkout.cart.calculate.items.tax.before', $cart); - foreach ($cart->items()->get() as $item) { + foreach ($cart->items as $item) { $taxCategory = $this->taxCategoryRepository->find($item->product->tax_category_id); if (! $taxCategory) { @@ -768,7 +767,7 @@ class Cart $this->cartItemRepository->delete($item->id); - if ($cart->items()->get()->count() == 0) { + if ($cart->items->count() == 0) { $this->cartRepository->delete($cart->id); if (session()->has('cart')) { @@ -992,7 +991,7 @@ class Cart $result = $this->cartItemRepository->delete($itemId); - if (! $cart->items()->count()) { + if (! $cart->items->count()) { $this->cartRepository->delete($cart->id); } @@ -1085,7 +1084,13 @@ class Cart * @return bool */ private function isCartItemInactive(\Webkul\Checkout\Contracts\CartItem $item): bool { - return $item->product->getTypeInstance()->isCartItemInactive($item); + static $loadedCartItem = []; + + if (array_key_exists($item->product_id, $loadedCartItem)) { + return $loadedCartItem[$item->product_id]; + } + + return $loadedCartItem[$item->product_id] = $item->product->getTypeInstance()->isCartItemInactive($item); } /** diff --git a/packages/Webkul/Product/src/Models/Product.php b/packages/Webkul/Product/src/Models/Product.php index 537024f5d..220a5a15c 100755 --- a/packages/Webkul/Product/src/Models/Product.php +++ b/packages/Webkul/Product/src/Models/Product.php @@ -3,15 +3,15 @@ namespace Webkul\Product\Models; use Exception; -use Webkul\Product\Type\AbstractType; use Illuminate\Database\Eloquent\Model; -use Webkul\Category\Models\CategoryProxy; -use Webkul\Attribute\Models\AttributeProxy; -use Webkul\Product\Database\Eloquent\Builder; use Webkul\Attribute\Models\AttributeFamilyProxy; -use Webkul\Inventory\Models\InventorySourceProxy; +use Webkul\Attribute\Models\AttributeProxy; use Webkul\Attribute\Repositories\AttributeRepository; +use Webkul\Category\Models\CategoryProxy; +use Webkul\Inventory\Models\InventorySourceProxy; use Webkul\Product\Contracts\Product as ProductContract; +use Webkul\Product\Database\Eloquent\Builder; +use Webkul\Product\Type\AbstractType; class Product extends Model implements ProductContract { @@ -43,6 +43,13 @@ class Product extends Model implements ProductContract */ protected $typeInstance; + /** + * Loaded attribute values. + * + * @var $loadedAttributeValues + */ + public static $loadedAttributeValues = []; + /** * The "booted" method of the model. * @@ -65,6 +72,16 @@ class Product extends Model implements ProductContract }); } + /** + * Refresh the loaded attribute values. + * + * @return void + */ + public function refreshloadedAttributeValues() + { + self::$loadedAttributeValues = []; + } + /** * Get the product attribute family that owns the product. */ @@ -245,8 +262,9 @@ class Product extends Model implements ProductContract } /** - * @param integer $qty + * Get inventory source quantity. * + * @param integer $qty * @return bool */ public function inventory_source_qty($inventorySourceId) @@ -257,7 +275,7 @@ class Product extends Model implements ProductContract } /** - * Retrieve type instance + * Get type instance. * * @return AbstractType */ @@ -281,8 +299,9 @@ class Product extends Model implements ProductContract } /** - * @param string $key + * Is saleable. * + * @param string $key * @return bool */ public function isSaleable() @@ -291,6 +310,8 @@ class Product extends Model implements ProductContract } /** + * Total quantity. + * * @return integer */ public function totalQuantity() @@ -299,8 +320,9 @@ class Product extends Model implements ProductContract } /** - * @param int $qty + * Have sufficient quantity. * + * @param int $qty * @return bool */ public function haveSufficientQuantity(int $qty): bool @@ -309,6 +331,8 @@ class Product extends Model implements ProductContract } /** + * Is stockable. + * * @return bool */ public function isStockable() @@ -316,24 +340,10 @@ class Product extends Model implements ProductContract return $this->getTypeInstance()->isStockable(); } - /** - * Retrieve product attributes - * - * @param Group $group - * @param bool $skipSuperAttribute - * - * @return Collection - */ - public function getEditableAttributes($group = null, $skipSuperAttribute = true) - { - return $this->getTypeInstance()->getEditableAttributes($group, $skipSuperAttribute); - } - /** * Get an attribute from the model. * * @param string $key - * * @return mixed */ public function getAttribute($key) @@ -358,23 +368,59 @@ class Product extends Model implements ProductContract } /** - * Check in loaded family attributes. + * Retrieve product attributes. * - * @return object + * @param Group $group + * @param bool $skipSuperAttribute + * + * @return Collection */ - public function checkInLoadedFamilyAttributes() + public function getEditableAttributes($group = null, $skipSuperAttribute = true) { - static $loadedFamilyAttributes = []; - - if (array_key_exists($this->attribute_family_id, $loadedFamilyAttributes)) { - return $loadedFamilyAttributes[$this->attribute_family_id]; - } - - return $loadedFamilyAttributes[$this->attribute_family_id] = core()->getSingletonInstance(AttributeRepository::class) - ->getFamilyAttributes($this->attribute_family); + return $this->getTypeInstance()->getEditableAttributes($group, $skipSuperAttribute); } /** + * Get an product attribute value. + * + * @return mixed + */ + public function getCustomAttributeValue($attribute) + { + if (! $attribute) { + return; + } + + $locale = core()->checkRequestedLocaleCodeInRequestedChannel(); + $channel = core()->getRequestedChannelCode(); + + if ( + array_key_exists($this->id, self::$loadedAttributeValues) + && array_key_exists($attribute->id, self::$loadedAttributeValues[$this->id]) + ) { + return self::$loadedAttributeValues[$this->id][$attribute->id]; + } + + if ($attribute->value_per_channel) { + if ($attribute->value_per_locale) { + $attributeValue = $this->attribute_values()->where('channel', $channel)->where('locale', $locale)->where('attribute_id', $attribute->id)->first(); + } else { + $attributeValue = $this->attribute_values()->where('channel', $channel)->where('attribute_id', $attribute->id)->first(); + } + } else { + if ($attribute->value_per_locale) { + $attributeValue = $this->attribute_values()->where('locale', $locale)->where('attribute_id', $attribute->id)->first(); + } else { + $attributeValue = $this->attribute_values()->where('attribute_id', $attribute->id)->first(); + } + } + + return self::$loadedAttributeValues[$this->id][$attribute->id] = $attributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]] ?? null; + } + + /** + * Attributes to array. + * * @return array */ public function attributesToArray() @@ -398,37 +444,6 @@ class Product extends Model implements ProductContract return $attributes; } - /** - * Get an product attribute value. - * - * @return mixed - */ - public function getCustomAttributeValue($attribute) - { - if (! $attribute) { - return; - } - - $locale = core()->checkRequestedLocaleCodeInRequestedChannel(); - $channel = core()->getRequestedChannelCode(); - - if ($attribute->value_per_channel) { - if ($attribute->value_per_locale) { - $attributeValue = $this->attribute_values()->where('channel', $channel)->where('locale', $locale)->where('attribute_id', $attribute->id)->first(); - } else { - $attributeValue = $this->attribute_values()->where('channel', $channel)->where('attribute_id', $attribute->id)->first(); - } - } else { - if ($attribute->value_per_locale) { - $attributeValue = $this->attribute_values()->where('locale', $locale)->where('attribute_id', $attribute->id)->first(); - } else { - $attributeValue = $this->attribute_values()->where('attribute_id', $attribute->id)->first(); - } - } - - return $attributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]] ?? null; - } - /** * Overrides the default Eloquent query builder. * @@ -455,4 +470,21 @@ class Product extends Model implements ProductContract { return $this; } + + /** + * Check in loaded family attributes. + * + * @return object + */ + public function checkInLoadedFamilyAttributes() + { + static $loadedFamilyAttributes = []; + + if (array_key_exists($this->attribute_family_id, $loadedFamilyAttributes)) { + return $loadedFamilyAttributes[$this->attribute_family_id]; + } + + return $loadedFamilyAttributes[$this->attribute_family_id] = core()->getSingletonInstance(AttributeRepository::class) + ->getFamilyAttributes($this->attribute_family); + } } diff --git a/tests/unit/Checkout/Cart/CartCest.php b/tests/unit/Checkout/Cart/CartCest.php index 0baad7700..dc53dc3cf 100644 --- a/tests/unit/Checkout/Cart/CartCest.php +++ b/tests/unit/Checkout/Cart/CartCest.php @@ -80,6 +80,8 @@ class CartCest ]) ->update(['boolean_value' => 0]); + $this->simpleProduct2->refreshloadedAttributeValues(); + Event::dispatch('catalog.product.update.after', $this->simpleProduct2->refresh()); $I->assertFalse(cart()->hasError()); @@ -107,6 +109,8 @@ class CartCest ]) ->update(['boolean_value' => 0]); + $this->simpleProduct2->refreshloadedAttributeValues(); + Event::dispatch('catalog.product.update.after', $this->downloadableProduct2->refresh()); $I->comment('add dP1 to cart, dP2 should be removed now'); @@ -128,6 +132,8 @@ class CartCest ]) ->update(['boolean_value' => 0]); + $this->simpleProduct2->refreshloadedAttributeValues(); + Event::dispatch('catalog.product.update.after', $this->virtualProduct2->refresh()); $I->comment('change quantity of vP1, vP2 should be removed now'); diff --git a/tests/unit/Core/Commands/BookingCronCest.php b/tests/unit/Core/Commands/BookingCronCest.php index 455fcf2ec..2112a55df 100644 --- a/tests/unit/Core/Commands/BookingCronCest.php +++ b/tests/unit/Core/Commands/BookingCronCest.php @@ -36,6 +36,7 @@ class BookingCronCest ['booking_product_id' => $bookingProducts[$i]->id]); $products[$i]->refresh(); + $products[$i]->refreshloadedAttributeValues(); $I->assertNotFalse($products[$i]->status); } @@ -43,6 +44,7 @@ class BookingCronCest for ($i=0; $i<$index; $i++) { $products[$i]->refresh(); + $products[$i]->refreshloadedAttributeValues(); if ($bookingProducts[$i]->available_to < Carbon::now()) { $I->assertEquals(0, $products[$i]->status);