@@ -49,53 +49,58 @@ public function __construct(
49
49
* @param array $billingAddressInput
50
50
* @return void
51
51
* @throws GraphQlAuthorizationException
52
- * @throws GraphQlInputException
53
- * @throws GraphQlNoSuchEntityException
54
52
*/
55
53
public function execute (ContextInterface $ context , CartInterface $ cart , array $ billingAddressInput ): void
56
54
{
55
+ $ this ->checkForInputExceptions ($ billingAddressInput );
56
+
57
57
$ customerAddressId = $ billingAddressInput ['customer_address_id ' ] ?? null ;
58
58
$ addressInput = $ billingAddressInput ['address ' ] ?? null ;
59
+ $ useForShipping = $ billingAddressInput ['use_for_shipping ' ] ?? false ;
60
+ $ sameAsShipping = $ billingAddressInput ['same_as_shipping ' ] ?? false ;
59
61
60
- if (!$ customerAddressId && !isset ($ billingAddressInput [ ' address ' ][ ' save_in_address_book ' ]) && $ addressInput ) {
62
+ if (!$ customerAddressId && $ addressInput && !isset ($ addressInput [ ' save_in_address_book ' ])) {
61
63
$ addressInput ['save_in_address_book ' ] = true ;
62
64
}
63
65
64
- // Need to keep this for BC of `use_for_shipping` field
65
- $ sameAsShipping = isset ($ billingAddressInput ['use_for_shipping ' ])
66
- ? (bool )$ billingAddressInput ['use_for_shipping ' ] : false ;
67
- $ sameAsShipping = isset ($ billingAddressInput ['same_as_shipping ' ])
68
- ? (bool )$ billingAddressInput ['same_as_shipping ' ] : $ sameAsShipping ;
69
-
70
- $ this ->checkForInputExceptions ($ billingAddressInput );
71
-
72
- $ addresses = $ cart ->getAllShippingAddresses ();
73
- if ($ sameAsShipping && count ($ addresses ) > 1 ) {
74
- throw new GraphQlInputException (
75
- __ ('Using the "same_as_shipping" option with multishipping is not possible. ' )
66
+ if ($ sameAsShipping ) {
67
+ $ this ->validateCanUseShippingForBilling ($ cart );
68
+ $ billingAddress = $ this ->quoteAddressFactory ->createBasedOnShippingAddress ($ cart );
69
+ $ useForShipping = false ;
70
+ } elseif ($ customerAddressId ) {
71
+ $ this ->validateCanUseCustomerAddress ($ context );
72
+ $ billingAddress = $ this ->quoteAddressFactory ->createBasedOnCustomerAddress (
73
+ (int )$ customerAddressId ,
74
+ (int )$ context ->getUserId ()
76
75
);
76
+ } else {
77
+ $ billingAddress = $ this ->quoteAddressFactory ->createBasedOnInputData ($ addressInput );
77
78
}
78
79
79
- $ billingAddress = $ this ->createBillingAddress ($ context , $ customerAddressId , $ addressInput );
80
+ if ($ useForShipping ) {
81
+ $ this ->validateCanUseBillingForShipping ($ cart );
82
+ }
80
83
81
- $ this ->assignBillingAddressToCart ->execute ($ cart , $ billingAddress , $ sameAsShipping );
84
+ $ this ->validateBillingAddress ($ billingAddress );
85
+ $ this ->assignBillingAddressToCart ->execute ($ cart , $ billingAddress , $ useForShipping );
82
86
}
83
87
84
88
/**
85
89
* Check for the input exceptions
86
90
*
87
- * @param array $billingAddressInput
91
+ * @param array|null $billingAddressInput
88
92
* @throws GraphQlInputException
89
93
*/
90
94
private function checkForInputExceptions (
91
95
?array $ billingAddressInput
92
96
) {
93
97
$ customerAddressId = $ billingAddressInput ['customer_address_id ' ] ?? null ;
94
98
$ addressInput = $ billingAddressInput ['address ' ] ?? null ;
99
+ $ sameAsShipping = $ billingAddressInput ['same_as_shipping ' ] ?? null ;
95
100
96
- if (null === $ customerAddressId && null === $ addressInput ) {
101
+ if (null === $ customerAddressId && null === $ addressInput && empty ( $ sameAsShipping ) ) {
97
102
throw new GraphQlInputException (
98
- __ ('The billing address must contain either "customer_address_id" or "address ". ' )
103
+ __ ('The billing address must contain either "customer_address_id", "address", or "same_as_shipping ". ' )
99
104
);
100
105
}
101
106
@@ -107,41 +112,79 @@ private function checkForInputExceptions(
107
112
}
108
113
109
114
/**
110
- * Create billing address
115
+ * Validate that the quote is capable of using the shipping address as the billing address.
111
116
*
112
- * @param ContextInterface $context
113
- * @param int|null $customerAddressId
114
- * @param array $addressInput
115
- * @return Address
116
- * @throws GraphQlAuthorizationException
117
+ * @param CartInterface $quote
117
118
* @throws GraphQlInputException
118
- * @throws GraphQlNoSuchEntityException
119
119
*/
120
- private function createBillingAddress (
121
- ContextInterface $ context ,
122
- ?int $ customerAddressId ,
123
- ?array $ addressInput
124
- ): Address {
125
- if (null === $ customerAddressId ) {
126
- $ billingAddress = $ this ->quoteAddressFactory ->createBasedOnInputData ($ addressInput );
127
- } else {
128
- if (false === $ context ->getExtensionAttributes ()->getIsCustomer ()) {
129
- throw new GraphQlAuthorizationException (__ ('The current customer isn \'t authorized. ' ));
130
- }
120
+ private function validateCanUseShippingForBilling (CartInterface $ quote )
121
+ {
122
+ $ shippingAddresses = $ quote ->getAllShippingAddresses ();
131
123
132
- $ billingAddress = $ this -> quoteAddressFactory -> createBasedOnCustomerAddress (
133
- ( int ) $ customerAddressId ,
134
- ( int ) $ context -> getUserId ( )
124
+ if ( count ( $ shippingAddresses ) > 1 ) {
125
+ throw new GraphQlInputException (
126
+ __ ( ' Could not use the "same_as_shipping" option, because multiple shipping addresses have been set. ' )
135
127
);
136
128
}
129
+
130
+ if (empty ($ shippingAddresses ) || $ shippingAddresses [0 ]->validate () !== true ) {
131
+ throw new GraphQlInputException (
132
+ __ ('Could not use the "same_as_shipping" option, because the shipping address has not been set. ' )
133
+ );
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Validate that the quote is capable of using the billing address as the shipping address.
139
+ *
140
+ * @param CartInterface $quote
141
+ * @throws GraphQlInputException
142
+ */
143
+ private function validateCanUseBillingForShipping (CartInterface $ quote )
144
+ {
145
+ $ shippingAddresses = $ quote ->getAllShippingAddresses ();
146
+
147
+ if (count ($ shippingAddresses ) > 1 ) {
148
+ throw new GraphQlInputException (
149
+ __ ('Could not use the "use_for_shipping" option, because multiple shipping addresses have already been set. ' )
150
+ );
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Validate that the currently logged-in customer is authorized to use a customer address id as the billing address.
156
+ *
157
+ * @param ContextInterface $context
158
+ * @throws GraphQlAuthorizationException
159
+ */
160
+ private function validateCanUseCustomerAddress (ContextInterface $ context )
161
+ {
162
+ if (false === $ context ->getExtensionAttributes ()->getIsCustomer ()) {
163
+ throw new GraphQlAuthorizationException (__ ('The current customer isn \'t authorized. ' ));
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Validate the billing address to be set on the cart.
169
+ *
170
+ * @param Address $billingAddress
171
+ * @return Address
172
+ * @throws GraphQlInputException
173
+ */
174
+ private function validateBillingAddress (Address $ billingAddress )
175
+ {
137
176
$ errors = $ billingAddress ->validate ();
177
+
138
178
if (true !== $ errors ) {
139
- $ e = new GraphQlInputException (__ ('Billing address errors ' ));
179
+ $ e = new GraphQlInputException (__ ('An error occurred while processing the billing address. ' ));
180
+
140
181
foreach ($ errors as $ error ) {
141
182
$ e ->addError (new GraphQlInputException ($ error ));
142
183
}
184
+
143
185
throw $ e ;
144
186
}
187
+
145
188
return $ billingAddress ;
146
189
}
147
190
}
0 commit comments