Skip to content

Commit 6f51c11

Browse files
committed
MC-19432: REST API returns 404 error instead of 400
1 parent f2b5e48 commit 6f51c11

File tree

3 files changed

+96
-36
lines changed

3 files changed

+96
-36
lines changed
Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,34 @@
11
<?php
22
/**
3+
*
34
* Copyright © Magento, Inc. All rights reserved.
45
* See COPYING.txt for license details.
56
*/
67

78
namespace Magento\Quote\Model\Quote\Item;
89

9-
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Framework\App\ObjectManager;
1011
use Magento\Framework\Exception\CouldNotSaveException;
11-
use Magento\Framework\Exception\InputException;
1212
use Magento\Framework\Exception\NoSuchEntityException;
13-
use Magento\Quote\Api\CartItemRepositoryInterface;
14-
use Magento\Quote\Api\CartRepositoryInterface;
15-
use Magento\Quote\Api\Data\CartItemInterfaceFactory;
1613

17-
/**
18-
* Repository for quote item.
19-
*/
20-
class Repository implements CartItemRepositoryInterface
14+
class Repository implements \Magento\Quote\Api\CartItemRepositoryInterface
2115
{
2216
/**
2317
* Quote repository.
2418
*
25-
* @var CartRepositoryInterface
19+
* @var \Magento\Quote\Api\CartRepositoryInterface
2620
*/
2721
protected $quoteRepository;
2822

2923
/**
3024
* Product repository.
3125
*
32-
* @var ProductRepositoryInterface
26+
* @var \Magento\Catalog\Api\ProductRepositoryInterface
3327
*/
3428
protected $productRepository;
3529

3630
/**
37-
* @var CartItemInterfaceFactory
31+
* @var \Magento\Quote\Api\Data\CartItemInterfaceFactory
3832
*/
3933
protected $itemDataFactory;
4034

@@ -49,28 +43,25 @@ class Repository implements CartItemRepositoryInterface
4943
private $cartItemOptionsProcessor;
5044

5145
/**
52-
* @param CartRepositoryInterface $quoteRepository
53-
* @param ProductRepositoryInterface $productRepository
54-
* @param CartItemInterfaceFactory $itemDataFactory
55-
* @param CartItemOptionsProcessor $cartItemOptionsProcessor
46+
* @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
47+
* @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
48+
* @param \Magento\Quote\Api\Data\CartItemInterfaceFactory $itemDataFactory
5649
* @param CartItemProcessorInterface[] $cartItemProcessors
5750
*/
5851
public function __construct(
59-
CartRepositoryInterface $quoteRepository,
60-
ProductRepositoryInterface $productRepository,
61-
CartItemInterfaceFactory $itemDataFactory,
62-
CartItemOptionsProcessor $cartItemOptionsProcessor,
52+
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
53+
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
54+
\Magento\Quote\Api\Data\CartItemInterfaceFactory $itemDataFactory,
6355
array $cartItemProcessors = []
6456
) {
6557
$this->quoteRepository = $quoteRepository;
6658
$this->productRepository = $productRepository;
6759
$this->itemDataFactory = $itemDataFactory;
68-
$this->cartItemOptionsProcessor = $cartItemOptionsProcessor;
6960
$this->cartItemProcessors = $cartItemProcessors;
7061
}
7162

7263
/**
73-
* @inheritdoc
64+
* {@inheritdoc}
7465
*/
7566
public function getList($cartId)
7667
{
@@ -80,26 +71,21 @@ public function getList($cartId)
8071

8172
/** @var \Magento\Quote\Model\Quote\Item $item */
8273
foreach ($quote->getAllVisibleItems() as $item) {
83-
$item = $this->cartItemOptionsProcessor->addProductOptions($item->getProductType(), $item);
84-
$output[] = $this->cartItemOptionsProcessor->applyCustomOptions($item);
74+
$item = $this->getCartItemOptionsProcessor()->addProductOptions($item->getProductType(), $item);
75+
$output[] = $this->getCartItemOptionsProcessor()->applyCustomOptions($item);
8576
}
8677
return $output;
8778
}
8879

8980
/**
90-
* @inheritdoc
81+
* {@inheritdoc}
9182
*/
9283
public function save(\Magento\Quote\Api\Data\CartItemInterface $cartItem)
9384
{
9485
/** @var \Magento\Quote\Model\Quote $quote */
9586
$cartId = $cartItem->getQuoteId();
96-
if (!$cartId) {
97-
throw new InputException(
98-
__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'cartId'])
99-
);
100-
}
101-
10287
$quote = $this->quoteRepository->getActive($cartId);
88+
10389
$quoteItems = $quote->getItems();
10490
$quoteItems[] = $cartItem;
10591
$quote->setItems($quoteItems);
@@ -109,7 +95,7 @@ public function save(\Magento\Quote\Api\Data\CartItemInterface $cartItem)
10995
}
11096

11197
/**
112-
* @inheritdoc
98+
* {@inheritdoc}
11399
*/
114100
public function deleteById($cartId, $itemId)
115101
{
@@ -130,4 +116,17 @@ public function deleteById($cartId, $itemId)
130116

131117
return true;
132118
}
119+
120+
/**
121+
* @return CartItemOptionsProcessor
122+
* @deprecated 100.1.0
123+
*/
124+
private function getCartItemOptionsProcessor()
125+
{
126+
if (!$this->cartItemOptionsProcessor instanceof CartItemOptionsProcessor) {
127+
$this->cartItemOptionsProcessor = ObjectManager::getInstance()->get(CartItemOptionsProcessor::class);
128+
}
129+
130+
return $this->cartItemOptionsProcessor;
131+
}
133132
}

dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemRepositoryTest.php

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
namespace Magento\Quote\Api;
88

9+
use Magento\Catalog\Api\ProductRepositoryInterface;
910
use Magento\Catalog\Model\CustomOptions\CustomOptionProcessor;
1011
use Magento\Framework\Webapi\Rest\Request;
1112
use Magento\Quote\Model\Quote;
@@ -83,9 +84,10 @@ public function testGetList()
8384
*/
8485
public function testAddItem()
8586
{
86-
/** @var \Magento\Catalog\Model\Product $product */
87-
$product = $this->objectManager->create(\Magento\Catalog\Model\Product::class)->load(2);
88-
$productSku = $product->getSku();
87+
$productSku = 'custom-design-simple-product';
88+
$productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
89+
$product = $productRepository->get($productSku);
90+
8991
/** @var Quote $quote */
9092
$quote = $this->objectManager->create(Quote::class);
9193
$quote->load('test_order_1', 'reserved_order_id');
@@ -110,10 +112,56 @@ public function testAddItem()
110112
],
111113
];
112114
$this->_webApiCall($serviceInfo, $requestData);
113-
$this->assertTrue($quote->hasProductId(2));
115+
$this->assertTrue($quote->hasProductId($product->getId()));
114116
$this->assertEquals(7, $quote->getItemByProduct($product)->getQty());
115117
}
116118

119+
/**
120+
* @expectedException \Exception
121+
* @expectedExceptionCode 400
122+
* @dataProvider failedAddItemDataProvider
123+
* @param array|null $cartItem
124+
*/
125+
public function testFailedAddItem(?array $cartItem)
126+
{
127+
$serviceInfo = [
128+
'rest' => [
129+
'resourcePath' => self::RESOURCE_PATH . 'mine/items',
130+
'httpMethod' => Request::HTTP_METHOD_POST,
131+
],
132+
'soap' => [
133+
'service' => self::SERVICE_NAME,
134+
'serviceVersion' => self::SERVICE_VERSION,
135+
'operation' => self::SERVICE_NAME . 'Save',
136+
],
137+
];
138+
$requestData = [
139+
'cartItem' => $cartItem,
140+
];
141+
$this->_webApiCall($serviceInfo, $requestData);
142+
}
143+
144+
/**
145+
* @return array
146+
*/
147+
public function failedAddItemDataProvider(): array
148+
{
149+
return [
150+
'absent cart item' => [
151+
null,
152+
],
153+
'empty cart item' => [
154+
[],
155+
],
156+
'absent cart id' => [
157+
[
158+
'sku' => 'custom-design-simple-product',
159+
'qty' => 7,
160+
],
161+
],
162+
];
163+
}
164+
117165
/**
118166
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
119167
*/

lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,19 @@ protected function _createFromArray($className, $data)
243243
$className = substr($className, 0, -strlen('Interface'));
244244
}
245245

246+
$typeName = $this->typeProcessor->register($className);
247+
$typeData = $this->typeProcessor->getTypeData($typeName);
248+
$requiredFields = array_filter(
249+
$typeData['parameters'],
250+
function (array $fieldData) {
251+
return $fieldData['required'];
252+
}
253+
);
254+
$missedRequiredFields = array_keys(array_diff_key($requiredFields, $data));
255+
if (!empty($missedRequiredFields)) {
256+
$this->processInputError($missedRequiredFields);
257+
}
258+
246259
// Primary method: assign to constructor parameters
247260
$constructorArgs = $this->getConstructorData($className, $data);
248261
$object = $this->objectManager->create($className, $constructorArgs);

0 commit comments

Comments
 (0)