|
6 | 6 | declare(strict_types=1);
|
7 | 7 | namespace Magento\Sales\Model\Reorder;
|
8 | 8 |
|
| 9 | +use Magento\Catalog\Api\Data\ProductInterface; |
9 | 10 | use Magento\Catalog\Api\ProductRepositoryInterface;
|
10 | 11 | use Magento\Catalog\Model\Product;
|
| 12 | +use Magento\Framework\Api\SearchCriteriaBuilder; |
| 13 | +use Magento\Framework\App\ObjectManager; |
11 | 14 | use Magento\Framework\Exception\InputException;
|
12 | 15 | use Magento\Framework\Exception\NoSuchEntityException;
|
13 | 16 | use Magento\Quote\Api\CartRepositoryInterface;
|
14 | 17 | use Magento\Quote\Api\Data\CartInterface;
|
15 | 18 | use Magento\Quote\Model\Cart\CustomerCartResolver;
|
| 19 | +use Magento\Quote\Model\Quote as Quote; |
| 20 | +use Magento\Sales\Api\Data\OrderItemInterface; |
16 | 21 | use Magento\Sales\Helper\Reorder as ReorderHelper;
|
17 | 22 | use Magento\Sales\Model\Order\Item;
|
18 | 23 | use Magento\Sales\Model\OrderFactory;
|
| 24 | +use Magento\Sales\Model\ResourceModel\Order\Item\Collection as ItemCollection; |
19 | 25 |
|
20 | 26 | /**
|
21 | 27 | * Allows customer quickly to reorder previously added products and put them to the Cart
|
@@ -81,28 +87,37 @@ class Reorder
|
81 | 87 | */
|
82 | 88 | private $customerCartProvider;
|
83 | 89 |
|
| 90 | + /** |
| 91 | + * @var SearchCriteriaBuilder |
| 92 | + */ |
| 93 | + private $searchCriteriaBuilder; |
| 94 | + |
84 | 95 | /**
|
85 | 96 | * @param OrderFactory $orderFactory
|
86 | 97 | * @param CustomerCartResolver $customerCartProvider
|
87 | 98 | * @param CartRepositoryInterface $cartRepository
|
88 | 99 | * @param ProductRepositoryInterface $productRepository
|
89 | 100 | * @param ReorderHelper $reorderHelper
|
90 | 101 | * @param \Psr\Log\LoggerInterface $logger
|
| 102 | + * @param SearchCriteriaBuilder $searchCriteriaBuilder = null |
91 | 103 | */
|
92 | 104 | public function __construct(
|
93 | 105 | OrderFactory $orderFactory,
|
94 | 106 | CustomerCartResolver $customerCartProvider,
|
95 | 107 | CartRepositoryInterface $cartRepository,
|
96 | 108 | ProductRepositoryInterface $productRepository,
|
97 | 109 | ReorderHelper $reorderHelper,
|
98 |
| - \Psr\Log\LoggerInterface $logger |
| 110 | + \Psr\Log\LoggerInterface $logger, |
| 111 | + SearchCriteriaBuilder $searchCriteriaBuilder = null |
99 | 112 | ) {
|
100 | 113 | $this->orderFactory = $orderFactory;
|
101 | 114 | $this->cartRepository = $cartRepository;
|
102 | 115 | $this->productRepository = $productRepository;
|
103 | 116 | $this->reorderHelper = $reorderHelper;
|
104 | 117 | $this->logger = $logger;
|
105 | 118 | $this->customerCartProvider = $customerCartProvider;
|
| 119 | + $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: |
| 120 | + ObjectManager::getInstance()->get(SearchCriteriaBuilder::class); |
106 | 121 | }
|
107 | 122 |
|
108 | 123 | /**
|
@@ -133,66 +148,102 @@ public function execute(string $orderNumber, string $storeId): Data\ReorderOutpu
|
133 | 148 | return $this->prepareOutput($cart);
|
134 | 149 | }
|
135 | 150 |
|
136 |
| - $items = $order->getItemsCollection(); |
137 |
| - foreach ($items as $item) { |
138 |
| - $this->addOrderItem($cart, $item); |
139 |
| - } |
| 151 | + $cartWithItems = $this->addItemsToCart($cart, $order->getItemsCollection()); |
140 | 152 |
|
141 | 153 | try {
|
142 |
| - $this->cartRepository->save($cart); |
| 154 | + $this->cartRepository->save($cartWithItems); |
143 | 155 | } catch (\Magento\Framework\Exception\LocalizedException $e) {
|
144 | 156 | // handle exception from \Magento\Quote\Model\QuoteRepository\SaveHandler::save
|
145 | 157 | $this->addError($e->getMessage());
|
146 | 158 | }
|
147 | 159 |
|
148 |
| - $cart = $this->cartRepository->get($cart->getId()); |
| 160 | + $savedCart = $this->cartRepository->get($cartWithItems->getId()); |
149 | 161 |
|
150 |
| - return $this->prepareOutput($cart); |
| 162 | + return $this->prepareOutput($savedCart); |
151 | 163 | }
|
152 | 164 |
|
153 | 165 | /**
|
154 |
| - * Convert order item to quote item |
| 166 | + * Add collections of order items to cart. |
155 | 167 | *
|
156 |
| - * @param \Magento\Quote\Model\Quote $cart |
157 |
| - * @param Item $orderItem |
158 |
| - * @return void |
| 168 | + * @param Quote $cart |
| 169 | + * @param ItemCollection $orderItems |
| 170 | + * @return Quote |
159 | 171 | */
|
160 |
| - private function addOrderItem(\Magento\Quote\Model\Quote $cart, $orderItem): void |
| 172 | + private function addItemsToCart(Quote $cart, ItemCollection $orderItems): Quote |
161 | 173 | {
|
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; |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + $criteria = $this->searchCriteriaBuilder |
| 187 | + ->addFilter('entity_id', $orderItemProductIds, 'in') |
| 188 | + ->create(); |
| 189 | + |
| 190 | + /** @var \Magento\Catalog\Api\Data\ProductInterface $products */ |
| 191 | + $products = $this->productRepository->getList($criteria)->getItems(); |
| 192 | + |
| 193 | + // compare founded products and throw an error if some product not exists |
| 194 | + $productsNotFound = array_diff($orderItemProductIds, array_keys($products)); |
| 195 | + if (!empty($productsNotFound)) { |
| 196 | + foreach ($productsNotFound as $productId) { |
| 197 | + /** @var \Magento\Sales\Model\Order\Item $orderItemProductNotFound */ |
172 | 198 | $this->addError(
|
173 |
| - (string)__('Could not find a product with ID "%1"', $orderItem->getProductId()), |
| 199 | + (string)__('Could not find a product with ID "%1"', $productId), |
174 | 200 | self::ERROR_PRODUCT_NOT_FOUND
|
175 | 201 | );
|
176 |
| - return; |
177 |
| - } |
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); |
186 | 202 | }
|
| 203 | + } |
187 | 204 |
|
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 |
| - } |
| 205 | + /** @var ProductInterface $product */ |
| 206 | + foreach ($products as $product) { |
| 207 | + $orderItem = $orderItemsByProductId[$product->getId()]; |
| 208 | + $this->addItemToCart($orderItem, $cart, $product); |
| 209 | + } |
| 210 | + |
| 211 | + return $cart; |
| 212 | + } |
| 213 | + |
| 214 | + /** |
| 215 | + * Adds order item product to cart. |
| 216 | + * |
| 217 | + * @param OrderItemInterface $orderItem |
| 218 | + * @param Quote $cart |
| 219 | + * @param ProductInterface $product |
| 220 | + * @return Quote |
| 221 | + */ |
| 222 | + private function addItemToCart(OrderItemInterface $orderItem, Quote $cart, ProductInterface $product): Quote |
| 223 | + { |
| 224 | + $info = $orderItem->getProductOptionByCode('info_buyRequest'); |
| 225 | + $info = new \Magento\Framework\DataObject($info); |
| 226 | + $info->setQty($orderItem->getQtyOrdered()); |
| 227 | + |
| 228 | + $addProductResult = null; |
| 229 | + try { |
| 230 | + $addProductResult = $cart->addProduct($product, $info); |
| 231 | + } catch (\Magento\Framework\Exception\LocalizedException $e) { |
| 232 | + $this->addError($this->getCartItemErrorMessage($orderItem, $product, $e->getMessage())); |
| 233 | + } catch (\Throwable $e) { |
| 234 | + $this->logger->critical($e); |
| 235 | + $this->addError($this->getCartItemErrorMessage($orderItem, $product), self::ERROR_UNDEFINED); |
| 236 | + } |
| 237 | + |
| 238 | + // error happens in case the result is string |
| 239 | + if (is_string($addProductResult)) { |
| 240 | + $errors = array_unique(explode("\n", $addProductResult)); |
| 241 | + foreach ($errors as $error) { |
| 242 | + $this->addError($this->getCartItemErrorMessage($orderItem, $product, $error)); |
194 | 243 | }
|
195 | 244 | }
|
| 245 | + |
| 246 | + return $cart; |
196 | 247 | }
|
197 | 248 |
|
198 | 249 | /**
|
|
0 commit comments