View source
<?php
namespace Drupal\commerce_shipping;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Form\BaseFormIdInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\profile\Entity\ProfileInterface;
class ProfileFieldCopy implements ProfileFieldCopyInterface {
use StringTranslationTrait;
protected $currentUser;
public function __construct(AccountInterface $current_user) {
$this->currentUser = $current_user;
}
public function supportsForm(array &$inline_form, FormStateInterface $form_state) {
if (!isset($inline_form['#profile_scope']) || $inline_form['#profile_scope'] != 'billing') {
return FALSE;
}
$order = static::getOrder($form_state);
if (!$order) {
return FALSE;
}
if (!$order
->hasField('shipments')) {
return FALSE;
}
return TRUE;
}
public function alterForm(array &$inline_form, FormStateInterface $form_state) {
$shipping_profile = static::getShippingProfile($form_state);
if (!$shipping_profile) {
return;
}
$billing_profile = static::getBillingProfile($inline_form);
$shipping_form_display = static::getFormDisplay($shipping_profile, 'shipping');
$shipping_fields = array_keys($shipping_form_display
->getComponents());
$user_input = (array) NestedArray::getValue($form_state
->getUserInput(), $inline_form['#parents']);
$enabled = $billing_profile
->getData('copy_fields', $billing_profile
->isNew());
if ($user_input) {
if (isset($user_input['copy_fields'])) {
$enabled = (bool) $user_input['copy_fields']['enable'];
}
elseif (isset($user_input['select_address'])) {
$enabled = FALSE;
}
}
$inline_form['copy_fields'] = [
'#parents' => array_merge($inline_form['#parents'], [
'copy_fields',
]),
'#type' => 'container',
'#weight' => -1000,
'#shipping_fields' => $shipping_fields,
'#has_form' => FALSE,
];
$inline_form['copy_fields']['enable'] = [
'#type' => 'checkbox',
'#title' => $this
->getCopyLabel($inline_form),
'#default_value' => $enabled,
'#ajax' => [
'callback' => [
get_class($this),
'ajaxRefresh',
],
'wrapper' => $inline_form['#id'],
],
];
if ($enabled) {
$billing_profile
->populateFromProfile($shipping_profile, $shipping_fields);
$inline_form['copy_to_address_book'] = [
'#type' => 'value',
'#value' => FALSE,
];
foreach (Element::getVisibleChildren($inline_form) as $key) {
if (!in_array($key, [
'copy_fields',
'copy_to_address_book',
])) {
$inline_form[$key]['#access'] = FALSE;
}
}
$form_display = static::getFormDisplay($billing_profile, 'billing', $shipping_fields);
$billing_fields = array_keys($form_display
->getComponents());
if ($billing_fields) {
$form_display
->buildForm($billing_profile, $inline_form['copy_fields'], $form_state);
$inline_form['copy_fields']['#has_form'] = TRUE;
}
foreach ($inline_form['#element_validate'] as &$validate_handler) {
if ($validate_handler[1] == 'runValidate') {
$validate_handler = [
get_class($this),
'validateForm',
];
break;
}
}
foreach ($inline_form['#commerce_element_submit'] as &$submit_handler) {
if ($submit_handler[1] == 'runSubmit') {
$submit_handler = [
get_class($this),
'submitForm',
];
break;
}
}
}
else {
$billing_profile
->unsetData('copy_fields');
}
}
protected function getCopyLabel(array $inline_form) {
$plugin = $inline_form['#inline_form'];
$configuration = $plugin
->getConfiguration();
$is_owner = FALSE;
if (empty($configuration['admin'])) {
$is_owner = $this->currentUser
->id() == $configuration['address_book_uid'];
}
if ($is_owner) {
$copy_label = $this
->t('My billing information is the same as my shipping information.');
}
else {
$copy_label = $this
->t('Billing information is the same as the shipping information.');
}
return $copy_label;
}
public static function ajaxRefresh(array &$form, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
$inline_form = NestedArray::getValue($form, array_slice($triggering_element['#array_parents'], 0, -2));
return $inline_form;
}
public static function validateForm(array &$inline_form, FormStateInterface $form_state) {
$shipping_fields = $inline_form['copy_fields']['#shipping_fields'];
if ($inline_form['copy_fields']['#has_form']) {
$billing_profile = static::getBillingProfile($inline_form);
$form_display = static::getFormDisplay($billing_profile, 'billing', $shipping_fields);
$form_display
->extractFormValues($billing_profile, $inline_form['copy_fields'], $form_state);
$form_display
->validateFormValues($billing_profile, $inline_form['copy_fields'], $form_state);
}
}
public static function submitForm(array &$inline_form, FormStateInterface $form_state) {
$shipping_fields = $inline_form['copy_fields']['#shipping_fields'];
$shipping_profile = static::getShippingProfile($form_state);
$billing_profile = static::getBillingProfile($inline_form);
$billing_profile
->populateFromProfile($shipping_profile, $shipping_fields);
if ($inline_form['copy_fields']['#has_form']) {
$form_display = static::getFormDisplay($billing_profile, 'billing', $shipping_fields);
$form_display
->extractFormValues($billing_profile, $inline_form['copy_fields'], $form_state);
}
$billing_profile
->setData('copy_fields', TRUE);
$billing_profile
->unsetData('copy_to_address_book');
$address_book_profile_id = $shipping_profile
->getData('address_book_profile_id');
if ($address_book_profile_id && $shipping_profile
->bundle() == $billing_profile
->bundle()) {
$billing_profile
->setData('address_book_profile_id', $address_book_profile_id);
}
$billing_profile
->save();
}
protected static function getBillingProfile(array &$inline_form) {
$plugin = $inline_form['#inline_form'];
$profile = $plugin
->getEntity();
assert($profile instanceof ProfileInterface);
return $profile;
}
protected static function getShippingProfile(FormStateInterface $form_state) {
if ($form_state
->has('shipping_profile')) {
$shipping_profile = $form_state
->get('shipping_profile');
}
else {
$order = static::getOrder($form_state);
$profiles = $order
->collectProfiles();
$shipping_profile = $profiles['shipping'] ?? NULL;
}
return $shipping_profile;
}
protected static function getOrder(FormStateInterface $form_state) {
$form_object = $form_state
->getFormObject();
if (!$form_object instanceof BaseFormIdInterface) {
return NULL;
}
$order = NULL;
if ($form_object instanceof EntityFormInterface) {
$entity = $form_object
->getEntity();
if ($entity
->getEntityTypeId() == 'commerce_order') {
$order = $entity;
}
}
elseif ($form_object
->getBaseFormId() == 'commerce_checkout_flow') {
$order = $form_object
->getOrder();
}
return $order;
}
protected static function getFormDisplay(ProfileInterface $profile, $form_mode, array $remove_fields = []) {
$form_display = EntityFormDisplay::collectRenderDisplay($profile, $form_mode);
$form_display
->removeComponent('revision_log_message');
foreach ($form_display
->getComponents() as $name => $component) {
if (in_array($name, $remove_fields)) {
$form_display
->removeComponent($name);
}
}
return $form_display;
}
}