commerce-8.x-2.8/modules/order/src/Element/ProfileSelect.php
modules/order/src/Element/ProfileSelect.php
<?php namespace Drupal\commerce_order\Element; use Drupal\commerce\Element\CommerceElementTrait; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element\RenderElement; use Drupal\profile\Entity\ProfileInterface; /** * Provides a form element for selecting a customer profile. * * Usage example: * @code * $form['billing_profile'] = [ * '#type' => 'commerce_profile_select', * '#default_value' => $profile, * '#default_country' => 'FR', * '#available_countries' => ['US', 'FR'], * ]; * @endcode * To access the profile in validation or submission callbacks, use * $form['billing_profile']['#profile']. Due to Drupal core limitations the * profile can't be accessed via $form_state->getValue('billing_profile'). * * @RenderElement("commerce_profile_select") */ class ProfileSelect extends RenderElement { use CommerceElementTrait; /** * {@inheritdoc} */ public function getInfo() { $class = get_class($this); return [ // The country to select if the address widget doesn't have a default. '#default_country' => NULL, // A list of country codes. If empty, all countries will be available. '#available_countries' => [], // The profile entity operated on. Required. '#default_value' => NULL, '#process' => [ [$class, 'attachElementSubmit'], [$class, 'processForm'], ], '#element_validate' => [ [$class, 'validateElementSubmit'], [$class, 'validateForm'], ], '#commerce_element_submit' => [ [$class, 'submitForm'], ], '#theme_wrappers' => ['container'], ]; } /** * Builds the element form. * * @param array $element * The form element being processed. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param array $complete_form * The complete form structure. * * @throws \InvalidArgumentException * Thrown when #default_value is empty or not an entity, or when * #available_countries is not an array of country codes. * * @return array * The processed form element. */ public static function processForm(array $element, FormStateInterface $form_state, array &$complete_form) { if (empty($element['#default_value'])) { throw new \InvalidArgumentException('The commerce_profile_select element requires the #default_value property.'); } elseif (isset($element['#default_value']) && !($element['#default_value'] instanceof ProfileInterface)) { throw new \InvalidArgumentException('The commerce_profile_select #default_value property must be a profile entity.'); } if (!is_array($element['#available_countries'])) { throw new \InvalidArgumentException('The commerce_profile_select #available_countries property must be an array.'); } // Make sure that the specified default country is available. if (!empty($element['#default_country']) && !empty($element['#available_countries'])) { if (!in_array($element['#default_country'], $element['#available_countries'])) { $element['#default_country'] = NULL; } } $element['#profile'] = $element['#default_value']; $form_display = EntityFormDisplay::collectRenderDisplay($element['#profile'], 'default'); $form_display->buildForm($element['#profile'], $element, $form_state); if (!empty($element['address']['widget'][0])) { $widget_element = &$element['address']['widget'][0]; // Remove the details wrapper from the address widget. $widget_element['#type'] = 'container'; // Provide a default country. if (!empty($element['#default_country']) && empty($widget_element['address']['#default_value']['country_code'])) { $widget_element['address']['#default_value']['country_code'] = $element['#default_country']; } // Limit the available countries. if (!empty($element['#available_countries'])) { $widget_element['address']['#available_countries'] = $element['#available_countries']; } } return $element; } /** * Validates the element form. * * @param array $element * The form element. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @throws \Exception * Thrown if button-level #validate handlers are detected on the parent * form, as a protection against buggy behavior. */ public static function validateForm(array &$element, FormStateInterface $form_state) { $form_display = EntityFormDisplay::collectRenderDisplay($element['#profile'], 'default'); $form_display->extractFormValues($element['#profile'], $element, $form_state); $form_display->validateFormValues($element['#profile'], $element, $form_state); } /** * Submits the element form. * * @param array $element * The form element. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ public static function submitForm(array &$element, FormStateInterface $form_state) { $form_display = EntityFormDisplay::collectRenderDisplay($element['#profile'], 'default'); $form_display->extractFormValues($element['#profile'], $element, $form_state); $element['#profile']->save(); } }