Loading config/schema/commerce_shipping.schema.yml +11 −0 Original line number Diff line number Diff line Loading @@ -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: Loading src/EventSubscriber/FilterConditionsEventSubscriber.php +2 −2 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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); } } Loading src/Plugin/Commerce/Condition/OrderShippingMethod.php 0 → 100644 +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); } } src/Plugin/Commerce/Condition/ShipmentQuantity.php +1 −1 Original line number Diff line number Diff line Loading @@ -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", * ) */ Loading tests/src/FunctionalJavascript/CheckoutPaneTest.php +70 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
config/schema/commerce_shipping.schema.yml +11 −0 Original line number Diff line number Diff line Loading @@ -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: Loading
src/EventSubscriber/FilterConditionsEventSubscriber.php +2 −2 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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); } } Loading
src/Plugin/Commerce/Condition/OrderShippingMethod.php 0 → 100644 +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); } }
src/Plugin/Commerce/Condition/ShipmentQuantity.php +1 −1 Original line number Diff line number Diff line Loading @@ -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", * ) */ Loading
tests/src/FunctionalJavascript/CheckoutPaneTest.php +70 −1 Original line number Diff line number Diff line Loading @@ -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