Skip to content

Commit 112c038

Browse files
Merge pull request #7318 from magento-honey-badgers/PWA-1611-nq-batch-operation-status
[honey] Negotiable Quote PWA-1611, PWA-1648
2 parents 7996e89 + cc67611 commit 112c038

File tree

32 files changed

+679
-81
lines changed

32 files changed

+679
-81
lines changed

app/code/Magento/CatalogInventory/Model/StockManagement.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414
use Magento\CatalogInventory\Model\Spi\StockRegistryProviderInterface;
1515
use Magento\Catalog\Api\ProductRepositoryInterface;
1616
use Magento\CatalogInventory\Model\ResourceModel\Stock as ResourceStock;
17+
use Magento\Framework\Exception\LocalizedException;
1718

1819
/**
1920
* Implements a few interfaces for backward compatibility
21+
*
22+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2023
*/
2124
class StockManagement implements StockManagementInterface, RegisterProductSaleInterface, RevertProductSaleInterface
2225
{
@@ -91,7 +94,8 @@ public function __construct(
9194
* @param string[] $items
9295
* @param int $websiteId
9396
* @return StockItemInterface[]
94-
* @throws \Magento\Framework\Exception\LocalizedException
97+
* @throws StockStateException
98+
* @throws LocalizedException
9599
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
96100
*/
97101
public function registerProductsSale($items, $websiteId = null)
@@ -118,7 +122,7 @@ public function registerProductsSale($items, $websiteId = null)
118122
&& !$this->stockState->checkQty($productId, $orderedQty, $stockItem->getWebsiteId())
119123
) {
120124
$this->getResource()->commit();
121-
throw new \Magento\Framework\Exception\LocalizedException(
125+
throw new StockStateException(
122126
__('Some of the products are out of stock.')
123127
);
124128
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\CatalogInventory\Model;
7+
8+
use Magento\Framework\Exception\LocalizedException;
9+
10+
/**
11+
* Exception class reflecting when an operation cannot be completed due to the current stock status of an inventory item
12+
*
13+
* @api
14+
*/
15+
class StockStateException extends LocalizedException
16+
{
17+
}

app/code/Magento/CatalogInventory/Test/Unit/Model/StockManagementTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public function testRegisterProductsSale(
203203
*/
204204
public function testRegisterProductsSaleException(array $items, array $lockedItems)
205205
{
206-
$this->expectException('Magento\Framework\Exception\LocalizedException');
206+
$this->expectException('Magento\CatalogInventory\Model\StockStateException');
207207
$this->expectExceptionMessage('Some of the products are out of stock.');
208208
$this->stockResourceMock
209209
->expects($this->once())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventoryGraphQl\Helper\Error\MessageFormatters;
9+
10+
use Magento\CatalogInventory\Model\StockStateException;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
use Magento\GraphQl\Helper\Error\ExceptionMessageFormatterInterface;
17+
18+
/**
19+
* Check if an internally-thrown exception is from an item stock status issue and re-throw with the message intact if so
20+
*/
21+
class StockStateExceptionMessageFormatter implements ExceptionMessageFormatterInterface
22+
{
23+
/**
24+
* If the thrown exception was from an item stock status issue, allow the message to go through
25+
*
26+
* @param LocalizedException $e
27+
* @param string $messagePrefix
28+
* @param Field $field
29+
* @param ContextInterface $context
30+
* @param ResolveInfo $info
31+
*
32+
* @return GraphQlInputException|null
33+
*/
34+
public function getFormatted(
35+
LocalizedException $e,
36+
string $messagePrefix,
37+
Field $field,
38+
ContextInterface $context,
39+
ResolveInfo $info
40+
): ?GraphQlInputException {
41+
if ($e instanceof StockStateException) {
42+
return new GraphQlInputException(__("$messagePrefix: %message", ['message' => $e->getMessage()]), $e);
43+
}
44+
return null;
45+
}
46+
}

app/code/Magento/CatalogInventoryGraphQl/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"magento/framework": "*",
88
"magento/module-store": "*",
99
"magento/module-catalog": "*",
10-
"magento/module-catalog-inventory": "*"
10+
"magento/module-catalog-inventory": "*",
11+
"magento/module-graph-ql": "*"
1112
},
1213
"license": [
1314
"OSL-3.0",

app/code/Magento/ConfigurableProductGraphQl/Model/Cart/BuyRequest/SuperAttributeDataProvider.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Catalog\Api\Data\ProductInterface;
1111
use Magento\Catalog\Api\ProductRepositoryInterface;
1212
use Magento\CatalogInventory\Api\StockStateInterface;
13+
use Magento\CatalogInventory\Model\StockStateException;
1314
use Magento\ConfigurableProductGraphQl\Model\Options\Collection as OptionCollection;
1415
use Magento\Framework\EntityManager\MetadataPool;
1516
use Magento\Framework\Exception\LocalizedException;
@@ -146,12 +147,13 @@ private function checkProductStock(string $sku, float $qty, int $scopeId): void
146147
*
147148
* @param string $parentSku
148149
* @param array $superAttributesData
150+
* @throws StockStateException
149151
* @throws LocalizedException
150152
*/
151153
private function checkSuperAttributeData(string $parentSku, array $superAttributesData): void
152154
{
153155
if (empty($superAttributesData)) {
154-
throw new LocalizedException(
156+
throw new StockStateException(
155157
__('The product with SKU %sku is out of stock.', ['sku' => $parentSku])
156158
);
157159
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Helper\Error;
9+
10+
use GraphQL\Error\ClientAware;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
use Magento\Framework\Phrase;
17+
18+
/**
19+
* Class for formatting internally-thrown errors if they match allowed exception types or using a default message if not
20+
*/
21+
class AggregateExceptionMessageFormatter
22+
{
23+
/**
24+
* @var ExceptionMessageFormatterInterface[]
25+
*/
26+
private $messageFormatters;
27+
28+
/**
29+
* @param ExceptionMessageFormatterInterface[] $messageFormatters
30+
*/
31+
public function __construct(array $messageFormatters)
32+
{
33+
$this->messageFormatters = $messageFormatters;
34+
}
35+
36+
/**
37+
* Format a thrown exception message if it matches one of the supplied formatters, otherwise use a default message
38+
*
39+
* @param LocalizedException $e
40+
* @param Phrase $defaultMessage
41+
* @param string $messagePrefix
42+
* @param Field $field
43+
* @param ContextInterface $context
44+
* @param ResolveInfo $info
45+
*
46+
* @return ClientAware
47+
*/
48+
public function getFormatted(
49+
LocalizedException $e,
50+
Phrase $defaultMessage,
51+
string $messagePrefix,
52+
Field $field,
53+
ContextInterface $context,
54+
ResolveInfo $info
55+
): ClientAware {
56+
foreach ($this->messageFormatters as $formatter) {
57+
$formatted = $formatter->getFormatted($e, $messagePrefix, $field, $context, $info);
58+
if ($formatted) {
59+
return $formatted;
60+
}
61+
}
62+
return new GraphQlInputException($defaultMessage, $e);
63+
}
64+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Helper\Error;
9+
10+
use GraphQL\Error\ClientAware;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15+
16+
/**
17+
* Interface for formatting reportable internal error messages
18+
*/
19+
interface ExceptionMessageFormatterInterface
20+
{
21+
/**
22+
* Re-throws a matching internal exception with the appropriate GraphQl exception type and user-safe message
23+
*
24+
* @param LocalizedException $e
25+
* @param string $messagePrefix
26+
* @param Field $field
27+
* @param ContextInterface $context
28+
* @param ResolveInfo $info
29+
*
30+
* @return ClientAware|null
31+
*/
32+
public function getFormatted(
33+
LocalizedException $e,
34+
string $messagePrefix,
35+
Field $field,
36+
ContextInterface $context,
37+
ResolveInfo $info
38+
): ?ClientAware;
39+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Helper\Error\MessageFormatters;
9+
10+
use GraphQL\Error\ClientAware;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException;
15+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
16+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
17+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
18+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
19+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
20+
use Magento\GraphQl\Helper\Error\ExceptionMessageFormatterInterface;
21+
22+
/**
23+
* Check if a thrown exception is already formatted for GraphQL and re-throw with no changes if so
24+
*/
25+
class GraphQlExceptionMessageFormatter implements ExceptionMessageFormatterInterface
26+
{
27+
/**
28+
* If the thrown exception is already formatted for GraphQl, re-throw it with no changes
29+
*
30+
* @param LocalizedException $e
31+
* @param string $messagePrefix
32+
* @param Field $field
33+
* @param ContextInterface $context
34+
* @param ResolveInfo $info
35+
*
36+
* @return GraphQlAlreadyExistsException|GraphQlAuthenticationException|GraphQlAuthorizationException|GraphQlInputException|GraphQlNoSuchEntityException|null
37+
*/
38+
public function getFormatted(
39+
LocalizedException $e,
40+
string $messagePrefix,
41+
Field $field,
42+
ContextInterface $context,
43+
ResolveInfo $info
44+
): ?ClientAware {
45+
if ($e instanceof GraphQlAlreadyExistsException
46+
|| $e instanceof GraphQlAuthenticationException
47+
|| $e instanceof GraphQlAuthorizationException
48+
|| $e instanceof GraphQlInputException
49+
|| $e instanceof GraphQlNoSuchEntityException) {
50+
return $e;
51+
}
52+
return null;
53+
}
54+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Helper\Error\MessageFormatters;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
14+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
use Magento\GraphQl\Helper\Error\ExceptionMessageFormatterInterface;
17+
18+
/**
19+
* Check if an internally-thrown exception is a NoSuchEntityException and re-throw with the message intact if so
20+
*/
21+
class NoSuchEntityExceptionMessageFormatter implements ExceptionMessageFormatterInterface
22+
{
23+
/**
24+
* If the thrown exception was a NoSuchEntityException, allow the message to go through
25+
*
26+
* @param LocalizedException $e
27+
* @param string $messagePrefix
28+
* @param Field $field
29+
* @param ContextInterface $context
30+
* @param ResolveInfo $info
31+
*
32+
* @return GraphQlNoSuchEntityException|null
33+
*/
34+
public function getFormatted(
35+
LocalizedException $e,
36+
string $messagePrefix,
37+
Field $field,
38+
ContextInterface $context,
39+
ResolveInfo $info
40+
): ?GraphQlNoSuchEntityException {
41+
if ($e instanceof NoSuchEntityException) {
42+
return new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
43+
}
44+
return null;
45+
}
46+
}

0 commit comments

Comments
 (0)