9
9
10
10
use Magento \Framework \Exception \AuthorizationException ;
11
11
use Magento \Framework \Exception \LocalizedException ;
12
+ use Magento \Framework \Exception \NoSuchEntityException ;
12
13
use Magento \Framework \GraphQl \Config \Element \Field ;
13
14
use Magento \Framework \GraphQl \Exception \GraphQlAuthorizationException ;
14
15
use Magento \Framework \GraphQl \Exception \GraphQlInputException ;
15
16
use Magento \Framework \GraphQl \Query \ResolverInterface ;
16
17
use Magento \Framework \GraphQl \Schema \Type \ResolveInfo ;
17
- use Magento \GraphQl \ Helper \ Error \ AggregateExceptionMessageFormatter ;
18
+ use Magento \Framework \ ObjectManager \ ResetAfterRequestInterface ;
18
19
use Magento \QuoteGraphQl \Model \Cart \GetCartForCheckout ;
19
- use Magento \GraphQl \Model \Query \ContextInterface ;
20
20
use Magento \QuoteGraphQl \Model \Cart \PlaceOrder as PlaceOrderModel ;
21
21
use Magento \Sales \Api \OrderRepositoryInterface ;
22
22
23
23
/**
24
24
* Resolver for placing order after payment method has already been set
25
25
*/
26
- class PlaceOrder implements ResolverInterface
26
+ class PlaceOrder implements ResolverInterface, ResetAfterRequestInterface
27
27
{
28
+ /**#@+
29
+ * Error message codes
30
+ */
31
+ private const ERROR_CART_NOT_FOUND = 'CART_NOT_FOUND ' ;
32
+ private const ERROR_CART_NOT_ACTIVE = 'CART_NOT_ACTIVE ' ;
33
+ private const ERROR_GUEST_EMAIL_MISSING = 'GUEST_EMAIL_MISSING ' ;
34
+ private const ERROR_UNABLE_TO_PLACE_ORDER = 'UNABLE_TO_PLACE_ORDER ' ;
35
+ private const ERROR_UNDEFINED = 'UNDEFINED ' ;
36
+ /**#@-*/
37
+
38
+ /**
39
+ * List of error messages and codes.
40
+ */
41
+ private const MESSAGE_CODES = [
42
+ 'Could not find a cart with ID ' => self ::ERROR_CART_NOT_FOUND ,
43
+ 'The cart isn \'t active ' => self ::ERROR_CART_NOT_ACTIVE ,
44
+ 'Guest email for cart is missing ' => self ::ERROR_GUEST_EMAIL_MISSING ,
45
+ 'A server error stopped your order from being placed. Please try to place your order again ' =>
46
+ self ::ERROR_UNABLE_TO_PLACE_ORDER ,
47
+ 'Some addresses can \'t be used due to the configurations for specific countries ' =>
48
+ self ::ERROR_UNABLE_TO_PLACE_ORDER ,
49
+ 'The shipping method is missing. Select the shipping method and try again ' =>
50
+ self ::ERROR_UNABLE_TO_PLACE_ORDER ,
51
+ 'Please check the billing address information ' => self ::ERROR_UNABLE_TO_PLACE_ORDER ,
52
+ 'Enter a valid payment method and try again ' => self ::ERROR_UNABLE_TO_PLACE_ORDER ,
53
+ 'Some of the products are out of stock ' => self ::ERROR_UNABLE_TO_PLACE_ORDER ,
54
+ ];
55
+
28
56
/**
29
57
* @var GetCartForCheckout
30
58
*/
@@ -41,33 +69,32 @@ class PlaceOrder implements ResolverInterface
41
69
private $ orderRepository ;
42
70
43
71
/**
44
- * @var AggregateExceptionMessageFormatter
72
+ * @var \string[]
45
73
*/
46
- private $ errorMessageFormatter ;
74
+ private $ errors = [] ;
47
75
48
76
/**
49
77
* @param GetCartForCheckout $getCartForCheckout
50
78
* @param PlaceOrderModel $placeOrder
51
79
* @param OrderRepositoryInterface $orderRepository
52
- * @param AggregateExceptionMessageFormatter $errorMessageFormatter
53
80
*/
54
81
public function __construct (
55
82
GetCartForCheckout $ getCartForCheckout ,
56
83
PlaceOrderModel $ placeOrder ,
57
- OrderRepositoryInterface $ orderRepository ,
58
- AggregateExceptionMessageFormatter $ errorMessageFormatter
84
+ OrderRepositoryInterface $ orderRepository
59
85
) {
60
86
$ this ->getCartForCheckout = $ getCartForCheckout ;
61
87
$ this ->placeOrder = $ placeOrder ;
62
88
$ this ->orderRepository = $ orderRepository ;
63
- $ this ->errorMessageFormatter = $ errorMessageFormatter ;
64
89
}
65
90
66
91
/**
67
92
* @inheritdoc
68
93
*/
69
94
public function resolve (Field $ field , $ context , ResolveInfo $ info , array $ value = null , array $ args = null )
70
95
{
96
+ $ this ->errors = [];
97
+ $ order = null ;
71
98
if (empty ($ args ['input ' ]['cart_id ' ])) {
72
99
throw new GraphQlInputException (__ ('Required parameter "cart_id" is missing ' ));
73
100
}
@@ -80,28 +107,77 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
80
107
$ cart = $ this ->getCartForCheckout ->execute ($ maskedCartId , $ userId , $ storeId );
81
108
$ orderId = $ this ->placeOrder ->execute ($ cart , $ maskedCartId , $ userId );
82
109
$ order = $ this ->orderRepository ->get ($ orderId );
110
+ } catch (NoSuchEntityException $ exception ) {
111
+ $ this ->addError ($ exception ->getMessage ());
112
+ } catch (GraphQlInputException $ exception ) {
113
+ $ this ->addError ($ exception ->getMessage ());
83
114
} catch (AuthorizationException $ exception ) {
84
115
throw new GraphQlAuthorizationException (
85
116
__ ($ exception ->getMessage ())
86
117
);
87
118
} catch (LocalizedException $ e ) {
88
- throw $ this ->errorMessageFormatter ->getFormatted (
89
- $ e ,
90
- __ ('Unable to place order: A server error stopped your order from being placed. ' .
91
- 'Please try to place your order again ' ),
92
- 'Unable to place order ' ,
93
- $ field ,
94
- $ context ,
95
- $ info
96
- );
119
+ $ this ->addError ($ e ->getMessage ());
120
+ }
121
+ if ($ this ->errors ) {
122
+ return [
123
+ 'errors ' =>
124
+ $ this ->errors
125
+ ];
97
126
}
98
-
99
127
return [
100
128
'order ' => [
101
129
'order_number ' => $ order ->getIncrementId (),
102
130
// @deprecated The order_id field is deprecated, use order_number instead
103
131
'order_id ' => $ order ->getIncrementId (),
104
132
],
133
+ 'errors ' => []
134
+ ];
135
+ }
136
+
137
+ /**
138
+ * Add order line item error
139
+ *
140
+ * @param string $message
141
+ * @return void
142
+ */
143
+ private function addError (string $ message ): void
144
+ {
145
+ $ this ->errors [] = [
146
+ 'message ' => $ message ,
147
+ 'code ' => $ this ->getErrorCode ($ message )
105
148
];
106
149
}
150
+
151
+ /**
152
+ * Get message error code. Ad-hoc solution based on message parsing.
153
+ *
154
+ * @param string $message
155
+ * @return string
156
+ */
157
+ private function getErrorCode (string $ message ): string
158
+ {
159
+ $ code = self ::ERROR_UNDEFINED ;
160
+
161
+ $ matchedCodes = array_filter (
162
+ self ::MESSAGE_CODES ,
163
+ function ($ key ) use ($ message ) {
164
+ return false !== strpos ($ message , $ key );
165
+ },
166
+ ARRAY_FILTER_USE_KEY
167
+ );
168
+
169
+ if (!empty ($ matchedCodes )) {
170
+ $ code = current ($ matchedCodes );
171
+ }
172
+
173
+ return $ code ;
174
+ }
175
+
176
+ /**
177
+ * @inheritDoc
178
+ */
179
+ public function _resetState (): void
180
+ {
181
+ $ this ->errors = [];
182
+ }
107
183
}
0 commit comments