Skip to content

Commit 0e743f2

Browse files
authored
Merge pull request #5659 from magento-performance/MC-33400-cart-addorderitem-improvement
[Performance] MC-33400 Cart Add Order Item-improvement
2 parents 4e085c7 + 2d1058d commit 0e743f2

File tree

3 files changed

+118
-47
lines changed

3 files changed

+118
-47
lines changed

app/code/Magento/Bundle/Model/ResourceModel/Option.php

+10-10
Original file line numberDiff line numberDiff line change
@@ -92,29 +92,29 @@ protected function _afterSave(AbstractModel $object)
9292
{
9393
parent::_afterSave($object);
9494

95-
$condition = [
96-
'option_id = ?' => $object->getId(),
97-
'store_id = ? OR store_id = 0' => $object->getStoreId(),
98-
'parent_product_id = ?' => $object->getParentId()
99-
];
100-
10195
$connection = $this->getConnection();
102-
$connection->delete($this->getTable('catalog_product_bundle_option_value'), $condition);
103-
10496
$data = new DataObject();
10597
$data->setOptionId($object->getId())
10698
->setStoreId($object->getStoreId())
10799
->setParentProductId($object->getParentId())
108100
->setTitle($object->getTitle());
109101

110-
$connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData());
102+
$connection->insertOnDuplicate(
103+
$this->getTable('catalog_product_bundle_option_value'),
104+
$data->getData(),
105+
['title']
106+
);
111107

112108
/**
113109
* also saving default fallback value
114110
*/
115111
if (0 !== (int)$object->getStoreId()) {
116112
$data->setStoreId(0)->setTitle($object->getDefaultTitle());
117-
$connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData());
113+
$connection->insertOnDuplicate(
114+
$this->getTable('catalog_product_bundle_option_value'),
115+
$data->getData(),
116+
['title']
117+
);
118118
}
119119

120120
return $this;

app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyComparedAtWebsiteLevelTest.xml

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
<useCaseId value="MC-32763"/>
1919
<group value="catalog"/>
2020
<group value="widget"/>
21+
<skip>
22+
<issueId value="MC-34091"/>
23+
</skip>
2124
</annotations>
2225
<before>
2326
<!-- Set Stores > Configurations > Catalog > Recently Viewed/Compared Products > Show for Current = Website -->

app/code/Magento/Sales/Model/Reorder/Reorder.php

+105-37
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@
66
declare(strict_types=1);
77
namespace Magento\Sales\Model\Reorder;
88

9+
use Magento\Catalog\Api\Data\ProductInterface;
910
use Magento\Catalog\Api\ProductRepositoryInterface;
1011
use Magento\Catalog\Model\Product;
12+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
1113
use Magento\Framework\Exception\InputException;
1214
use Magento\Framework\Exception\NoSuchEntityException;
1315
use Magento\Quote\Api\CartRepositoryInterface;
1416
use Magento\Quote\Api\Data\CartInterface;
1517
use Magento\Quote\Model\Cart\CustomerCartResolver;
18+
use Magento\Quote\Model\Quote as Quote;
19+
use Magento\Sales\Api\Data\OrderItemInterface;
1620
use Magento\Sales\Helper\Reorder as ReorderHelper;
1721
use Magento\Sales\Model\Order\Item;
1822
use Magento\Sales\Model\OrderFactory;
23+
use Magento\Sales\Model\ResourceModel\Order\Item\Collection as ItemCollection;
24+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
1925

2026
/**
2127
* Allows customer quickly to reorder previously added products and put them to the Cart
@@ -81,28 +87,36 @@ class Reorder
8187
*/
8288
private $customerCartProvider;
8389

90+
/**
91+
* @var ProductCollectionFactory
92+
*/
93+
private $productCollectionFactory;
94+
8495
/**
8596
* @param OrderFactory $orderFactory
8697
* @param CustomerCartResolver $customerCartProvider
8798
* @param CartRepositoryInterface $cartRepository
8899
* @param ProductRepositoryInterface $productRepository
89100
* @param ReorderHelper $reorderHelper
90101
* @param \Psr\Log\LoggerInterface $logger
102+
* @param ProductCollectionFactory $productCollectionFactory
91103
*/
92104
public function __construct(
93105
OrderFactory $orderFactory,
94106
CustomerCartResolver $customerCartProvider,
95107
CartRepositoryInterface $cartRepository,
96108
ProductRepositoryInterface $productRepository,
97109
ReorderHelper $reorderHelper,
98-
\Psr\Log\LoggerInterface $logger
110+
\Psr\Log\LoggerInterface $logger,
111+
ProductCollectionFactory $productCollectionFactory
99112
) {
100113
$this->orderFactory = $orderFactory;
101114
$this->cartRepository = $cartRepository;
102115
$this->productRepository = $productRepository;
103116
$this->reorderHelper = $reorderHelper;
104117
$this->logger = $logger;
105118
$this->customerCartProvider = $customerCartProvider;
119+
$this->productCollectionFactory = $productCollectionFactory;
106120
}
107121

108122
/**
@@ -133,10 +147,7 @@ public function execute(string $orderNumber, string $storeId): Data\ReorderOutpu
133147
return $this->prepareOutput($cart);
134148
}
135149

136-
$items = $order->getItemsCollection();
137-
foreach ($items as $item) {
138-
$this->addOrderItem($cart, $item);
139-
}
150+
$this->addItemsToCart($cart, $order->getItemsCollection(), $storeId);
140151

141152
try {
142153
$this->cartRepository->save($cart);
@@ -145,52 +156,109 @@ public function execute(string $orderNumber, string $storeId): Data\ReorderOutpu
145156
$this->addError($e->getMessage());
146157
}
147158

148-
$cart = $this->cartRepository->get($cart->getId());
159+
$savedCart = $this->cartRepository->get($cart->getId());
149160

150-
return $this->prepareOutput($cart);
161+
return $this->prepareOutput($savedCart);
151162
}
152163

153164
/**
154-
* Convert order item to quote item
165+
* Add collections of order items to cart.
155166
*
156-
* @param \Magento\Quote\Model\Quote $cart
157-
* @param Item $orderItem
167+
* @param Quote $cart
168+
* @param ItemCollection $orderItems
169+
* @param string $storeId
158170
* @return void
159171
*/
160-
private function addOrderItem(\Magento\Quote\Model\Quote $cart, $orderItem): void
172+
private function addItemsToCart(Quote $cart, ItemCollection $orderItems, string $storeId): void
161173
{
162-
/* @var $orderItem Item */
163-
if ($orderItem->getParentItem() === null) {
164-
$info = $orderItem->getProductOptionByCode('info_buyRequest');
165-
$info = new \Magento\Framework\DataObject($info);
166-
$info->setQty($orderItem->getQtyOrdered());
167-
168-
try {
169-
/** @var Product $product */
170-
$product = $this->productRepository->getById($orderItem->getProductId(), false, null, true);
171-
} catch (NoSuchEntityException $e) {
174+
$orderItemProductIds = [];
175+
/** @var \Magento\Sales\Model\Order\Item[] $orderItemsByProductId */
176+
$orderItemsByProductId = [];
177+
178+
/** @var \Magento\Sales\Model\Order\Item $item */
179+
foreach ($orderItems as $item) {
180+
if ($item->getParentItem() === null) {
181+
$orderItemProductIds[] = $item->getProductId();
182+
$orderItemsByProductId[$item->getProductId()][$item->getId()] = $item;
183+
}
184+
}
185+
186+
$products = $this->getOrderProducts($storeId, $orderItemProductIds);
187+
188+
// compare founded products and throw an error if some product not exists
189+
$productsNotFound = array_diff($orderItemProductIds, array_keys($products));
190+
if (!empty($productsNotFound)) {
191+
foreach ($productsNotFound as $productId) {
192+
/** @var \Magento\Sales\Model\Order\Item $orderItemProductNotFound */
172193
$this->addError(
173-
(string)__('Could not find a product with ID "%1"', $orderItem->getProductId()),
194+
(string)__('Could not find a product with ID "%1"', $productId),
174195
self::ERROR_PRODUCT_NOT_FOUND
175196
);
176-
return;
177197
}
178-
$addProductResult = null;
179-
try {
180-
$addProductResult = $cart->addProduct($product, $info);
181-
} catch (\Magento\Framework\Exception\LocalizedException $e) {
182-
$this->addError($this->getCartItemErrorMessage($orderItem, $product, $e->getMessage()));
183-
} catch (\Throwable $e) {
184-
$this->logger->critical($e);
185-
$this->addError($this->getCartItemErrorMessage($orderItem, $product), self::ERROR_UNDEFINED);
198+
}
199+
200+
foreach ($orderItemsByProductId as $productId => $orderItems) {
201+
if (!isset($products[$productId])) {
202+
continue;
203+
}
204+
$product = $products[$productId];
205+
foreach ($orderItems as $orderItem) {
206+
$this->addItemToCart($orderItem, $cart, clone $product);
186207
}
208+
}
209+
}
210+
211+
/**
212+
* Get order products by store id and order item product ids.
213+
*
214+
* @param string $storeId
215+
* @param int[] $orderItemProductIds
216+
* @return Product[]
217+
* @throws \Magento\Framework\Exception\LocalizedException
218+
*/
219+
private function getOrderProducts(string $storeId, array $orderItemProductIds): array
220+
{
221+
/** @var Collection $collection */
222+
$collection = $this->productCollectionFactory->create();
223+
$collection->setStore($storeId)
224+
->addIdFilter($orderItemProductIds)
225+
->addStoreFilter()
226+
->addAttributeToSelect('*')
227+
->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner')
228+
->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');
229+
230+
return $collection->getItems();
231+
}
232+
233+
/**
234+
* Adds order item product to cart.
235+
*
236+
* @param OrderItemInterface $orderItem
237+
* @param Quote $cart
238+
* @param ProductInterface $product
239+
* @return void
240+
*/
241+
private function addItemToCart(OrderItemInterface $orderItem, Quote $cart, ProductInterface $product): void
242+
{
243+
$info = $orderItem->getProductOptionByCode('info_buyRequest');
244+
$info = new \Magento\Framework\DataObject($info);
245+
$info->setQty($orderItem->getQtyOrdered());
246+
247+
$addProductResult = null;
248+
try {
249+
$addProductResult = $cart->addProduct($product, $info);
250+
} catch (\Magento\Framework\Exception\LocalizedException $e) {
251+
$this->addError($this->getCartItemErrorMessage($orderItem, $product, $e->getMessage()));
252+
} catch (\Throwable $e) {
253+
$this->logger->critical($e);
254+
$this->addError($this->getCartItemErrorMessage($orderItem, $product), self::ERROR_UNDEFINED);
255+
}
187256

188-
// error happens in case the result is string
189-
if (is_string($addProductResult)) {
190-
$errors = array_unique(explode("\n", $addProductResult));
191-
foreach ($errors as $error) {
192-
$this->addError($this->getCartItemErrorMessage($orderItem, $product, $error));
193-
}
257+
// error happens in case the result is string
258+
if (is_string($addProductResult)) {
259+
$errors = array_unique(explode("\n", $addProductResult));
260+
foreach ($errors as $error) {
261+
$this->addError($this->getCartItemErrorMessage($orderItem, $product, $error));
194262
}
195263
}
196264
}

0 commit comments

Comments
 (0)