diff --git a/modules/product/src/Plugin/Commerce/PromotionCondition/ProductEquals.php b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductEquals.php new file mode 100644 index 0000000000..7a28d1cc40 --- /dev/null +++ b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductEquals.php @@ -0,0 +1,118 @@ +productStorage = $entity_type_manager->getStorage('commerce_product'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'product_id' => NULL, + ] + parent::defaultConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + $product = $this->productStorage->load($this->configuration['product_id']); + $form['product_id'] = [ + '#type' => 'entity_autocomplete', + '#title' => $this->t('Product'), + '#default_value' => $product, + '#target_type' => 'commerce_product', + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + $values = $form_state->getValue($form['#parents']); + $this->configuration['product_id'] = $values['product_id']; + parent::submitConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + $product_id = $this->configuration['product_id']; + if (empty($product_id)) { + return FALSE; + } + + /** @var \Drupal\commerce_product\Entity\ProductInterface $current_product */ + $current_product = $this->getTargetEntity()->getPurchasedEntity()->getProduct(); + + return $current_product->id() == $product_id; + } + + /** + * {@inheritdoc} + */ + public function summary() { + return $this->t('Compares the purchased product.'); + } + +} diff --git a/modules/product/src/Plugin/Commerce/PromotionCondition/ProductFieldEquals.php b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductFieldEquals.php new file mode 100644 index 0000000000..67cf3f5620 --- /dev/null +++ b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductFieldEquals.php @@ -0,0 +1,186 @@ + NULL, + 'field' => NULL, + ] + parent::defaultConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form += parent::buildConfigurationForm($form, $form_state); + $ajax_wrapper_id = Html::getUniqueId('ajax-wrapper'); + // Prefix and suffix used for Ajax replacement. + $form['#prefix'] = '
'; + $form['#suffix'] = '
'; + + $selected_bundle = isset($this->configuration['bundle']) ? $this->configuration['bundle'] : NULL; + $bundles = \Drupal::service("entity_type.bundle.info")->getBundleInfo('commerce_product'); + $bundle_options = []; + foreach ($bundles as $bundle => $label) { + $bundle_options[$bundle] = $label['label']; + } + + $form['bundle'] = [ + '#type' => 'select', + '#options' => $bundle_options, + '#title' => t('Product bundle'), + '#default_value' => $selected_bundle, + '#required' => TRUE, + '#ajax' => [ + 'callback' => [$this, 'bundleAjaxCallback'], + 'wrapper' => $ajax_wrapper_id, + ], + ]; + if (!$selected_bundle) { + return $form; + } + + $fields = \Drupal::service("entity_field.manager")->getFieldDefinitions('commerce_product', $selected_bundle); + $selected_field = isset($this->configuration['field']) ? $this->configuration['field'] : NULL; + + $filed_options = []; + foreach ($fields as $field_id => $field_definition) { + $filed_options[$field_id] = $field_definition->getLabel(); + } + + $form['field'] = [ + '#type' => 'select', + '#title' => t('Field'), + '#options' => $filed_options, + '#default_value' => $selected_field, + '#required' => TRUE, + '#ajax' => [ + 'callback' => [$this, 'bundleAjaxCallback'], + 'wrapper' => $ajax_wrapper_id, + ], + ]; + + if (!$selected_field) { + return $form; + } + + //Create an empty representative entity + $commerce_product = \Drupal::service('entity_type.manager')->getStorage('commerce_product')->create(array( + 'type' => $selected_bundle, + $selected_field => $this->configuration[$selected_field], + ) + ); + + //Get the EntityFormDisplay (i.e. the default Form Display) of this content type + $entity_form_display = \Drupal::service('entity_type.manager')->getStorage('entity_form_display') + ->load('commerce_product.' . $selected_bundle . '.default'); + + //Get the body field widget and add it to the form + if ($widget = $entity_form_display->getRenderer($selected_field)) { //Returns the widget class + $items = $commerce_product->get($selected_field); //Returns the FieldItemsList interface + $items->filterEmptyItems(); + $form[$selected_field] = $widget->form($items, $form, $form_state); //Builds the widget form and attach it to your form + $form[$selected_field]['widget']['#required'] = TRUE; + } + + return $form; + } + + + public function bundleAjaxCallback(array $form, FormStateInterface $form_state) { + $triggering_element = $form_state->getTriggeringElement(); + $parents = array_slice($triggering_element['#array_parents'], 0, -1); + $form_element = NestedArray::getValue($form, $parents); + return $form_element; + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + $bundle_id = $this->configuration['bundle']; + if (empty($bundle_id)) { + return FALSE; + } + $field_id = $this->configuration['field']; + if (empty($field_id)) { + return FALSE; + } + /** @var OrderItemInterface $order_item */ + $order_item = $this->getContextValue('commerce_order_item'); + + /** @var \Drupal\commerce_product\Entity\ProductInterface $current_product */ + $current_product = $order_item->getPurchasedEntity()->getProduct(); + if ($current_product->bundle() != $bundle_id) { + return FALSE; + } + + if (!$current_product->hasField($field_id)) { + return FALSE; + } + + $field_type = $current_product->get($field_id)->getFieldDefinition()->getType(); + $target_type = NULL; + if ($field_type == 'entity_reference') { + $target_type = $current_product->get($field_id)->getFieldDefinition()->getFieldStorageDefinition()->getSetting('target_type'); + } + + if ($target_type == 'taxonomy_term') { + if ($current_product->get($field_id)->getValue() == $this->configuration[$field_id]) { + return TRUE; + } + else { + /** @var TermInterface $term */ + $term = \Drupal::service('entity_type.manager') + ->getStorage("taxonomy_term")->load($this->configuration[$field_id][0]['target_id']); + $tree = \Drupal::service('entity_type.manager') + ->getStorage("taxonomy_term") + ->loadTree($term->getVocabularyId(), $term->id()); + $found = FALSE; + foreach ($tree as $item) { + if ($item->tid == $current_product->get($field_id)->getValue()[0]['target_id']) { + $found = TRUE; + break; + } + } + return $found; + } + } + elseif ($current_product->get($field_id)->getValue() != $this->configuration[$field_id]) { + return FALSE; + } + + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function summary() { + return $this->t('Compares the product entity.'); + } + +} diff --git a/modules/product/src/Plugin/Commerce/PromotionCondition/ProductVariationEquals.php b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductVariationEquals.php new file mode 100644 index 0000000000..ee9e90f8ae --- /dev/null +++ b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductVariationEquals.php @@ -0,0 +1,119 @@ +productVariationStorage = $entity_type_manager->getStorage('commerce_product_variation'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'variation_id' => NULL, + ] + parent::defaultConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + $form['variation_id'] = [ + '#type' => 'entity_autocomplete', + '#title' => t('Product variation'), + '#default_value' => $this->productVariationStorage->load($this->configuration['variation_id']), + '#target_type' => 'commerce_product_variation', + '#selection_handler' => 'default', + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + $values = $form_state->getValue($form['#parents']); + $this->configuration['variation_id'] = $values['variation_id']; + parent::submitConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + $variant_id = $this->configuration['variation_id']; + if (empty($variant_id)) { + return FALSE; + } + + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $current_product_variation */ + $current_product_variation = $this->getTargetEntity()->getPurchasedEntity(); + + $result = ($current_product_variation->id() == $variant_id); + return $this->isNegated() ? !$result : $result; + } + + /** + * {@inheritdoc} + */ + public function summary() { + return $this->t('Compares the purchased product variation.'); + } + +} diff --git a/modules/product/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEquals.php b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEquals.php new file mode 100644 index 0000000000..ecaec0834a --- /dev/null +++ b/modules/product/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEquals.php @@ -0,0 +1,189 @@ + NULL, + 'field' => NULL, + 'value' => NULL, + ] + parent::defaultConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form += parent::buildConfigurationForm($form, $form_state); + $ajax_wrapper_id = Html::getUniqueId('ajax-wrapper'); + // Prefix and suffix used for Ajax replacement. + $form['#prefix'] = '
'; + $form['#suffix'] = '
'; + +// $entity_id = isset($this->configuration['entity']) ? $this->configuration['entity'] : NULL; + $selected_bundle = isset($this->configuration['bundle']) ? $this->configuration['bundle'] : NULL; + $bundles = \Drupal::service("entity_type.bundle.info")->getBundleInfo('commerce_product_variation'); + $bundle_options = []; + foreach ($bundles as $bundle => $label) { + $bundle_options[$bundle] = $label['label']; + } + + $form['bundle'] = [ + '#type' => 'select', + '#options' => $bundle_options, + '#title' => t('Product variation bundle'), + '#default_value' => $selected_bundle, + '#required' => TRUE, + '#ajax' => [ + 'callback' => [$this, 'bundleAjaxCallback'], + 'wrapper' => $ajax_wrapper_id, + ], + ]; + if (!$selected_bundle) { + return $form; + } + + $fields = \Drupal::service("entity_field.manager")->getFieldDefinitions('commerce_product_variation', $selected_bundle); + $selected_field = isset($this->configuration['field']) ? $this->configuration['field'] : NULL; + + $filed_options = []; + foreach ($fields as $field_id => $field_definition) { + $filed_options[$field_id] = $field_definition->getLabel(); + } + + $form['field'] = [ + '#type' => 'select', + '#title' => t('Field'), + '#options' => $filed_options, + '#default_value' => $selected_field, + '#required' => TRUE, + '#ajax' => [ + 'callback' => [$this, 'bundleAjaxCallback'], + 'wrapper' => $ajax_wrapper_id, + ], + ]; + + if (!$selected_field) { + return $form; + } + + //Create an empty representative entity + $commerce_product_variation = \Drupal::service('entity_type.manager')->getStorage('commerce_product_variation')->create(array( + 'type' => $selected_bundle, + $selected_field => $this->configuration[$selected_field], + ) + ); + + //Get the EntityFormDisplay (i.e. the default Form Display) of this content type + $entity_form_display = \Drupal::service('entity_type.manager')->getStorage('entity_form_display') + ->load('commerce_product_variation.' . $selected_bundle . '.default'); + + //Get the body field widget and add it to the form + if ($widget = $entity_form_display->getRenderer($selected_field)) { //Returns the widget class + $items = $commerce_product_variation->get($selected_field); //Returns the FieldItemsList interface + $items->filterEmptyItems(); + $form[$selected_field] = $widget->form($items, $form, $form_state); //Builds the widget form and attach it to your form + $form[$selected_field]['widget']['#required'] = TRUE; + } + + return $form; + } + + public function bundleAjaxCallback(array $form, FormStateInterface $form_state) { + $triggering_element = $form_state->getTriggeringElement(); + $parents = array_slice($triggering_element['#array_parents'], 0, -1); + $form_element = NestedArray::getValue($form, $parents); + return $form_element; + } + + + /** + * {@inheritdoc} + */ + public function evaluate() { + $bundle_id = $this->configuration['bundle']; + if (empty($bundle_id)) { + return FALSE; + } + $field_id = $this->configuration['field']; + if (empty($field_id)) { + return FALSE; + } + /** @var OrderItemInterface $order_item */ + $order_item = $this->getContextValue('commerce_order_item'); + + /** @var ProductVariationInterface $current_product */ + $current_product_variation = $order_item->getPurchasedEntity(); + if ($current_product_variation->bundle() != $bundle_id) { + return FALSE; + } + + if (!$current_product_variation->hasField($field_id)) { + return FALSE; + } + + $field_type = $current_product_variation->get($field_id)->getFieldDefinition()->getType(); + $target_type = NULL; + if ($field_type == 'entity_reference') { + $target_type = $current_product->get($field_id)->getFieldDefinition()->getFieldStorageDefinition()->getSetting('target_type'); + } + + if ($target_type == 'taxonomy_term') { + if ($current_product_variation->get($field_id)->getValue() == $this->configuration[$field_id]) { + return TRUE; + } + else { + /** @var TermInterface $term */ + $term = \Drupal::service('entity_type.manager') + ->getStorage("taxonomy_term")->load($this->configuration[$field_id][0]['target_id']); + $tree = \Drupal::service('entity_type.manager') + ->getStorage("taxonomy_term") + ->loadTree($term->getVocabularyId(), $term->id()); + $found = FALSE; + foreach ($tree as $item) { + if ($item->tid == $current_product_variation->get($field_id)->getValue()[0]['target_id']) { + $found = TRUE; + break; + } + } + return $found; + } + } + elseif ($current_product_variation->get($field_id)->getValue() != $this->configuration[$field_id]) { + return FALSE; + } + + return TRUE; + + } + + /** + * {@inheritdoc} + */ + public function summary() { + return $this->t('Compares the product variation entity.'); + } + +} diff --git a/modules/product/src/Plugin/EntityReferenceSelection/ProductVariationSelection.php b/modules/product/src/Plugin/EntityReferenceSelection/ProductVariationSelection.php new file mode 100644 index 0000000000..598f63e395 --- /dev/null +++ b/modules/product/src/Plugin/EntityReferenceSelection/ProductVariationSelection.php @@ -0,0 +1,60 @@ +configuration['target_type']; + + $query = $this->buildEntityQuery($match, $match_operator); + if ($limit > 0) { + $query->range(0, $limit); + } + + $result = $query->execute(); + + if (empty($result)) { + return []; + } + + /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface[] $variation_types */ + $variation_types = $this->entityManager->getStorage('commerce_product_variation_type')->loadMultiple(); + $options = array(); + $entities = $this->entityManager->getStorage($target_type)->loadMultiple($result); + foreach ($entities as $entity_id => $entity) { + $bundle = $variation_types[$entity->bundle()]; + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $entity */ + $entity = $this->entityManager->getTranslationFromContext($entity); + + if ($bundle->shouldGenerateTitle()) { + $option_label = $entity->label(); + } + else { + $option_label = $entity->getProduct()->label() . ': ' . $entity->label(); + } + + $options[$bundle->id()][$entity_id] = Html::escape($option_label); + } + + return $options; + } + +}