diff --git a/modules/order/src/Plugin/Commerce/Condition/OrderItemQuantity.php b/modules/order/src/Plugin/Commerce/Condition/OrderItemQuantity.php index a45c7ab53c..64d57825c7 100644 --- a/modules/order/src/Plugin/Commerce/Condition/OrderItemQuantity.php +++ b/modules/order/src/Plugin/Commerce/Condition/OrderItemQuantity.php @@ -3,6 +3,8 @@ namespace Drupal\commerce_order\Plugin\Commerce\Condition; use Drupal\commerce\Plugin\Commerce\Condition\ConditionBase; +use Drupal\commerce\Plugin\Commerce\Condition\ParentEntityAwareInterface; +use Drupal\commerce\Plugin\Commerce\Condition\ParentEntityAwareTrait; use Drupal\commerce_price\Calculator; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; @@ -18,9 +20,12 @@ * label = @Translation("Total product quantity"), * category = @Translation("Order"), * entity_type = "commerce_order", + * parent_entity_type = "commerce_promotion", * ) */ -class OrderItemQuantity extends ConditionBase { +class OrderItemQuantity extends ConditionBase implements ParentEntityAwareInterface { + + use ParentEntityAwareTrait; /** * {@inheritdoc} @@ -74,6 +79,9 @@ public function evaluate(EntityInterface $entity) { $this->assertEntity($entity); /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order = $entity; + /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */ + $promotion = $this->parentEntity; + $quantity = '0'; foreach ($order->getItems() as $order_item) { // @todo Filter by offer conditions here, once available. diff --git a/modules/order/tests/src/Unit/Plugin/Commerce/Condition/OrderItemQuantityTest.php b/modules/order/tests/src/Unit/Plugin/Commerce/Condition/OrderItemQuantityTest.php index 1e79777328..6b5654b17c 100644 --- a/modules/order/tests/src/Unit/Plugin/Commerce/Condition/OrderItemQuantityTest.php +++ b/modules/order/tests/src/Unit/Plugin/Commerce/Condition/OrderItemQuantityTest.php @@ -5,6 +5,7 @@ use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_order\Entity\OrderItemInterface; use Drupal\commerce_order\Plugin\Commerce\Condition\OrderItemQuantity; +use Drupal\commerce_promotion\Entity\PromotionInterface; use Drupal\Tests\UnitTestCase; /** @@ -19,10 +20,15 @@ class OrderItemQuantityTest extends UnitTestCase { * @dataProvider quantityProvider */ public function testEvaluate($operator, $quantity, $given_quantity, $result) { + $parent_entity = $this->prophesize(PromotionInterface::class); + $parent_entity = $parent_entity->reveal(); + $condition = new OrderItemQuantity([ 'operator' => $operator, 'quantity' => $quantity, ], 'order_item_quantity', ['entity_type' => 'commerce_order']); + $condition->setParentEntity($parent_entity); + $order_item = $this->prophesize(OrderItemInterface::class); $order_item->getEntityTypeId()->willReturn('commerce_order_item'); $order_item->getQuantity()->willReturn($given_quantity); diff --git a/modules/payment/src/Entity/PaymentGateway.php b/modules/payment/src/Entity/PaymentGateway.php index f93a1fbaae..fbb6c4e278 100644 --- a/modules/payment/src/Entity/PaymentGateway.php +++ b/modules/payment/src/Entity/PaymentGateway.php @@ -4,6 +4,7 @@ use Drupal\commerce\CommerceSinglePluginCollection; use Drupal\commerce\ConditionGroup; +use Drupal\commerce\Plugin\Commerce\Condition\ParentEntityAwareInterface; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\Core\Config\Entity\ConfigEntityBase; @@ -188,7 +189,11 @@ public function getConditions() { $plugin_manager = \Drupal::service('plugin.manager.commerce_condition'); $conditions = []; foreach ($this->conditions as $condition) { - $conditions[] = $plugin_manager->createInstance($condition['plugin'], $condition['configuration']); + $condition = $plugin_manager->createInstance($condition['plugin'], $condition['configuration']); + if ($condition instanceof ParentEntityAwareInterface) { + $condition->setParentEntity($this); + } + $conditions[] = $condition; } return $conditions; } diff --git a/modules/promotion/src/Entity/Promotion.php b/modules/promotion/src/Entity/Promotion.php index 4f8118eb53..f39849140d 100644 --- a/modules/promotion/src/Entity/Promotion.php +++ b/modules/promotion/src/Entity/Promotion.php @@ -5,6 +5,7 @@ use Drupal\commerce\ConditionGroup; use Drupal\commerce\Entity\CommerceContentEntityBase; use Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface; +use Drupal\commerce\Plugin\Commerce\Condition\ParentEntityAwareInterface; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderItemPromotionOfferInterface; use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\PromotionOfferInterface; @@ -193,7 +194,11 @@ public function getConditions() { $conditions = []; foreach ($this->get('conditions') as $field_item) { /** @var \Drupal\commerce\Plugin\Field\FieldType\PluginItemInterface $field_item */ - $conditions[] = $field_item->getTargetInstance(); + $condition = $field_item->getTargetInstance(); + if ($condition instanceof ParentEntityAwareInterface) { + $condition->setParentEntity($this); + } + $conditions[] = $condition; } return $conditions; } diff --git a/src/Annotation/CommerceCondition.php b/src/Annotation/CommerceCondition.php index 36bee82712..a497320ec9 100644 --- a/src/Annotation/CommerceCondition.php +++ b/src/Annotation/CommerceCondition.php @@ -60,6 +60,18 @@ class CommerceCondition extends Plugin { */ public $entity_type; + /** + * The parent entity type ID. + * + * This is the entity type ID of the entity that embeds the conditions. + * For example: 'commerce_promotion'. + * + * When specified, a condition will only be available on that entity type. + * + * @var string + */ + public $parent_entity_type; + /** * The condition weight. * diff --git a/src/ConditionManager.php b/src/ConditionManager.php index 5747e2ca5e..0cf938cc9f 100644 --- a/src/ConditionManager.php +++ b/src/ConditionManager.php @@ -82,10 +82,21 @@ public function processDefinition(&$definition, $plugin_id) { * {@inheritdoc} */ public function getFilteredDefinitions($parent_entity_type_id, array $entity_type_ids) { - $definitions = array_filter($this->getDefinitions(), function ($definition) use ($entity_type_ids) { - return in_array($definition['entity_type'], $entity_type_ids); - }); - // Certain conditions might be unavailable to the given parent entity type. + $definitions = $this->getDefinitions(); + foreach ($definitions as $plugin_id => $definition) { + // Filter by entity type. + if (!in_array($definition['entity_type'], $entity_type_ids)) { + unset($definitions[$plugin_id]); + continue; + } + // Filter by parent_entity_type, if specified by the plugin. + if (!empty($definition['parent_entity_type'])) { + if ($definition['parent_entity_type'] != $parent_entity_type_id) { + unset($definitions[$plugin_id]); + } + } + } + // Allow modules to filter the condition list. $event = new FilterConditionsEvent($definitions, $parent_entity_type_id); $this->eventDispatcher->dispatch(CommerceEvents::FILTER_CONDITIONS, $event); $definitions = $event->getDefinitions(); diff --git a/src/Plugin/Commerce/Condition/ParentEntityAwareInterface.php b/src/Plugin/Commerce/Condition/ParentEntityAwareInterface.php new file mode 100644 index 0000000000..74e7dfe40c --- /dev/null +++ b/src/Plugin/Commerce/Condition/ParentEntityAwareInterface.php @@ -0,0 +1,26 @@ +parentEntity = $parent_entity; + return $this; + } + +}