@@ -49,53 +49,58 @@ public function __construct(
4949 * @param array $billingAddressInput
5050 * @return void
5151 * @throws GraphQlAuthorizationException
52- * @throws GraphQlInputException
53- * @throws GraphQlNoSuchEntityException
5452 */
5553 public function execute (ContextInterface $ context , CartInterface $ cart , array $ billingAddressInput ): void
5654 {
55+ $ this ->checkForInputExceptions ($ billingAddressInput );
56+
5757 $ customerAddressId = $ billingAddressInput ['customer_address_id ' ] ?? null ;
5858 $ addressInput = $ billingAddressInput ['address ' ] ?? null ;
59+ $ useForShipping = $ billingAddressInput ['use_for_shipping ' ] ?? false ;
60+ $ sameAsShipping = $ billingAddressInput ['same_as_shipping ' ] ?? false ;
5961
60- if (!$ customerAddressId && !isset ($ billingAddressInput [ ' address ' ][ ' save_in_address_book ' ]) && $ addressInput ) {
62+ if (!$ customerAddressId && $ addressInput && !isset ($ addressInput [ ' save_in_address_book ' ])) {
6163 $ addressInput ['save_in_address_book ' ] = true ;
6264 }
6365
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 ()
7675 );
76+ } else {
77+ $ billingAddress = $ this ->quoteAddressFactory ->createBasedOnInputData ($ addressInput );
7778 }
7879
79- $ billingAddress = $ this ->createBillingAddress ($ context , $ customerAddressId , $ addressInput );
80+ if ($ useForShipping ) {
81+ $ this ->validateCanUseBillingForShipping ($ cart );
82+ }
8083
81- $ this ->assignBillingAddressToCart ->execute ($ cart , $ billingAddress , $ sameAsShipping );
84+ $ this ->validateBillingAddress ($ billingAddress );
85+ $ this ->assignBillingAddressToCart ->execute ($ cart , $ billingAddress , $ useForShipping );
8286 }
8387
8488 /**
8589 * Check for the input exceptions
8690 *
87- * @param array $billingAddressInput
91+ * @param array|null $billingAddressInput
8892 * @throws GraphQlInputException
8993 */
9094 private function checkForInputExceptions (
9195 ?array $ billingAddressInput
9296 ) {
9397 $ customerAddressId = $ billingAddressInput ['customer_address_id ' ] ?? null ;
9498 $ addressInput = $ billingAddressInput ['address ' ] ?? null ;
99+ $ sameAsShipping = $ billingAddressInput ['same_as_shipping ' ] ?? null ;
95100
96- if (null === $ customerAddressId && null === $ addressInput ) {
101+ if (null === $ customerAddressId && null === $ addressInput && empty ( $ sameAsShipping ) ) {
97102 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 ". ' )
99104 );
100105 }
101106
@@ -107,41 +112,79 @@ private function checkForInputExceptions(
107112 }
108113
109114 /**
110- * Create billing address
115+ * Validate that the quote is capable of using the shipping address as the billing address.
111116 *
112- * @param ContextInterface $context
113- * @param int|null $customerAddressId
114- * @param array $addressInput
115- * @return Address
116- * @throws GraphQlAuthorizationException
117+ * @param CartInterface $quote
117118 * @throws GraphQlInputException
118- * @throws GraphQlNoSuchEntityException
119119 */
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 ();
131123
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. ' )
135127 );
136128 }
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+ {
137176 $ errors = $ billingAddress ->validate ();
177+
138178 if (true !== $ errors ) {
139- $ e = new GraphQlInputException (__ ('Billing address errors ' ));
179+ $ e = new GraphQlInputException (__ ('An error occurred while processing the billing address. ' ));
180+
140181 foreach ($ errors as $ error ) {
141182 $ e ->addError (new GraphQlInputException ($ error ));
142183 }
184+
143185 throw $ e ;
144186 }
187+
145188 return $ billingAddress ;
146189 }
147190}
0 commit comments