Commit 4f691115 authored by Jonathan Sacksick's avatar Jonathan Sacksick Committed by Jonathan Sacksick
Browse files

Issue #2976252 by Primsi, jsacksick, martin_klima, mhawwari, dwkitchen, ekes,...

Issue #2976252 by Primsi, jsacksick, martin_klima, mhawwari, dwkitchen, ekes, mellowtothemax, mirom, parisek, mglaman, Berdir, oneICT: Provide a shipping method condition for orders.
parent 86f9ebf6
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -5,6 +5,17 @@ commerce.commerce_condition.plugin.shipment_address:
      type: address_zone
      label: 'Zone'

commerce.commerce_condition.plugin.order_shipping_method:
  type: commerce_condition_configuration
  mapping:
    shipping_methods:
      type: sequence
      label: 'Shipping methods'
      orderby: value
      sequence:
        type: string
        label: 'Shipping method'

commerce.commerce_condition.plugin.shipment_quantity:
  type: commerce_condition_configuration
  mapping:
+2 −2
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ class FilterConditionsEventSubscriber implements EventSubscriberInterface {
  }

  /**
   * Removes the order shipping address condition on shipping method form.
   * Removes unnecessary shipping conditions on shipping method form.
   *
   * @param \Drupal\commerce\Event\FilterConditionsEvent $event
   *   The event.
@@ -28,7 +28,7 @@ class FilterConditionsEventSubscriber implements EventSubscriberInterface {
  public function onFilterConditions(FilterConditionsEvent $event) {
    if ($event->getParentEntityTypeId() === 'commerce_shipping_method') {
      $definitions = $event->getDefinitions();
      unset($definitions['order_shipping_address']);
      unset($definitions['order_shipping_address'], $definitions['order_shipping_method']);
      $event->setDefinitions($definitions);
    }
  }
+105 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\commerce_shipping\Plugin\Commerce\Condition;

use Drupal\commerce\Plugin\Commerce\Condition\ConditionBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides the shipping method condition for orders.
 *
 * @CommerceCondition(
 *   id = "order_shipping_method",
 *   label = @Translation("Shipping method"),
 *   display_label = @Translation("Shipping method"),
 *   category = @Translation("Shipment"),
 *   entity_type = "commerce_order",
 * )
 */
class OrderShippingMethod extends ConditionBase implements ContainerFactoryPluginInterface {

  /**
   * The entity UUID mapper.
   *
   * @var \Drupal\commerce\EntityUuidMapperInterface
   */
  protected $entityUuidMapper;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static($configuration, $plugin_id, $plugin_definition);
    $instance->entityUuidMapper = $container->get('commerce.entity_uuid_mapper');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      // The shipping method UUIDS.
      'shipping_methods' => [],
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildConfigurationForm($form, $form_state);

    // Map the UUIDs back to IDs for the form element.
    $shipping_method_ids = $this->entityUuidMapper->mapToIds('commerce_shipping_method', $this->configuration['shipping_methods']);
    $form['shipping_methods'] = [
      '#type' => 'commerce_entity_select',
      '#title' => $this->t('Shipping methods'),
      '#default_value' => $shipping_method_ids,
      '#target_type' => 'commerce_shipping_method',
      '#hide_single_entity' => FALSE,
      '#multiple' => TRUE,
      '#required' => TRUE,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);

    $values = $form_state->getValue($form['#parents']);
    $this->configuration['shipping_methods'] = $this->entityUuidMapper->mapFromIds('commerce_shipping_method', $values['shipping_methods']);
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate(EntityInterface $entity) {
    $this->assertEntity($entity);
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $entity;
    if (!$order->hasField('shipments') ||
      $order->get('shipments')->isEmpty()) {
      // The shipping method is not known yet, the condition cannot pass.
      return FALSE;
    }
    /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface[] $shipments */
    $shipments = $order->get('shipments')->referencedEntities();
    $shipment = reset($shipments);
    $shipping_method = $shipment->getShippingMethod();

    if (!$shipping_method) {
      return FALSE;
    }

    return in_array($shipping_method->uuid(), $this->configuration['shipping_methods'], TRUE);
  }

}
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ use Drupal\Core\Form\FormStateInterface;
 * @CommerceCondition(
 *   id = "shipment_quantity",
 *   label = @Translation("Shipment quantity"),
 *   category = @Translation("Shipping"),
 *   category = @Translation("Shipment"),
 *   entity_type = "commerce_shipment",
 * )
 */
+70 −1
Original line number Diff line number Diff line
@@ -1029,11 +1029,80 @@ class CheckoutPaneTest extends CommerceWebDriverTestBase {
    $this->assertSession()->elementTextContains('xpath', $selector, 'VAT $1.60');
  }

  /**
   * Tests the payment gateway filtering by shipping method.
   */
  public function testPaymentGatewayCondition() {
    $checkout_flow = CheckoutFlow::load('shipping');
    $checkout_flow_configuration = $checkout_flow->get('configuration');
    $checkout_flow_configuration['panes']['payment_information'] = [
      'step' => 'review',
      'weight' => 3,
    ];
    $checkout_flow->set('configuration', $checkout_flow_configuration);
    $checkout_flow->save();

    $payment_gateway = PaymentGateway::create([
      'id' => 'cash_on_delivery',
      'label' => 'Manual',
      'plugin' => 'manual',
      'configuration' => [
        'display_label' => 'Cash on delivery',
        'instructions' => [
          'value' => 'Sample payment instructions.',
          'format' => 'plain_text',
        ],
      ],
      'conditions' => [
        [
          'plugin' => 'order_shipping_method',
          'configuration' => [
            'shipping_methods' => [$this->secondShippingMethod->uuid()],
          ],
        ],
      ],
      'weight' => 10,
    ]);
    $payment_gateway->save();

    $this->drupalGet($this->firstProduct->toUrl()->toString());
    $this->submitForm([], 'Add to cart');
    $this->drupalGet('checkout/1');
    $page = $this->getSession()->getPage();

    $address = [
      'given_name' => 'John',
      'family_name' => 'Smith',
      'address_line1' => 'Hauptstrasse 38',
      'locality' => 'Berlin',
      'postal_code' => '75002',
    ];

    $address_prefix = 'shipping_information[shipping_profile][address][0][address]';
    $page->fillField($address_prefix . '[country_code]', 'DE');
    $this->assertSession()->assertWaitOnAjaxRequest();
    foreach ($address as $property => $value) {
      $page->fillField($address_prefix . '[' . $property . ']', $value);
    }
    $page->findButton('Recalculate shipping')->click();
    $this->assertSession()->assertWaitOnAjaxRequest();
    $page->selectFieldOption('shipping_information[shipments][0][shipping_method][0]', '2--default');
    $this->submitForm([], 'Continue to review');

    $this->assertSession()->pageTextContains('Credit card');
    $this->assertSession()->pageTextContains('Cash on delivery');

    $this->clickLink('Go back');
    $page->selectFieldOption('shipping_information[shipments][0][shipping_method][0]', '1--default');
    $this->assertSession()->pageTextNotContains('Cash on delivery');
    $this->submitForm([], 'Continue to review');
  }

  /**
   * Tests that the shipping method doesn't change.
   */
  public function testSelectedShippingMethodPersists() {
    $default_profile = $this->createEntity('profile', [
    $this->createEntity('profile', [
      'type' => 'customer',
      'uid' => $this->adminUser->id(),
      'address' => $this->defaultAddress,
Loading