Skip to content

Commit 6736c38

Browse files
goldorakbojanz
goldorak
authored andcommitted
Issue #2842924 by mglaman, bojanz, jkuma, niko-: Add a product condition
1 parent e333424 commit 6736c38

File tree

3 files changed

+191
-0
lines changed

3 files changed

+191
-0
lines changed

modules/product/config/schema/commerce_product.schema.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
commerce.commerce_condition.plugin.order_item_product:
2+
type: commerce_condition_configuration
3+
mapping:
4+
products:
5+
type: sequence
6+
label: 'Products'
7+
sequence:
8+
type: mapping
9+
mapping:
10+
product_id:
11+
type: integer
12+
113
commerce_product.commerce_product_type.*:
214
type: commerce_config_entity_bundle
315
label: 'Product type'
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
namespace Drupal\commerce_product\Plugin\Commerce\Condition;
4+
5+
use Drupal\commerce\Plugin\Commerce\Condition\ConditionBase;
6+
use Drupal\Core\Entity\EntityInterface;
7+
use Drupal\Core\Entity\EntityTypeManagerInterface;
8+
use Drupal\Core\Form\FormStateInterface;
9+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
10+
use Symfony\Component\DependencyInjection\ContainerInterface;
11+
12+
/**
13+
* Provides the product condition for order items.
14+
*
15+
* @CommerceCondition(
16+
* id = "order_item_product",
17+
* label = @Translation("Product"),
18+
* display_label = @Translation("Limit by product"),
19+
* category = @Translation("Product"),
20+
* entity_type = "commerce_order_item",
21+
* )
22+
*/
23+
class OrderItemProduct extends ConditionBase implements ContainerFactoryPluginInterface {
24+
25+
/**
26+
* The product storage.
27+
*
28+
* @var \Drupal\Core\Entity\EntityStorageInterface
29+
*/
30+
protected $productStorage;
31+
32+
/**
33+
* Constructs a new OrderItemProduct object.
34+
*
35+
* @param array $configuration
36+
* The plugin configuration, i.e. an array with configuration values keyed
37+
* by configuration option name.
38+
* @param string $plugin_id
39+
* The plugin_id for the plugin instance.
40+
* @param mixed $plugin_definition
41+
* The plugin implementation definition.
42+
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
43+
* The entity type manager.
44+
*/
45+
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
46+
parent::__construct($configuration, $plugin_id, $plugin_definition);
47+
48+
$this->productStorage = $entity_type_manager->getStorage('commerce_product');
49+
}
50+
51+
/**
52+
* {@inheritdoc}
53+
*/
54+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
55+
return new static(
56+
$configuration,
57+
$plugin_id,
58+
$plugin_definition,
59+
$container->get('entity_type.manager')
60+
);
61+
}
62+
63+
/**
64+
* {@inheritdoc}
65+
*/
66+
public function defaultConfiguration() {
67+
return [
68+
'products' => [],
69+
] + parent::defaultConfiguration();
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
76+
$form = parent::buildConfigurationForm($form, $form_state);
77+
78+
$products = [];
79+
$product_ids = array_column($this->configuration['products'], 'product_id');
80+
if (!empty($product_ids)) {
81+
$products = $this->productStorage->loadMultiple($product_ids);
82+
}
83+
$form['products'] = [
84+
'#type' => 'entity_autocomplete',
85+
'#title' => $this->t('Products'),
86+
'#default_value' => $products,
87+
'#target_type' => 'commerce_product',
88+
'#tags' => TRUE,
89+
'#required' => TRUE,
90+
];
91+
92+
return $form;
93+
}
94+
95+
/**
96+
* {@inheritdoc}
97+
*/
98+
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
99+
parent::submitConfigurationForm($form, $form_state);
100+
101+
$values = $form_state->getValue($form['#parents']);
102+
$this->configuration['products'] = [];
103+
foreach ($values['products'] as $value) {
104+
$this->configuration['products'][] = [
105+
'product_id' => $value['target_id'],
106+
];
107+
}
108+
}
109+
110+
/**
111+
* {@inheritdoc}
112+
*/
113+
public function evaluate(EntityInterface $entity) {
114+
$this->assertEntity($entity);
115+
/** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
116+
$order_item = $entity;
117+
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface $purchasable_entity */
118+
$purchasable_entity = $order_item->getPurchasedEntity();
119+
if (!$purchasable_entity || $purchasable_entity->getEntityTypeId() != 'commerce_product_variation') {
120+
return FALSE;
121+
}
122+
$product_ids = array_column($this->configuration['products'], 'product_id');
123+
124+
return in_array($purchasable_entity->getProductId(), $product_ids);
125+
}
126+
127+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Drupal\Tests\commerce_product\Unit\Plugin\Commerce\Condition;
4+
5+
use Drupal\commerce_order\Entity\OrderItemInterface;
6+
use Drupal\commerce_product\Entity\ProductVariationInterface;
7+
use Drupal\commerce_product\Plugin\Commerce\Condition\OrderItemProduct;
8+
use Drupal\Core\Entity\EntityTypeManagerInterface;
9+
use Drupal\Tests\UnitTestCase;
10+
11+
/**
12+
* @coversDefaultClass \Drupal\commerce_product\Plugin\Commerce\Condition\OrderItemProduct
13+
* @group commerce
14+
*/
15+
class OrderItemProductTest extends UnitTestCase {
16+
17+
/**
18+
* ::covers evaluate.
19+
*/
20+
public function testEvaluate() {
21+
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
22+
$entity_type_manager = $entity_type_manager->reveal();
23+
$configuration = [];
24+
$configuration['products'] = [
25+
['product_id' => 1],
26+
];
27+
$condition = new OrderItemProduct($configuration, 'order_item_product', ['entity_type' => 'commerce_order_item'], $entity_type_manager);
28+
29+
// Order item with no purchasable entity.
30+
$order_item = $this->prophesize(OrderItemInterface::class);
31+
$order_item->getEntityTypeId()->willReturn('commerce_order_item');
32+
$order_item->getPurchasedEntity()->willReturn(NULL);
33+
$order_item = $order_item->reveal();
34+
$this->assertFalse($condition->evaluate($order_item));
35+
36+
// Order item with a variation belong to product #2.
37+
$purchased_entity = $this->prophesize(ProductVariationInterface::class);
38+
$purchased_entity->getEntityTypeId()->willReturn('commerce_product_variation');
39+
$purchased_entity->getProductId()->willReturn(2);
40+
$purchased_entity = $purchased_entity->reveal();
41+
$order_item = $this->prophesize(OrderItemInterface::class);
42+
$order_item->getEntityTypeId()->willReturn('commerce_order_item');
43+
$order_item->getPurchasedEntity()->willReturn($purchased_entity);
44+
$order_item = $order_item->reveal();
45+
$this->assertFalse($condition->evaluate($order_item));
46+
47+
$configuration['products'][0]['product_id'] = 2;
48+
$condition->setConfiguration($configuration);
49+
$this->assertTrue($condition->evaluate($order_item));
50+
}
51+
52+
}

0 commit comments

Comments
 (0)