Skip to content

Commit fc55693

Browse files
committed
Merge remote-tracking branch 'origin/MAGETWO-56925' into 2.0-develop-pr2
2 parents 0a28ca0 + e638c0b commit fc55693

File tree

13 files changed

+787
-215
lines changed

13 files changed

+787
-215
lines changed

app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php

Lines changed: 218 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
*/
66
namespace Magento\Checkout\Block\Checkout;
77

8+
use Magento\Checkout\Helper\Data;
9+
use Magento\Framework\App\ObjectManager;
10+
811
class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
912
{
1013
/**
@@ -22,6 +25,16 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso
2225
*/
2326
protected $merger;
2427

28+
/**
29+
* @var \Magento\Customer\Model\Options
30+
*/
31+
private $options;
32+
33+
/**
34+
* @var Data
35+
*/
36+
private $checkoutDataHelper;
37+
2538
/**
2639
* @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider
2740
* @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper
@@ -38,12 +51,22 @@ public function __construct(
3851
}
3952

4053
/**
41-
* Process js Layout of block
42-
*
43-
* @param array $jsLayout
54+
* @deprecated
55+
* @return \Magento\Customer\Model\Options
56+
*/
57+
private function getOptions()
58+
{
59+
if (!is_object($this->options)) {
60+
$this->options = ObjectManager::getInstance()->get(\Magento\Customer\Model\Options::class);
61+
}
62+
return $this->options;
63+
}
64+
65+
/**
66+
* Get addresses attributes
4467
* @return array
4568
*/
46-
public function process($jsLayout)
69+
private function getAddressAttributes()
4770
{
4871
/** @var \Magento\Eav\Api\Data\AttributeInterface[] $attributes */
4972
$attributes = $this->attributeMetadataDataProvider->loadAttributesCollection(
@@ -53,37 +76,77 @@ public function process($jsLayout)
5376

5477
$elements = [];
5578
foreach ($attributes as $attribute) {
79+
$code = $attribute->getAttributeCode();
5680
if ($attribute->getIsUserDefined()) {
5781
continue;
5882
}
59-
$elements[$attribute->getAttributeCode()] = $this->attributeMapper->map($attribute);
60-
if (isset($elements[$attribute->getAttributeCode()]['label'])) {
61-
$label = $elements[$attribute->getAttributeCode()]['label'];
62-
$elements[$attribute->getAttributeCode()]['label'] = __($label);
83+
$elements[$code] = $this->attributeMapper->map($attribute);
84+
if (isset($elements[$code]['label'])) {
85+
$label = $elements[$code]['label'];
86+
$elements[$code]['label'] = __($label);
6387
}
6488
}
6589

90+
return $elements;
91+
}
92+
93+
/**
94+
* Convert elements(like prefix and suffix) from inputs to selects when necessary
95+
*
96+
* @param array $elements address attributes
97+
* @param array $attributesToConvert fields and their callbacks
98+
* @return array
99+
*/
100+
private function convertElementsToSelect($elements, $attributesToConvert)
101+
{
102+
$codes = array_keys($attributesToConvert);
103+
foreach (array_keys($elements) as $code) {
104+
if (!in_array($code, $codes)) {
105+
continue;
106+
}
107+
$options = call_user_func($attributesToConvert[$code]);
108+
if (!is_array($options)) {
109+
continue;
110+
}
111+
$elements[$code]['dataType'] = 'select';
112+
$elements[$code]['formElement'] = 'select';
113+
114+
foreach ($options as $key => $value) {
115+
$elements[$code]['options'][] = [
116+
'value' => $key,
117+
'label' => $value,
118+
];
119+
}
120+
}
121+
122+
return $elements;
123+
}
124+
125+
/**
126+
* Process js Layout of block
127+
*
128+
* @param array $jsLayout
129+
* @return array
130+
*/
131+
public function process($jsLayout)
132+
{
133+
$attributesToConvert = [
134+
'prefix' => [$this->getOptions(), 'getNamePrefixOptions'],
135+
'suffix' => [$this->getOptions(), 'getNameSuffixOptions'],
136+
];
137+
138+
$elements = $this->getAddressAttributes();
139+
$elements = $this->convertElementsToSelect($elements, $attributesToConvert);
66140
// The following code is a workaround for custom address attributes
67141
if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
68142
['payment']['children']
69143
)) {
70-
if (!isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
71-
['payment']['children']['payments-list']['children'])) {
72-
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
73-
['payment']['children']['payments-list']['children'] = [];
74-
}
75-
76144
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
77-
['payment']['children']['payments-list']['children'] =
78-
array_merge_recursive(
79-
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
80-
['payment']['children']['payments-list']['children'],
81-
$this->processPaymentConfiguration(
82-
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
83-
['payment']['children']['renders']['children'],
84-
$elements
85-
)
86-
);
145+
['payment']['children'] = $this->processPaymentChildrenComponents(
146+
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
147+
['payment']['children'],
148+
$elements
149+
);
87150
}
88151

89152
if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
@@ -99,9 +162,48 @@ public function process($jsLayout)
99162
$fields
100163
);
101164
}
165+
102166
return $jsLayout;
103167
}
104168

169+
/**
170+
* Appends billing address form component to payment layout
171+
* @param array $paymentLayout
172+
* @param array $elements
173+
* @return array
174+
*/
175+
private function processPaymentChildrenComponents(array $paymentLayout, array $elements)
176+
{
177+
if (!isset($paymentLayout['payments-list']['children'])) {
178+
$paymentLayout['payments-list']['children'] = [];
179+
}
180+
181+
if (!isset($paymentLayout['afterMethods']['children'])) {
182+
$paymentLayout['afterMethods']['children'] = [];
183+
}
184+
185+
// The if billing address should be displayed on Payment method or page
186+
if ($this->getCheckoutDataHelper()->isDisplayBillingOnPaymentMethodAvailable()) {
187+
$paymentLayout['payments-list']['children'] =
188+
array_merge_recursive(
189+
$paymentLayout['payments-list']['children'],
190+
$this->processPaymentConfiguration(
191+
$paymentLayout['renders']['children'],
192+
$elements
193+
)
194+
);
195+
} else {
196+
$component['billing-address-form'] = $this->getBillingAddressComponent('shared', $elements);
197+
$paymentLayout['afterMethods']['children'] =
198+
array_merge_recursive(
199+
$component,
200+
$paymentLayout['afterMethods']['children']
201+
);
202+
}
203+
204+
return $paymentLayout;
205+
}
206+
105207
/**
106208
* Inject billing address component into every payment component
107209
*
@@ -117,75 +219,102 @@ private function processPaymentConfiguration(array &$configuration, array $eleme
117219
if (empty($paymentComponent['isBillingAddressRequired'])) {
118220
continue;
119221
}
120-
$output[$paymentCode . '-form'] = [
121-
'component' => 'Magento_Checkout/js/view/billing-address',
122-
'displayArea' => 'billing-address-form-' . $paymentCode,
123-
'provider' => 'checkoutProvider',
124-
'deps' => 'checkoutProvider',
125-
'dataScopePrefix' => 'billingAddress' . $paymentCode,
126-
'sortOrder' => 1,
127-
'children' => [
128-
'form-fields' => [
129-
'component' => 'uiComponent',
130-
'displayArea' => 'additional-fieldsets',
131-
'children' => $this->merger->merge(
132-
$elements,
133-
'checkoutProvider',
134-
'billingAddress' . $paymentCode,
135-
[
136-
'country_id' => [
137-
'sortOrder' => 115,
138-
],
139-
'region' => [
140-
'visible' => false,
141-
],
142-
'region_id' => [
143-
'component' => 'Magento_Ui/js/form/element/region',
144-
'config' => [
145-
'template' => 'ui/form/field',
146-
'elementTmpl' => 'ui/form/element/select',
147-
'customEntry' => 'billingAddress' . $paymentCode . '.region',
148-
],
149-
'validation' => [
150-
'validate-select' => true,
151-
],
152-
'filterBy' => [
153-
'target' => '${ $.provider }:${ $.parentScope }.country_id',
154-
'field' => 'country_id',
155-
],
156-
],
157-
'postcode' => [
158-
'component' => 'Magento_Ui/js/form/element/post-code',
159-
'validation' => [
160-
'required-entry' => true,
161-
],
162-
],
163-
'company' => [
164-
'validation' => [
165-
'min_text_length' => 0,
166-
],
167-
],
168-
'fax' => [
169-
'validation' => [
170-
'min_text_length' => 0,
171-
],
172-
],
173-
'telephone' => [
174-
'config' => [
175-
'tooltip' => [
176-
'description' => 'For delivery questions.',
177-
],
178-
],
179-
],
180-
]
181-
),
182-
],
183-
],
184-
];
222+
$output[$paymentCode . '-form'] = $this->getBillingAddressComponent($paymentCode, $elements);
185223
}
186224
unset($configuration[$paymentGroup]['methods']);
187225
}
188226

189227
return $output;
190228
}
229+
230+
/**
231+
* Gets billing address component details
232+
*
233+
* @param string $paymentCode
234+
* @param array $elements
235+
* @return array
236+
*/
237+
private function getBillingAddressComponent($paymentCode, $elements)
238+
{
239+
return [
240+
'component' => 'Magento_Checkout/js/view/billing-address',
241+
'displayArea' => 'billing-address-form-' . $paymentCode,
242+
'provider' => 'checkoutProvider',
243+
'deps' => 'checkoutProvider',
244+
'dataScopePrefix' => 'billingAddress' . $paymentCode,
245+
'sortOrder' => 1,
246+
'children' => [
247+
'form-fields' => [
248+
'component' => 'uiComponent',
249+
'displayArea' => 'additional-fieldsets',
250+
'children' => $this->merger->merge(
251+
$elements,
252+
'checkoutProvider',
253+
'billingAddress' . $paymentCode,
254+
[
255+
'country_id' => [
256+
'sortOrder' => 115,
257+
],
258+
'region' => [
259+
'visible' => false,
260+
],
261+
'region_id' => [
262+
'component' => 'Magento_Ui/js/form/element/region',
263+
'config' => [
264+
'template' => 'ui/form/field',
265+
'elementTmpl' => 'ui/form/element/select',
266+
'customEntry' => 'billingAddress' . $paymentCode . '.region',
267+
],
268+
'validation' => [
269+
'required-entry' => true,
270+
],
271+
'filterBy' => [
272+
'target' => '${ $.provider }:${ $.parentScope }.country_id',
273+
'field' => 'country_id',
274+
],
275+
],
276+
'postcode' => [
277+
'component' => 'Magento_Ui/js/form/element/post-code',
278+
'validation' => [
279+
'required-entry' => true,
280+
],
281+
],
282+
'company' => [
283+
'validation' => [
284+
'min_text_length' => 0,
285+
],
286+
],
287+
'fax' => [
288+
'validation' => [
289+
'min_text_length' => 0,
290+
],
291+
],
292+
'telephone' => [
293+
'config' => [
294+
'tooltip' => [
295+
'description' => __('For delivery questions.'),
296+
],
297+
],
298+
],
299+
]
300+
),
301+
],
302+
],
303+
];
304+
}
305+
306+
/**
307+
* Get checkout data helper instance
308+
*
309+
* @return Data
310+
* @deprecated
311+
*/
312+
private function getCheckoutDataHelper()
313+
{
314+
if (!$this->checkoutDataHelper) {
315+
$this->checkoutDataHelper = ObjectManager::getInstance()->get(Data::class);
316+
}
317+
318+
return $this->checkoutDataHelper;
319+
}
191320
}

0 commit comments

Comments
 (0)