diff --git a/vendor/magento/module-checkout/Model/AddressComparator.php b/vendor/magento/module-checkout/Model/AddressComparator.php new file mode 100644 index 00000000000..c285f15e4e4 --- /dev/null +++ b/vendor/magento/module-checkout/Model/AddressComparator.php @@ -0,0 +1,79 @@ +serializer = $serializer; + } + + /** + * @inheritDoc + */ + public function isEqual(?AddressInterface $address1, ?AddressInterface $address2): bool + { + if ($address1 === null || $address2 === null) { + return false; + } + + if ($address1->getCustomerAddressId() !== null && + $address2->getCustomerAddressId() !== null + ) { + return ((int)$address1->getCustomerAddressId() === + (int)$address2->getCustomerAddressId()); + } else { + $addressKeys = array_intersect_key($address1->getData(), $address2->getData()); + $removeKeys = ['address_type', 'region_code', 'save_in_address_book']; + $addressKeys = array_diff_key($addressKeys, array_flip($removeKeys)); + + $address1Data = array_intersect_key($address1->getData(), $addressKeys); + $address2Data = array_intersect_key($address2->getData(), $addressKeys); + $diff = $this->computeArrayDifference($address1Data, $address2Data); + return empty($diff); + } + } + + /** + * Computing the difference of two arrays + * + * @param array $array1 + * @param array $array2 + * @return array + */ + private function computeArrayDifference(array $array1, array $array2): array + { + return array_udiff_assoc( + $array1, + $array2, + function ($el1, $el2) { + if (is_object($el1) || is_array($el1)) { + $el1 = $this->serializer->serialize($el1); + } + if (is_object($el2) || is_array($el2)) { + $el2 = $this->serializer->serialize($el2); + } + return strcmp((string)$el1, (string)$el2); + } + ); + } +} diff --git a/vendor/magento/module-checkout/Model/AddressComparatorInterface.php b/vendor/magento/module-checkout/Model/AddressComparatorInterface.php new file mode 100644 index 00000000000..2face53aa82 --- /dev/null +++ b/vendor/magento/module-checkout/Model/AddressComparatorInterface.php @@ -0,0 +1,22 @@ +billingAddressManagement = $billingAddressManagement; $this->paymentMethodManagement = $paymentMethodManagement; @@ -104,6 +111,8 @@ class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPa ?? ObjectManager::getInstance()->get(PaymentProcessingRateLimiterInterface::class); $this->savingRateLimiter = $savingRateLimiter ?? ObjectManager::getInstance()->get(PaymentSavingRateLimiterInterface::class); + $this->addressComparator = $addressComparator + ?? ObjectManager::getInstance()->get(AddressComparatorInterface::class); } /** @@ -165,7 +174,10 @@ class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPa $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); /** @var Quote $quote */ $quote = $this->cartRepository->getActive($quoteIdMask->getQuoteId()); - + $shippingAddress = $quote->getShippingAddress(); + if ($this->addressComparator->isEqual($shippingAddress, $billingAddress)) { + $shippingAddress->setSameAsBilling(1); + } if ($billingAddress) { $billingAddress->setEmail($email); $quote->removeAddress($quote->getBillingAddress()->getId()); @@ -194,6 +206,7 @@ class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPa * * @return \Psr\Log\LoggerInterface * @deprecated 100.1.8 + * @see not in use anymore */ private function getLogger() { diff --git a/vendor/magento/module-checkout/Model/PaymentInformationManagement.php b/vendor/magento/module-checkout/Model/PaymentInformationManagement.php index 1aad8a78bda..41867d3c835 100644 --- a/vendor/magento/module-checkout/Model/PaymentInformationManagement.php +++ b/vendor/magento/module-checkout/Model/PaymentInformationManagement.php @@ -9,9 +9,13 @@ namespace Magento\Checkout\Model; use Magento\Checkout\Api\Exception\PaymentProcessingRateLimitExceededException; use Magento\Checkout\Api\PaymentProcessingRateLimiterInterface; use Magento\Checkout\Api\PaymentSavingRateLimiterInterface; +use Magento\Customer\Api\AddressRepositoryInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\LocalizedException; use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Psr\Log\LoggerInterface; /** * Payment information management service. @@ -23,6 +27,7 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor /** * @var \Magento\Quote\Api\BillingAddressManagementInterface * @deprecated 100.1.0 This call was substituted to eliminate extra quote::save call + * @see not in use anymore */ protected $billingAddressManagement; @@ -46,11 +51,6 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor */ protected $cartTotalsRepository; - /** - * @var \Psr\Log\LoggerInterface - */ - private $logger; - /** * @var CartRepositoryInterface */ @@ -71,6 +71,21 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor */ private $saveRateLimiterDisabled = false; + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var AddressComparatorInterface + */ + private $addressComparator; + + /** + * @var LoggerInterface + */ + private $logger; + /** * @param \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement @@ -80,7 +95,11 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor * @param PaymentProcessingRateLimiterInterface|null $paymentRateLimiter * @param PaymentSavingRateLimiterInterface|null $saveRateLimiter * @param CartRepositoryInterface|null $cartRepository + * @param AddressRepositoryInterface|null $addressRepository + * @param AddressComparatorInterface|null $addressComparator + * @param LoggerInterface|null $logger * @codeCoverageIgnore + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement, @@ -90,7 +109,10 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository, ?PaymentProcessingRateLimiterInterface $paymentRateLimiter = null, ?PaymentSavingRateLimiterInterface $saveRateLimiter = null, - ?CartRepositoryInterface $cartRepository = null + ?CartRepositoryInterface $cartRepository = null, + ?AddressRepositoryInterface $addressRepository = null, + ?AddressComparatorInterface $addressComparator = null, + ?LoggerInterface $logger = null ) { $this->billingAddressManagement = $billingAddressManagement; $this->paymentMethodManagement = $paymentMethodManagement; @@ -103,6 +125,11 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor ?? ObjectManager::getInstance()->get(PaymentSavingRateLimiterInterface::class); $this->cartRepository = $cartRepository ?? ObjectManager::getInstance()->get(CartRepositoryInterface::class); + $this->addressRepository = $addressRepository + ?? ObjectManager::getInstance()->get(AddressRepositoryInterface::class); + $this->addressComparator = $addressComparator + ?? ObjectManager::getInstance()->get(AddressComparatorInterface::class); + $this->logger = $logger ?? ObjectManager::getInstance()->get(LoggerInterface::class); } /** @@ -123,8 +150,8 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor } try { $orderId = $this->cartManagement->placeOrder($cartId); - } catch (\Magento\Framework\Exception\LocalizedException $e) { - $this->getLogger()->critical( + } catch (LocalizedException $e) { + $this->logger->critical( 'Placing an order with quote_id ' . $cartId . ' is failed: ' . $e->getMessage() ); throw new CouldNotSaveException( @@ -132,7 +159,7 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor $e ); } catch (\Exception $e) { - $this->getLogger()->critical($e); + $this->logger->critical($e); throw new CouldNotSaveException( __('A server error stopped your order from being placed. Please try to place your order again.'), $e @@ -143,6 +170,8 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor /** * @inheritdoc + * + * @throws LocalizedException */ public function savePaymentInformation( $cartId, @@ -170,12 +199,8 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor $quote->removeAddress($quote->getBillingAddress()->getId()); $quote->setBillingAddress($billingAddress); $quote->setDataChanges(true); - $shippingAddress = $quote->getShippingAddress(); - if ($shippingAddress && $shippingAddress->getShippingMethod()) { - $shippingRate = $shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod()); - if ($shippingRate) { - $shippingAddress->setLimitCarrier($shippingRate->getCarrier()); - } + if ($quote->getShippingAddress()) { + $this->processShippingAddress($quote); } } $this->paymentMethodManagement->set($cartId, $paymentMethod); @@ -195,16 +220,44 @@ class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInfor } /** - * Get logger instance + * Processes shipping address. * - * @return \Psr\Log\LoggerInterface - * @deprecated 100.1.8 + * @param Quote $quote + * @return void + * @throws LocalizedException */ - private function getLogger() + private function processShippingAddress(Quote $quote): void { - if (!$this->logger) { - $this->logger = ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class); + $shippingAddress = $quote->getShippingAddress(); + $billingAddress = $quote->getBillingAddress(); + if ($shippingAddress->getShippingMethod()) { + $shippingRate = $shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod()); + if ($shippingRate) { + $shippingAddress->setLimitCarrier($shippingRate->getCarrier()); + } + } + if ($this->addressComparator->isEqual($shippingAddress, $billingAddress)) { + $shippingAddress->setSameAsBilling(1); + } + // Save new address in the customer address book and set it id for billing and shipping quote addresses. + if ($shippingAddress->getSameAsBilling() && $shippingAddress->getSaveInAddressBook()) { + $shippingAddressData = $shippingAddress->exportCustomerAddress(); + $customer = $quote->getCustomer(); + $hasDefaultBilling = (bool)$customer->getDefaultBilling(); + $hasDefaultShipping = (bool)$customer->getDefaultShipping(); + if (!$hasDefaultShipping) { + //Make provided address as default shipping address + $shippingAddressData->setIsDefaultShipping(true); + if (!$hasDefaultBilling && !$billingAddress->getSaveInAddressBook()) { + $shippingAddressData->setIsDefaultBilling(true); + } + } + $shippingAddressData->setCustomerId($quote->getCustomerId()); + $this->addressRepository->save($shippingAddressData); + $quote->addCustomerAddress($shippingAddressData); + $shippingAddress->setCustomerAddressData($shippingAddressData); + $shippingAddress->setCustomerAddressId($shippingAddressData->getId()); + $billingAddress->setCustomerAddressId($shippingAddressData->getId()); } - return $this->logger; } } diff --git a/vendor/magento/module-checkout/etc/di.xml b/vendor/magento/module-checkout/etc/di.xml index 1af46c87869..850b9187eeb 100644 --- a/vendor/magento/module-checkout/etc/di.xml +++ b/vendor/magento/module-checkout/etc/di.xml @@ -28,6 +28,7 @@ + diff --git a/vendor/magento/module-checkout/view/frontend/web/js/view/billing-address.js b/vendor/magento/module-checkout/view/frontend/web/js/view/billing-address.js index 0f21189cbec..6412fd726ed 100644 --- a/vendor/magento/module-checkout/view/frontend/web/js/view/billing-address.js +++ b/vendor/magento/module-checkout/view/frontend/web/js/view/billing-address.js @@ -283,6 +283,8 @@ function ( label = _.map(attribute.value, function (value) { return this.getCustomAttributeOptionLabel(attribute['attribute_code'], value) || value; }, this).join(', '); + } else if (typeof attribute.value === 'object') { + label = _.map(Object.values(attribute.value)).join(', '); } else { label = this.getCustomAttributeOptionLabel(attribute['attribute_code'], attribute.value); } @@ -310,6 +312,8 @@ function ( if (option) { label = option.label; } + } else if (value.file !== null) { + label = value.file; } return label; diff --git a/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js b/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js index 3a4f34c26e5..4405dfd7219 100644 --- a/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js +++ b/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js @@ -69,6 +69,8 @@ define([ label = _.map(attribute.value, function (value) { return this.getCustomAttributeOptionLabel(attribute['attribute_code'], value) || value; }, this).join(', '); + } else if (typeof attribute.value === 'object') { + label = _.map(Object.values(attribute.value)).join(', '); } else { label = this.getCustomAttributeOptionLabel(attribute['attribute_code'], attribute.value); } @@ -96,6 +98,8 @@ define([ if (option) { label = option.label; } + } else if (value.file !== null) { + label = value.file; } return label; diff --git a/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js b/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js index 03591c95e46..6a7b28f4150 100644 --- a/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js +++ b/vendor/magento/module-checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js @@ -46,6 +46,8 @@ define([ label = _.map(attribute.value, function (value) { return this.getCustomAttributeOptionLabel(attribute['attribute_code'], value) || value; }, this).join(', '); + } else if (typeof attribute.value === 'object') { + label = _.map(Object.values(attribute.value)).join(', '); } else { label = this.getCustomAttributeOptionLabel(attribute['attribute_code'], attribute.value); } @@ -73,6 +75,8 @@ define([ if (option) { label = option.label; } + } else if (value.file !== null) { + label = value.file; } return label; diff --git a/vendor/magento/module-quote/Model/QuoteManagement.php b/vendor/magento/module-quote/Model/QuoteManagement.php index b767fa9ce37..15c5b4b3879 100644 --- a/vendor/magento/module-quote/Model/QuoteManagement.php +++ b/vendor/magento/module-quote/Model/QuoteManagement.php @@ -306,7 +306,7 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface $customerActiveQuote->setIsActive(0); $this->quoteRepository->save($customerActiveQuote); - // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { } @@ -594,12 +594,13 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface * * @param Quote $quote * @return void + * @throws LocalizedException + * @throws NoSuchEntityException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _prepareCustomerQuote($quote) { - /** @var Quote $quote */ $billing = $quote->getBillingAddress(); $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress(); @@ -617,7 +618,7 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface if ($defaultShipping) { try { $shippingAddress = $this->addressRepository->getById($defaultShipping); - // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (LocalizedException $e) { // no address } @@ -651,7 +652,7 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface if ($defaultBilling) { try { $billingAddress = $this->addressRepository->getById($defaultBilling); - // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (LocalizedException $e) { // no address } @@ -672,6 +673,13 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface $billing->setCustomerAddressData($billingAddress); $this->addressesToSync[] = $billingAddress->getId(); $billing->setCustomerAddressId($billingAddress->getId()); + + // Admin order: `Same As Billing Address`- when new billing address saved in address book + if ($shipping !== null + && !$shipping->getCustomerAddressId() + && $shipping->getSameAsBilling()) { + $shipping->setCustomerAddressId($billingAddress->getId()); + } } } if ($shipping && !$shipping->getCustomerId() && !$hasDefaultBilling) {