PageRenderTime 28ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/crazybutterfly815/magento2
PHP | 257 lines | 189 code | 18 blank | 50 comment | 9 complexity | cd98c46d4078ae96307e293d7153f8f5 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright © 2016 Magento. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Checkout\Block\Checkout;
  7. use Magento\Framework\App\ObjectManager;
  8. class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
  9. {
  10. /**
  11. * @var \Magento\Customer\Model\AttributeMetadataDataProvider
  12. */
  13. private $attributeMetadataDataProvider;
  14. /**
  15. * @var \Magento\Ui\Component\Form\AttributeMapper
  16. */
  17. protected $attributeMapper;
  18. /**
  19. * @var AttributeMerger
  20. */
  21. protected $merger;
  22. /**
  23. * @var \Magento\Customer\Model\Options
  24. */
  25. private $options;
  26. /**
  27. * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider
  28. * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper
  29. * @param AttributeMerger $merger
  30. */
  31. public function __construct(
  32. \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider,
  33. \Magento\Ui\Component\Form\AttributeMapper $attributeMapper,
  34. AttributeMerger $merger
  35. ) {
  36. $this->attributeMetadataDataProvider = $attributeMetadataDataProvider;
  37. $this->attributeMapper = $attributeMapper;
  38. $this->merger = $merger;
  39. }
  40. /**
  41. * @deprecated
  42. * @return \Magento\Customer\Model\Options
  43. */
  44. private function getOptions()
  45. {
  46. if (!is_object($this->options)) {
  47. $this->options = ObjectManager::getInstance()->get(\Magento\Customer\Model\Options::class);
  48. }
  49. return $this->options;
  50. }
  51. /**
  52. * @return array
  53. */
  54. private function getAddressAttributes()
  55. {
  56. /** @var \Magento\Eav\Api\Data\AttributeInterface[] $attributes */
  57. $attributes = $this->attributeMetadataDataProvider->loadAttributesCollection(
  58. 'customer_address',
  59. 'customer_register_address'
  60. );
  61. $elements = [];
  62. foreach ($attributes as $attribute) {
  63. $code = $attribute->getAttributeCode();
  64. if ($attribute->getIsUserDefined()) {
  65. continue;
  66. }
  67. $elements[$code] = $this->attributeMapper->map($attribute);
  68. if (isset($elements[$code]['label'])) {
  69. $label = $elements[$code]['label'];
  70. $elements[$code]['label'] = __($label);
  71. }
  72. }
  73. return $elements;
  74. }
  75. /**
  76. * Convert elements(like prefix and suffix) from inputs to selects when necessary
  77. *
  78. * @param array $elements address attributes
  79. * @param array $attributesToConvert fields and their callbacks
  80. * @return array
  81. */
  82. private function convertElementsToSelect($elements, $attributesToConvert)
  83. {
  84. $codes = array_keys($attributesToConvert);
  85. foreach (array_keys($elements) as $code) {
  86. if (!in_array($code, $codes)) {
  87. continue;
  88. }
  89. $options = call_user_func($attributesToConvert[$code]);
  90. if (!is_array($options)) {
  91. continue;
  92. }
  93. $elements[$code]['dataType'] = 'select';
  94. $elements[$code]['formElement'] = 'select';
  95. foreach ($options as $key => $value) {
  96. $elements[$code]['options'][] = [
  97. 'value' => $key,
  98. 'label' => $value,
  99. ];
  100. }
  101. }
  102. return $elements;
  103. }
  104. /**
  105. * Process js Layout of block
  106. *
  107. * @param array $jsLayout
  108. * @return array
  109. */
  110. public function process($jsLayout)
  111. {
  112. $attributesToConvert = [
  113. 'prefix' => [$this->getOptions(), 'getNamePrefixOptions'],
  114. 'suffix' => [$this->getOptions(), 'getNameSuffixOptions'],
  115. ];
  116. $elements = $this->getAddressAttributes();
  117. $elements = $this->convertElementsToSelect($elements, $attributesToConvert);
  118. // The following code is a workaround for custom address attributes
  119. if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
  120. ['payment']['children']
  121. )) {
  122. if (!isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
  123. ['payment']['children']['payments-list']['children'])) {
  124. $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
  125. ['payment']['children']['payments-list']['children'] = [];
  126. }
  127. $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
  128. ['payment']['children']['payments-list']['children'] =
  129. array_merge_recursive(
  130. $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
  131. ['payment']['children']['payments-list']['children'],
  132. $this->processPaymentConfiguration(
  133. $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
  134. ['payment']['children']['renders']['children'],
  135. $elements
  136. )
  137. );
  138. }
  139. if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
  140. ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']
  141. )) {
  142. $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
  143. ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];
  144. $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
  145. ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] = $this->merger->merge(
  146. $elements,
  147. 'checkoutProvider',
  148. 'shippingAddress',
  149. $fields
  150. );
  151. }
  152. return $jsLayout;
  153. }
  154. /**
  155. * Inject billing address component into every payment component
  156. *
  157. * @param array $configuration list of payment components
  158. * @param array $elements attributes that must be displayed in address form
  159. * @return array
  160. */
  161. private function processPaymentConfiguration(array &$configuration, array $elements)
  162. {
  163. $output = [];
  164. foreach ($configuration as $paymentGroup => $groupConfig) {
  165. foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) {
  166. if (empty($paymentComponent['isBillingAddressRequired'])) {
  167. continue;
  168. }
  169. $output[$paymentCode . '-form'] = [
  170. 'component' => 'Magento_Checkout/js/view/billing-address',
  171. 'displayArea' => 'billing-address-form-' . $paymentCode,
  172. 'provider' => 'checkoutProvider',
  173. 'deps' => 'checkoutProvider',
  174. 'dataScopePrefix' => 'billingAddress' . $paymentCode,
  175. 'sortOrder' => 1,
  176. 'children' => [
  177. 'form-fields' => [
  178. 'component' => 'uiComponent',
  179. 'displayArea' => 'additional-fieldsets',
  180. 'children' => $this->merger->merge(
  181. $elements,
  182. 'checkoutProvider',
  183. 'billingAddress' . $paymentCode,
  184. [
  185. 'country_id' => [
  186. 'sortOrder' => 115,
  187. ],
  188. 'region' => [
  189. 'visible' => false,
  190. ],
  191. 'region_id' => [
  192. 'component' => 'Magento_Ui/js/form/element/region',
  193. 'config' => [
  194. 'template' => 'ui/form/field',
  195. 'elementTmpl' => 'ui/form/element/select',
  196. 'customEntry' => 'billingAddress' . $paymentCode . '.region',
  197. ],
  198. 'validation' => [
  199. 'required-entry' => true,
  200. ],
  201. 'filterBy' => [
  202. 'target' => '${ $.provider }:${ $.parentScope }.country_id',
  203. 'field' => 'country_id',
  204. ],
  205. ],
  206. 'postcode' => [
  207. 'component' => 'Magento_Ui/js/form/element/post-code',
  208. 'validation' => [
  209. 'required-entry' => true,
  210. ],
  211. ],
  212. 'company' => [
  213. 'validation' => [
  214. 'min_text_length' => 0,
  215. ],
  216. ],
  217. 'fax' => [
  218. 'validation' => [
  219. 'min_text_length' => 0,
  220. ],
  221. ],
  222. 'telephone' => [
  223. 'config' => [
  224. 'tooltip' => [
  225. 'description' => __('For delivery questions.'),
  226. ],
  227. ],
  228. ],
  229. ]
  230. ),
  231. ],
  232. ],
  233. ];
  234. }
  235. unset($configuration[$paymentGroup]['methods']);
  236. }
  237. return $output;
  238. }
  239. }