Loading src/Plugin/Commerce/CheckoutPane/PickupCapableShippingInformation.php +104 −8 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ namespace Drupal\commerce_packeta\Plugin\Commerce\CheckoutPane; use Drupal\commerce\InlineFormManager; use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\commerce_shipping\OrderShipmentSummaryInterface; use Drupal\commerce_shipping\PackerManagerInterface; use Drupal\commerce_shipping\Plugin\Commerce\CheckoutPane\ShippingInformation; Loading Loading @@ -65,10 +66,6 @@ class PickupCapableShippingInformation extends ShippingInformation { * {@inheritdoc} */ public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) { $pane_form = parent::buildPaneForm($pane_form, $form_state, $complete_form); unset($pane_form['recalculate_shipping']); $store = $this->order->getStore(); $available_countries = []; foreach ($store->get('shipping_countries') as $country_item) { Loading @@ -95,20 +92,101 @@ class PickupCapableShippingInformation extends ShippingInformation { 'shipping_method' => $shipping_method, ], $this->getShippingProfilePickup(TRUE)); } // Prepare the form for ajax. // Not using Html::getUniqueId() on the wrapper ID to avoid #2675688. $pane_form['#wrapper_id'] = 'shipping-information-wrapper'; $pane_form['#prefix'] = '<div id="' . $pane_form['#wrapper_id'] . '">'; $pane_form['#suffix'] = '</div>'; // Auto recalculation is enabled only when a shipping profile is required. $pane_form['#auto_recalculate'] = !empty($this->configuration['auto_recalculate']) && !empty($this->configuration['require_shipping_profile']); $pane_form['#after_build'][] = [static::class, 'autoRecalculateProcess']; $pane_form['shipping_profile'] = [ '#parents' => array_merge($pane_form['#parents'], ['shipping_profile']), '#inline_form' => $inline_form, ]; $pane_form['shipping_profile'] = $inline_form->buildInlineForm($pane_form['shipping_profile'], $form_state); // The shipping_profile should always exist in form state if (!$form_state->has('shipping_profile')) { $triggering_element = $form_state->getTriggeringElement(); // The shipping_profile should always exist in form state (and not just // after "Recalculate shipping" is clicked). if (!$form_state->has('shipping_profile') || // For some reason, when the address selected is changed, the shipping // profile in form state is stale. (isset($triggering_element['#parents']) && in_array('select_address', $triggering_element['#parents'], TRUE))) { $form_state->set('shipping_profile', $inline_form->getEntity()); } // Pickup custom: place at top. $pane_form['shipments']['#weight'] = -999; $class = get_class($this); // Ensure selecting a different address refreshes the entire form. if (isset($pane_form['shipping_profile']['select_address'])) { $pane_form['shipping_profile']['select_address']['#ajax'] = [ 'callback' => [$class, 'ajaxRefreshForm'], 'element' => $pane_form['#parents'], ]; // Selecting a different address should trigger a recalculation. $pane_form['shipping_profile']['select_address']['#recalculate'] = TRUE; } $pane_form['recalculate_shipping'] = [ '#type' => 'button', '#value' => $this->t('Recalculate shipping'), '#recalculate' => TRUE, '#ajax' => [ 'callback' => [$class, 'ajaxRefreshForm'], 'element' => $pane_form['#parents'], ], // The calculation process only needs a valid shipping profile. '#limit_validation_errors' => [ array_merge($pane_form['#parents'], ['shipping_profile']), ], '#after_build' => [ [static::class, 'clearValues'], ], ]; $pane_form['removed_shipments'] = [ '#type' => 'value', '#value' => [], ]; $pane_form['shipments'] = [ '#type' => 'container', ]; $shipping_profile = $form_state->get('shipping_profile'); $shipments = $this->order->get('shipments')->referencedEntities(); $recalculate_shipping = $form_state->get('recalculate_shipping'); $can_calculate_rates = $this->canCalculateRates($shipping_profile); // If the shipping recalculation is triggered, ensure the rates can // be recalculated (i.e a valid address is entered). if ($recalculate_shipping && !$can_calculate_rates) { $recalculate_shipping = FALSE; $shipments = []; } // Ensure the profile is saved with the latest address, it's necessary // to do that in case the profile isn't new, otherwise the shipping profile // referenced by the shipment won't reflect the updated address. if (!$shipping_profile->isNew() && $shipping_profile->hasTranslationChanges() && $can_calculate_rates) { $shipping_profile->save(); $inline_form->setEntity($shipping_profile); } $force_packing = empty($shipments) && $can_calculate_rates; if ($recalculate_shipping || $force_packing) { // We're still relying on the packer manager for packing the order since // we don't want the shipments to be saved for performance reasons. // The shipments are saved on pane submission. [$shipments, $removed_shipments] = $this->packerManager->packToShipments($this->order, $shipping_profile, $shipments); // Store the IDs of removed shipments for submitPaneForm(). $pane_form['removed_shipments']['#value'] = array_map(function ($shipment) { /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */ return $shipment->id(); }, $removed_shipments); } $single_shipment = count($shipments) === 1; foreach ($shipments as $index => $shipment) { Loading Loading @@ -136,6 +214,24 @@ class PickupCapableShippingInformation extends ShippingInformation { ]; } // Update the shipments and save the order if no rate was explicitly // selected, that usually occurs when changing addresses, this will ensure // the default rate is selected/applied. if (!$this->hasRateSelected($pane_form, $form_state) && ($recalculate_shipping || $force_packing)) { array_map(function (ShipmentInterface $shipment) { if (!$shipment->isNew()) { $shipment->save(); } }, $shipments); $this->order->set('shipments', $shipments); $this->order->save(); } // Pickup custom: place at top. $pane_form['shipments']['#weight'] = -999; unset($pane_form['recalculate_shipping']); return $pane_form; } Loading src/ProfileFieldCopyWithoutPickup.php +5 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,11 @@ final class ProfileFieldCopyWithoutPickup extends ProfileFieldCopy { $order = self::getOrder($form_state); $form = $form_state->getCompleteForm()['packeta_capable_shipping_information']; if (!$form) { parent::submitForm($inline_form, $form_state); return; } if (PickupCapableShippingInformation::isPickupSelected($form, $form_state, $order)) { $form_state->setError($inline_form, t('Can not use "Billing same as shipping while choosing this shipping method"')); } Loading Loading
src/Plugin/Commerce/CheckoutPane/PickupCapableShippingInformation.php +104 −8 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ namespace Drupal\commerce_packeta\Plugin\Commerce\CheckoutPane; use Drupal\commerce\InlineFormManager; use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\commerce_shipping\OrderShipmentSummaryInterface; use Drupal\commerce_shipping\PackerManagerInterface; use Drupal\commerce_shipping\Plugin\Commerce\CheckoutPane\ShippingInformation; Loading Loading @@ -65,10 +66,6 @@ class PickupCapableShippingInformation extends ShippingInformation { * {@inheritdoc} */ public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) { $pane_form = parent::buildPaneForm($pane_form, $form_state, $complete_form); unset($pane_form['recalculate_shipping']); $store = $this->order->getStore(); $available_countries = []; foreach ($store->get('shipping_countries') as $country_item) { Loading @@ -95,20 +92,101 @@ class PickupCapableShippingInformation extends ShippingInformation { 'shipping_method' => $shipping_method, ], $this->getShippingProfilePickup(TRUE)); } // Prepare the form for ajax. // Not using Html::getUniqueId() on the wrapper ID to avoid #2675688. $pane_form['#wrapper_id'] = 'shipping-information-wrapper'; $pane_form['#prefix'] = '<div id="' . $pane_form['#wrapper_id'] . '">'; $pane_form['#suffix'] = '</div>'; // Auto recalculation is enabled only when a shipping profile is required. $pane_form['#auto_recalculate'] = !empty($this->configuration['auto_recalculate']) && !empty($this->configuration['require_shipping_profile']); $pane_form['#after_build'][] = [static::class, 'autoRecalculateProcess']; $pane_form['shipping_profile'] = [ '#parents' => array_merge($pane_form['#parents'], ['shipping_profile']), '#inline_form' => $inline_form, ]; $pane_form['shipping_profile'] = $inline_form->buildInlineForm($pane_form['shipping_profile'], $form_state); // The shipping_profile should always exist in form state if (!$form_state->has('shipping_profile')) { $triggering_element = $form_state->getTriggeringElement(); // The shipping_profile should always exist in form state (and not just // after "Recalculate shipping" is clicked). if (!$form_state->has('shipping_profile') || // For some reason, when the address selected is changed, the shipping // profile in form state is stale. (isset($triggering_element['#parents']) && in_array('select_address', $triggering_element['#parents'], TRUE))) { $form_state->set('shipping_profile', $inline_form->getEntity()); } // Pickup custom: place at top. $pane_form['shipments']['#weight'] = -999; $class = get_class($this); // Ensure selecting a different address refreshes the entire form. if (isset($pane_form['shipping_profile']['select_address'])) { $pane_form['shipping_profile']['select_address']['#ajax'] = [ 'callback' => [$class, 'ajaxRefreshForm'], 'element' => $pane_form['#parents'], ]; // Selecting a different address should trigger a recalculation. $pane_form['shipping_profile']['select_address']['#recalculate'] = TRUE; } $pane_form['recalculate_shipping'] = [ '#type' => 'button', '#value' => $this->t('Recalculate shipping'), '#recalculate' => TRUE, '#ajax' => [ 'callback' => [$class, 'ajaxRefreshForm'], 'element' => $pane_form['#parents'], ], // The calculation process only needs a valid shipping profile. '#limit_validation_errors' => [ array_merge($pane_form['#parents'], ['shipping_profile']), ], '#after_build' => [ [static::class, 'clearValues'], ], ]; $pane_form['removed_shipments'] = [ '#type' => 'value', '#value' => [], ]; $pane_form['shipments'] = [ '#type' => 'container', ]; $shipping_profile = $form_state->get('shipping_profile'); $shipments = $this->order->get('shipments')->referencedEntities(); $recalculate_shipping = $form_state->get('recalculate_shipping'); $can_calculate_rates = $this->canCalculateRates($shipping_profile); // If the shipping recalculation is triggered, ensure the rates can // be recalculated (i.e a valid address is entered). if ($recalculate_shipping && !$can_calculate_rates) { $recalculate_shipping = FALSE; $shipments = []; } // Ensure the profile is saved with the latest address, it's necessary // to do that in case the profile isn't new, otherwise the shipping profile // referenced by the shipment won't reflect the updated address. if (!$shipping_profile->isNew() && $shipping_profile->hasTranslationChanges() && $can_calculate_rates) { $shipping_profile->save(); $inline_form->setEntity($shipping_profile); } $force_packing = empty($shipments) && $can_calculate_rates; if ($recalculate_shipping || $force_packing) { // We're still relying on the packer manager for packing the order since // we don't want the shipments to be saved for performance reasons. // The shipments are saved on pane submission. [$shipments, $removed_shipments] = $this->packerManager->packToShipments($this->order, $shipping_profile, $shipments); // Store the IDs of removed shipments for submitPaneForm(). $pane_form['removed_shipments']['#value'] = array_map(function ($shipment) { /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */ return $shipment->id(); }, $removed_shipments); } $single_shipment = count($shipments) === 1; foreach ($shipments as $index => $shipment) { Loading Loading @@ -136,6 +214,24 @@ class PickupCapableShippingInformation extends ShippingInformation { ]; } // Update the shipments and save the order if no rate was explicitly // selected, that usually occurs when changing addresses, this will ensure // the default rate is selected/applied. if (!$this->hasRateSelected($pane_form, $form_state) && ($recalculate_shipping || $force_packing)) { array_map(function (ShipmentInterface $shipment) { if (!$shipment->isNew()) { $shipment->save(); } }, $shipments); $this->order->set('shipments', $shipments); $this->order->save(); } // Pickup custom: place at top. $pane_form['shipments']['#weight'] = -999; unset($pane_form['recalculate_shipping']); return $pane_form; } Loading
src/ProfileFieldCopyWithoutPickup.php +5 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,11 @@ final class ProfileFieldCopyWithoutPickup extends ProfileFieldCopy { $order = self::getOrder($form_state); $form = $form_state->getCompleteForm()['packeta_capable_shipping_information']; if (!$form) { parent::submitForm($inline_form, $form_state); return; } if (PickupCapableShippingInformation::isPickupSelected($form, $form_state, $order)) { $form_state->setError($inline_form, t('Can not use "Billing same as shipping while choosing this shipping method"')); } Loading