Skip to content

Commit

Permalink
Issue #2844920 by johnhuang0808: Make multiple commerce_profile_selec…
Browse files Browse the repository at this point in the history
…t form elements available in the same form and so one.
  • Loading branch information
ymhuang0808 committed Aug 31, 2017
1 parent 3d70f0e commit 57c1117
Show file tree
Hide file tree
Showing 7 changed files with 693 additions and 54 deletions.
99 changes: 87 additions & 12 deletions modules/order/src/Element/ProfileSelect.php
Expand Up @@ -55,6 +55,7 @@ public function getInfo() {
],
'#element_validate' => [
[$class, 'validateElementSubmit'],
[$class, 'validateValueChanged'],
[$class, 'validateForm'],
],
'#commerce_element_submit' => [
Expand Down Expand Up @@ -125,7 +126,9 @@ public static function processForm(array $element, FormStateInterface $form_stat

// If this is the first form build, set the element's value based on
// the user's default profile.
if (!$form_state->isProcessingInput() && $existing_profile->isDefault()) {
if (!$form_state->isProcessingInput() &&
$existing_profile->isDefault() &&
$element['#value'] == '_new') {
$element['#value'] = $existing_profile->id();
}
}
Expand All @@ -134,13 +137,13 @@ public static function processForm(array $element, FormStateInterface $form_stat
$id_prefix = implode('-', $element['#parents']);
$wrapper_id = Html::getUniqueId($id_prefix . '-ajax-wrapper');
$element = [
'#tree' => TRUE,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
// Pass the id along to other methods.
'#wrapper_id' => $wrapper_id,
'#element_mode' => $form_state->get('element_mode') ?: 'view',
] + $element;
'#tree' => TRUE,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
// Pass the id along to other methods.
'#wrapper_id' => $wrapper_id,
'#element_mode' => $form_state->get('element_mode-' . $id_prefix . '-edit_button') ?: 'view',
] + $element;

if (!empty($user_profiles)) {
$element['profile_selection'] = [
Expand Down Expand Up @@ -180,7 +183,9 @@ public static function processForm(array $element, FormStateInterface $form_stat
if (!$element_profile->isNew() && $element['#element_mode'] == 'view') {
$view_builder = $entity_type_manager->getViewBuilder('profile');
$element['rendered_profile'] = $view_builder->view($element_profile, 'default');

// Make the name of edit_button element unique in multiple elements form
$edit_button_name = (isset($element['#parents'])) ? implode('_', $element['#parents']) . '_' : '';
$edit_button_name .= 'edit_profile';
$element['edit_button'] = [
'#type' => 'submit',
'#value' => t('Edit'),
Expand All @@ -190,7 +195,7 @@ public static function processForm(array $element, FormStateInterface $form_stat
'wrapper' => $wrapper_id,
],
'#submit' => [[get_called_class(), 'ajaxSubmit']],
'#name' => 'edit_profile',
'#name' => $edit_button_name,
'#element_mode' => 'edit',
];
}
Expand All @@ -217,6 +222,37 @@ public static function processForm(array $element, FormStateInterface $form_stat
return $element;
}

/**
* Validate whether the value of address field is changed or note.
* If the value of address field is changed, the profile_selection is _new for
* creating a new Profile entity.
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function validateValueChanged(array &$element, FormStateInterface $form_state) {
$value = $form_state->getValue($element['#parents']);

if ($value['profile_selection'] != '_new' &&
$element['#element_mode'] == 'edit') {
/** @var \Drupal\profile\ProfileStorageInterface $profile_storage */
$profile_storage = \Drupal::entityTypeManager()->getStorage('profile');
/** @var \Drupal\profile\Entity\Profile $element_profile */
$element_profile = $profile_storage->load($value['profile_selection']);

if ($element_profile->hasField('address')) {
$address = $element_profile->get('address')->getValue();
// Compare the input address and profile address to check if the address from input is changed
if (isset($value['address']) && !static::addressEquals($value['address'][0]['address'], $address[0])) {
$profile_selection_key = array_merge($element['#parents'], ['profile_selection']);
$form_state->setValue($profile_selection_key, '_new');
}
}
}
}

/**
* Validates the element form.
*
Expand Down Expand Up @@ -253,6 +289,17 @@ public static function validateForm(array &$element, FormStateInterface $form_st
}

$form_state->setValueForElement($element, $element_profile);

$triggering_element = $form_state->getTriggeringElement();
$element_parents = array_merge($element['#parents'], ['profile_selection']);
// Check if the triggering element is profile_selection element
if ($triggering_element['#parents'] === $element_parents && $element['#element_mode'] === 'edit') {
// Clear the input value
$input = &$form_state->getUserInput();
$address_parents = array_merge($element['#parents'], ['address', 0, 'address']);
NestedArray::unsetValue($input, $address_parents);
$form_state->setRebuild();
}
}

/**
Expand All @@ -264,12 +311,18 @@ public static function validateForm(array &$element, FormStateInterface $form_st
* The current state of the form.
*/
public static function submitForm(array &$element, FormStateInterface $form_state) {
/** @var \Drupal\profile\Entity\ProfileInterface $element_profile */
$element_profile = $form_state->getValue($element['#parents']);

if ($element['#element_mode'] != 'view' && $form_state->isSubmitted()) {
$form_display = EntityFormDisplay::collectRenderDisplay($element_profile, 'default');
$form_display->extractFormValues($element_profile, $element, $form_state);
$element_profile->save();
if ($element_profile->isNew()) {
$element_profile->save();
}

$element['#default_value'] = $element_profile;
$element['#value'] = $element_profile->id();
}

$form_state->setValueForElement($element, $element_profile);
Expand All @@ -289,8 +342,30 @@ public static function ajaxRefresh(array &$form, FormStateInterface $form_state)
*/
public static function ajaxSubmit(array &$form, FormStateInterface $form_state) {
$triggering_element = $form_state->getTriggeringElement();
$form_state->set('element_mode', $triggering_element['#element_mode']);
$parents = implode('-', $triggering_element['#parents']);
$element_mode_name = 'element_mode-' . $parents;

$form_state->set($element_mode_name, $triggering_element['#element_mode']);
$form_state->setRebuild();
}

/**
* Check if the address arrays are equal or not. In the equality comparition,
* empty string is regarded as the same with NULL.
*
* @param $address1
* @param $address2
* @return bool
*/
public static function addressEquals($address1, $address2) {
$replace_empty_callable = function (&$value) {
if (empty($value)) {
$value = NULL;
}
};

array_walk($address1, $replace_empty_callable);
array_walk($address2, $replace_empty_callable);
return $address1 == $address2;
}
}
Expand Up @@ -7,3 +7,13 @@ commerce_order_test.profile_select_form:
_access: 'TRUE'
options:
no_cache: TRUE
commerce_order_test.multiple_profile_select_form:
path: '/commerce_order_test/multiple_profile_select_form'
defaults:
_form: '\Drupal\commerce_order_test\Form\MultipleProfileSelectTestForm'
_title: 'Multiple profile select test form'
requirements:
_access: 'TRUE'
options:
no_cache: TRUE

@@ -0,0 +1,52 @@
<?php

namespace Drupal\commerce_order_test\Form;


use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class MultipleProfileSelectTestForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'multiple_commerce_profile_select_element_test_form';
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['profile1'] = [
'#type' => 'commerce_profile_select',
'#default_value' => NULL,
'#profile_type' => 'customer',
'#owner_uid' => \Drupal::currentUser()->id(),
'#available_countries' => ['TW', 'HU', 'FR', 'US', 'RS', 'DE'],
];
$form['profile2'] = [
'#type' => 'commerce_profile_select',
'#default_value' => NULL,
'#profile_type' => 'customer',
'#owner_uid' => \Drupal::currentUser()->id(),
'#available_countries' => ['TW', 'HU', 'FR', 'US', 'RS', 'DE'],
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];

return $form;
}

/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$profile1 = $form_state->getValue('profile1');
$profile2 = $form_state->getValue('profile2');
drupal_set_message($this->t('Profile1 selected: :label', [':label' => $profile1->label()]));
drupal_set_message($this->t('Profile2 selected: :label', [':label' => $profile2->label()]));
}
}
Expand Up @@ -20,7 +20,6 @@ public function getFormId() {
public function buildForm(array $form, FormStateInterface $form_state) {
$form['profile'] = [
'#type' => 'commerce_profile_select',
'#title' => $this->t('Profile'),
'#default_value' => NULL,
'#profile_type' => 'customer',
'#owner_uid' => \Drupal::currentUser()->id(),
Expand Down

0 comments on commit 57c1117

Please sign in to comment.