Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
LayoutProcessor.php
Go to the documentation of this file.
1 <?php
7 
11 
16 {
20  private $attributeMetadataDataProvider;
21 
25  protected $attributeMapper;
26 
30  protected $merger;
31 
35  private $options;
36 
40  private $checkoutDataHelper;
41 
45  private $storeManager;
46 
50  private $shippingConfig;
51 
61  public function __construct(
62  \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider,
63  \Magento\Ui\Component\Form\AttributeMapper $attributeMapper,
65  \Magento\Customer\Model\Options $options = null,
66  Data $checkoutDataHelper = null,
67  \Magento\Shipping\Model\Config $shippingConfig = null,
68  StoreManagerInterface $storeManager = null
69  ) {
70  $this->attributeMetadataDataProvider = $attributeMetadataDataProvider;
71  $this->attributeMapper = $attributeMapper;
72  $this->merger = $merger;
73  $this->options = $options ?: \Magento\Framework\App\ObjectManager::getInstance()
74  ->get(\Magento\Customer\Model\Options::class);
75  $this->checkoutDataHelper = $checkoutDataHelper ?: \Magento\Framework\App\ObjectManager::getInstance()
76  ->get(Data::class);
77  $this->shippingConfig = $shippingConfig ?: \Magento\Framework\App\ObjectManager::getInstance()
78  ->get(\Magento\Shipping\Model\Config::class);
79  $this->storeManager = $storeManager ?: \Magento\Framework\App\ObjectManager::getInstance()
80  ->get(StoreManagerInterface::class);
81  }
82 
88  private function getAddressAttributes()
89  {
91  $attributes = $this->attributeMetadataDataProvider->loadAttributesCollection(
92  'customer_address',
93  'customer_register_address'
94  );
95 
96  $elements = [];
97  foreach ($attributes as $attribute) {
98  $code = $attribute->getAttributeCode();
99  if ($attribute->getIsUserDefined()) {
100  continue;
101  }
102  $elements[$code] = $this->attributeMapper->map($attribute);
103  if (isset($elements[$code]['label'])) {
104  $label = $elements[$code]['label'];
105  $elements[$code]['label'] = __($label);
106  }
107  }
108  return $elements;
109  }
110 
118  private function convertElementsToSelect($elements, $attributesToConvert)
119  {
120  $codes = array_keys($attributesToConvert);
121  foreach (array_keys($elements) as $code) {
122  if (!in_array($code, $codes)) {
123  continue;
124  }
125  $options = call_user_func($attributesToConvert[$code]);
126  if (!is_array($options)) {
127  continue;
128  }
129  $elements[$code]['dataType'] = 'select';
130  $elements[$code]['formElement'] = 'select';
131 
132  foreach ($options as $key => $value) {
133  $elements[$code]['options'][] = [
134  'value' => $key,
135  'label' => $value,
136  ];
137  }
138  }
139 
140  return $elements;
141  }
142 
149  public function process($jsLayout)
150  {
151  $attributesToConvert = [
152  'prefix' => [$this->options, 'getNamePrefixOptions'],
153  'suffix' => [$this->options, 'getNameSuffixOptions'],
154  ];
155 
156  $elements = $this->getAddressAttributes();
157  $elements = $this->convertElementsToSelect($elements, $attributesToConvert);
158  // The following code is a workaround for custom address attributes
159  if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
160  ['payment']['children'])) {
161  $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
162  ['payment']['children'] = $this->processPaymentChildrenComponents(
163  $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
164  ['payment']['children'],
165  $elements
166  );
167  }
168  if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
169  ['step-config']['children']['shipping-rates-validation']['children'])) {
170  $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
171  ['step-config']['children']['shipping-rates-validation']['children'] =
172  $this->processShippingChildrenComponents(
173  $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
174  ['step-config']['children']['shipping-rates-validation']['children']
175  );
176  }
177 
178  if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
179  ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'])) {
180  $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
181  ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];
182  $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
183  ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] = $this->merger->merge(
184  $elements,
185  'checkoutProvider',
186  'shippingAddress',
187  $fields
188  );
189  }
190  return $jsLayout;
191  }
192 
199  private function processShippingChildrenComponents($shippingRatesLayout)
200  {
201  $activeCarriers = $this->shippingConfig->getActiveCarriers(
202  $this->storeManager->getStore()->getId()
203  );
204  foreach (array_keys($shippingRatesLayout) as $carrierName) {
205  $carrierKey = str_replace('-rates-validation', '', $carrierName);
206  if (!array_key_exists($carrierKey, $activeCarriers)) {
207  unset($shippingRatesLayout[$carrierName]);
208  }
209  }
210  return $shippingRatesLayout;
211  }
212 
220  private function processPaymentChildrenComponents(array $paymentLayout, array $elements)
221  {
222  if (!isset($paymentLayout['payments-list']['children'])) {
223  $paymentLayout['payments-list']['children'] = [];
224  }
225 
226  if (!isset($paymentLayout['afterMethods']['children'])) {
227  $paymentLayout['afterMethods']['children'] = [];
228  }
229 
230  // The if billing address should be displayed on Payment method or page
231  if ($this->checkoutDataHelper->isDisplayBillingOnPaymentMethodAvailable()) {
232  $paymentLayout['payments-list']['children'] =
233  array_merge_recursive(
234  $paymentLayout['payments-list']['children'],
235  $this->processPaymentConfiguration(
236  $paymentLayout['renders']['children'],
237  $elements
238  )
239  );
240  } else {
241  $component['billing-address-form'] = $this->getBillingAddressComponent('shared', $elements);
242  $paymentLayout['afterMethods']['children'] =
243  array_merge_recursive(
244  $component,
245  $paymentLayout['afterMethods']['children']
246  );
247  }
248 
249  return $paymentLayout;
250  }
251 
259  private function processPaymentConfiguration(array &$configuration, array $elements)
260  {
261  $output = [];
262  foreach ($configuration as $paymentGroup => $groupConfig) {
263  foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) {
264  if (empty($paymentComponent['isBillingAddressRequired'])) {
265  continue;
266  }
267  $output[$paymentCode . '-form'] = $this->getBillingAddressComponent($paymentCode, $elements);
268  }
269  unset($configuration[$paymentGroup]['methods']);
270  }
271 
272  return $output;
273  }
274 
282  private function getBillingAddressComponent($paymentCode, $elements)
283  {
284  return [
285  'component' => 'Magento_Checkout/js/view/billing-address',
286  'displayArea' => 'billing-address-form-' . $paymentCode,
287  'provider' => 'checkoutProvider',
288  'deps' => 'checkoutProvider',
289  'dataScopePrefix' => 'billingAddress' . $paymentCode,
290  'sortOrder' => 1,
291  'children' => [
292  'form-fields' => [
293  'component' => 'uiComponent',
294  'displayArea' => 'additional-fieldsets',
295  'children' => $this->merger->merge(
296  $elements,
297  'checkoutProvider',
298  'billingAddress' . $paymentCode,
299  [
300  'country_id' => [
301  'sortOrder' => 115,
302  ],
303  'region' => [
304  'visible' => false,
305  ],
306  'region_id' => [
307  'component' => 'Magento_Ui/js/form/element/region',
308  'config' => [
309  'template' => 'ui/form/field',
310  'elementTmpl' => 'ui/form/element/select',
311  'customEntry' => 'billingAddress' . $paymentCode . '.region',
312  ],
313  'validation' => [
314  'required-entry' => true,
315  ],
316  'filterBy' => [
317  'target' => '${ $.provider }:${ $.parentScope }.country_id',
318  'field' => 'country_id',
319  ],
320  ],
321  'postcode' => [
322  'component' => 'Magento_Ui/js/form/element/post-code',
323  'validation' => [
324  'required-entry' => true,
325  ],
326  ],
327  'company' => [
328  'validation' => [
329  'min_text_length' => 0,
330  ],
331  ],
332  'fax' => [
333  'validation' => [
334  'min_text_length' => 0,
335  ],
336  ],
337  'telephone' => [
338  'config' => [
339  'tooltip' => [
340  'description' => __('For delivery questions.'),
341  ],
342  ],
343  ],
344  ]
345  ),
346  ],
347  ],
348  ];
349  }
350 }
$configuration
Definition: index.php:33
$fields
Definition: details.phtml:14
__()
Definition: __.php:13
$label
Definition: details.phtml:21
$value
Definition: gender.phtml:16
__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)
$attributes
Definition: matrix.phtml:13
$code
Definition: info.phtml:12