123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Checkout\Block\Checkout;
- use Magento\Checkout\Helper\Data;
- use Magento\Framework\App\ObjectManager;
- use Magento\Store\Model\StoreManagerInterface;
- /**
- * Class LayoutProcessor
- */
- class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
- {
- /**
- * @var \Magento\Customer\Model\AttributeMetadataDataProvider
- */
- private $attributeMetadataDataProvider;
- /**
- * @var \Magento\Ui\Component\Form\AttributeMapper
- */
- protected $attributeMapper;
- /**
- * @var AttributeMerger
- */
- protected $merger;
- /**
- * @var \Magento\Customer\Model\Options
- */
- private $options;
- /**
- * @var Data
- */
- private $checkoutDataHelper;
- /**
- * @var StoreManagerInterface
- */
- private $storeManager;
- /**
- * @var \Magento\Shipping\Model\Config
- */
- private $shippingConfig;
- /**
- * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider
- * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper
- * @param AttributeMerger $merger
- * @param \Magento\Customer\Model\Options|null $options
- * @param Data|null $checkoutDataHelper
- * @param \Magento\Shipping\Model\Config|null $shippingConfig
- * @param StoreManagerInterface|null $storeManager
- */
- public function __construct(
- \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider,
- \Magento\Ui\Component\Form\AttributeMapper $attributeMapper,
- AttributeMerger $merger,
- \Magento\Customer\Model\Options $options = null,
- Data $checkoutDataHelper = null,
- \Magento\Shipping\Model\Config $shippingConfig = null,
- StoreManagerInterface $storeManager = null
- ) {
- $this->attributeMetadataDataProvider = $attributeMetadataDataProvider;
- $this->attributeMapper = $attributeMapper;
- $this->merger = $merger;
- $this->options = $options ?: \Magento\Framework\App\ObjectManager::getInstance()
- ->get(\Magento\Customer\Model\Options::class);
- $this->checkoutDataHelper = $checkoutDataHelper ?: \Magento\Framework\App\ObjectManager::getInstance()
- ->get(Data::class);
- $this->shippingConfig = $shippingConfig ?: \Magento\Framework\App\ObjectManager::getInstance()
- ->get(\Magento\Shipping\Model\Config::class);
- $this->storeManager = $storeManager ?: \Magento\Framework\App\ObjectManager::getInstance()
- ->get(StoreManagerInterface::class);
- }
- /**
- * Get address attributes.
- *
- * @return array
- */
- private function getAddressAttributes()
- {
- /** @var \Magento\Eav\Api\Data\AttributeInterface[] $attributes */
- $attributes = $this->attributeMetadataDataProvider->loadAttributesCollection(
- 'customer_address',
- 'customer_register_address'
- );
- $elements = [];
- foreach ($attributes as $attribute) {
- $code = $attribute->getAttributeCode();
- if ($attribute->getIsUserDefined()) {
- continue;
- }
- $elements[$code] = $this->attributeMapper->map($attribute);
- if (isset($elements[$code]['label'])) {
- $label = $elements[$code]['label'];
- $elements[$code]['label'] = __($label);
- }
- }
- return $elements;
- }
- /**
- * Convert elements(like prefix and suffix) from inputs to selects when necessary
- *
- * @param array $elements address attributes
- * @param array $attributesToConvert fields and their callbacks
- * @return array
- */
- private function convertElementsToSelect($elements, $attributesToConvert)
- {
- $codes = array_keys($attributesToConvert);
- foreach (array_keys($elements) as $code) {
- if (!in_array($code, $codes)) {
- continue;
- }
- $options = call_user_func($attributesToConvert[$code]);
- if (!is_array($options)) {
- continue;
- }
- $elements[$code]['dataType'] = 'select';
- $elements[$code]['formElement'] = 'select';
- foreach ($options as $key => $value) {
- $elements[$code]['options'][] = [
- 'value' => $key,
- 'label' => $value,
- ];
- }
- }
- return $elements;
- }
- /**
- * Process js Layout of block
- *
- * @param array $jsLayout
- * @return array
- */
- public function process($jsLayout)
- {
- $attributesToConvert = [
- 'prefix' => [$this->options, 'getNamePrefixOptions'],
- 'suffix' => [$this->options, 'getNameSuffixOptions'],
- ];
- $elements = $this->getAddressAttributes();
- $elements = $this->convertElementsToSelect($elements, $attributesToConvert);
- // The following code is a workaround for custom address attributes
- if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
- ['payment']['children'])) {
- $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
- ['payment']['children'] = $this->processPaymentChildrenComponents(
- $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
- ['payment']['children'],
- $elements
- );
- }
- if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
- ['step-config']['children']['shipping-rates-validation']['children'])) {
- $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
- ['step-config']['children']['shipping-rates-validation']['children'] =
- $this->processShippingChildrenComponents(
- $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
- ['step-config']['children']['shipping-rates-validation']['children']
- );
- }
- if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
- ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'])) {
- $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
- ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];
- $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
- ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] = $this->merger->merge(
- $elements,
- 'checkoutProvider',
- 'shippingAddress',
- $fields
- );
- }
- return $jsLayout;
- }
- /**
- * Process shipping configuration to exclude inactive carriers.
- *
- * @param array $shippingRatesLayout
- * @return array
- */
- private function processShippingChildrenComponents($shippingRatesLayout)
- {
- $activeCarriers = $this->shippingConfig->getActiveCarriers(
- $this->storeManager->getStore()->getId()
- );
- foreach (array_keys($shippingRatesLayout) as $carrierName) {
- $carrierKey = str_replace('-rates-validation', '', $carrierName);
- if (!array_key_exists($carrierKey, $activeCarriers)) {
- unset($shippingRatesLayout[$carrierName]);
- }
- }
- return $shippingRatesLayout;
- }
- /**
- * Appends billing address form component to payment layout
- *
- * @param array $paymentLayout
- * @param array $elements
- * @return array
- */
- private function processPaymentChildrenComponents(array $paymentLayout, array $elements)
- {
- if (!isset($paymentLayout['payments-list']['children'])) {
- $paymentLayout['payments-list']['children'] = [];
- }
- if (!isset($paymentLayout['afterMethods']['children'])) {
- $paymentLayout['afterMethods']['children'] = [];
- }
- // The if billing address should be displayed on Payment method or page
- if ($this->checkoutDataHelper->isDisplayBillingOnPaymentMethodAvailable()) {
- $paymentLayout['payments-list']['children'] =
- array_merge_recursive(
- $paymentLayout['payments-list']['children'],
- $this->processPaymentConfiguration(
- $paymentLayout['renders']['children'],
- $elements
- )
- );
- } else {
- $component['billing-address-form'] = $this->getBillingAddressComponent('shared', $elements);
- $paymentLayout['afterMethods']['children'] =
- array_merge_recursive(
- $component,
- $paymentLayout['afterMethods']['children']
- );
- }
- return $paymentLayout;
- }
- /**
- * Inject billing address component into every payment component
- *
- * @param array $configuration list of payment components
- * @param array $elements attributes that must be displayed in address form
- * @return array
- */
- private function processPaymentConfiguration(array &$configuration, array $elements)
- {
- $output = [];
- foreach ($configuration as $paymentGroup => $groupConfig) {
- foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) {
- if (empty($paymentComponent['isBillingAddressRequired'])) {
- continue;
- }
- $output[$paymentCode . '-form'] = $this->getBillingAddressComponent($paymentCode, $elements);
- }
- unset($configuration[$paymentGroup]['methods']);
- }
- return $output;
- }
- /**
- * Gets billing address component details
- *
- * @param string $paymentCode
- * @param array $elements
- * @return array
- */
- private function getBillingAddressComponent($paymentCode, $elements)
- {
- return [
- 'component' => 'Magento_Checkout/js/view/billing-address',
- 'displayArea' => 'billing-address-form-' . $paymentCode,
- 'provider' => 'checkoutProvider',
- 'deps' => 'checkoutProvider',
- 'dataScopePrefix' => 'billingAddress' . $paymentCode,
- 'sortOrder' => 1,
- 'children' => [
- 'form-fields' => [
- 'component' => 'uiComponent',
- 'displayArea' => 'additional-fieldsets',
- 'children' => $this->merger->merge(
- $elements,
- 'checkoutProvider',
- 'billingAddress' . $paymentCode,
- [
- 'country_id' => [
- 'sortOrder' => 115,
- ],
- 'region' => [
- 'visible' => false,
- ],
- 'region_id' => [
- 'component' => 'Magento_Ui/js/form/element/region',
- 'config' => [
- 'template' => 'ui/form/field',
- 'elementTmpl' => 'ui/form/element/select',
- 'customEntry' => 'billingAddress' . $paymentCode . '.region',
- ],
- 'validation' => [
- 'required-entry' => true,
- ],
- 'filterBy' => [
- 'target' => '${ $.provider }:${ $.parentScope }.country_id',
- 'field' => 'country_id',
- ],
- ],
- 'postcode' => [
- 'component' => 'Magento_Ui/js/form/element/post-code',
- 'validation' => [
- 'required-entry' => true,
- ],
- ],
- 'company' => [
- 'validation' => [
- 'min_text_length' => 0,
- ],
- ],
- 'fax' => [
- 'validation' => [
- 'min_text_length' => 0,
- ],
- ],
- 'telephone' => [
- 'config' => [
- 'tooltip' => [
- 'description' => __('For delivery questions.'),
- ],
- ],
- ],
- ]
- ),
- ],
- ],
- ];
- }
- }
|