View source
<?php
namespace Drupal\commerce_promotion\Plugin\Commerce\InlineForm;
use Drupal\commerce\Plugin\Commerce\InlineForm\InlineFormBase;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class CouponRedemption extends InlineFormBase {
protected $entityTypeManager;
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entity_type_manager;
}
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'));
}
public function defaultConfiguration() {
return [
'order_id' => '',
'max_coupons' => NULL,
];
}
protected function requiredConfiguration() {
return [
'order_id',
];
}
public function buildInlineForm(array $inline_form, FormStateInterface $form_state) {
$inline_form = parent::buildInlineForm($inline_form, $form_state);
$order = $this->entityTypeManager
->getStorage('commerce_order')
->load($this->configuration['order_id']);
if (!$order) {
throw new \RuntimeException('Invalid order_id given to the coupon_redemption inline form.');
}
assert($order instanceof OrderInterface);
$coupons = $order
->get('coupons')
->referencedEntities();
$inline_form = [
'#tree' => TRUE,
'#attached' => [
'library' => [
'commerce_promotion/coupon_redemption_form',
],
],
'#theme' => 'commerce_coupon_redemption_form',
'#configuration' => $this
->getConfiguration(),
] + $inline_form;
$inline_form['code'] = [
'#type' => 'textfield',
'#title' => $this
->t('Coupon code'),
'#attributes' => [
'autocomplete' => 'new-password',
],
];
$inline_form['apply'] = [
'#type' => 'submit',
'#value' => $this
->t('Apply coupon'),
'#name' => 'apply_coupon',
'#limit_validation_errors' => [
$inline_form['#parents'],
],
'#submit' => [
[
get_called_class(),
'applyCoupon',
],
],
'#ajax' => [
'callback' => [
get_called_class(),
'ajaxRefreshForm',
],
'element' => $inline_form['#parents'],
],
];
$max_coupons = $this->configuration['max_coupons'];
if ($max_coupons && count($coupons) >= $max_coupons) {
$inline_form['code']['#access'] = FALSE;
$inline_form['apply']['#access'] = FALSE;
}
foreach ($coupons as $index => $coupon) {
$inline_form['coupons'][$index]['code'] = [
'#plain_text' => $coupon
->getCode(),
];
$inline_form['coupons'][$index]['display_name'] = [
'#plain_text' => $coupon
->getPromotion()
->label(),
];
$inline_form['coupons'][$index]['remove_button'] = [
'#type' => 'submit',
'#value' => $this
->t('Remove coupon'),
'#name' => 'remove_coupon_' . $index,
'#ajax' => [
'callback' => [
get_called_class(),
'ajaxRefreshForm',
],
'element' => $inline_form['#parents'],
],
'#weight' => 50,
'#limit_validation_errors' => [
$inline_form['#parents'],
],
'#coupon_id' => $coupon
->id(),
'#submit' => [
[
get_called_class(),
'removeCoupon',
],
],
'#parents' => array_merge($inline_form['#parents'], [
'remove_coupon_' . $index,
]),
];
}
return $inline_form;
}
public function validateInlineForm(array &$inline_form, FormStateInterface $form_state) {
parent::validateInlineForm($inline_form, $form_state);
$triggering_element = $form_state
->getTriggeringElement();
$button_type = isset($triggering_element['#button_type']) ? $triggering_element['#button_type'] : NULL;
if ($triggering_element['#name'] != 'apply_coupon' && $button_type != 'primary') {
return;
}
$coupon_code_parents = array_merge($inline_form['#parents'], [
'code',
]);
$coupon_code = $form_state
->getValue($coupon_code_parents);
$coupon_code_path = implode('][', $coupon_code_parents);
if (empty($coupon_code)) {
if ($triggering_element['#name'] == 'apply_coupon') {
$form_state
->setErrorByName($coupon_code_path, t('Please provide a coupon code.'));
}
return;
}
$coupon_storage = $this->entityTypeManager
->getStorage('commerce_promotion_coupon');
$coupon = $coupon_storage
->loadEnabledByCode($coupon_code);
if (empty($coupon)) {
$form_state
->setErrorByName($coupon_code_path, t('The provided coupon code is invalid.'));
return;
}
$order_storage = $this->entityTypeManager
->getStorage('commerce_order');
$order = $order_storage
->load($this->configuration['order_id']);
foreach ($order
->get('coupons') as $item) {
if ($item->target_id == $coupon
->id()) {
return;
}
}
if (!$coupon
->available($order)) {
$form_state
->setErrorByName($coupon_code_path, t('The provided coupon code is not available. It may have expired or already been used.'));
return;
}
if (!$coupon
->getPromotion()
->applies($order)) {
$form_state
->setErrorByName($coupon_code_path, t('The provided coupon code cannot be applied to your order.'));
return;
}
$inline_form['code']['#coupon_id'] = $coupon
->id();
}
public static function applyCoupon(array $form, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
$parents = array_slice($triggering_element['#parents'], 0, -1);
$inline_form = NestedArray::getValue($form, $parents);
$user_input =& $form_state
->getUserInput();
NestedArray::setValue($user_input, array_merge($parents, [
'code',
]), '');
if (isset($inline_form['code']['#coupon_id'])) {
$order_storage = \Drupal::entityTypeManager()
->getStorage('commerce_order');
$order = $order_storage
->load($inline_form['#configuration']['order_id']);
$order
->get('coupons')
->appendItem($inline_form['code']['#coupon_id']);
$order
->save();
}
$form_state
->setRebuild();
}
public static function removeCoupon(array $form, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
$parents = array_slice($triggering_element['#parents'], 0, -1);
$inline_form = NestedArray::getValue($form, $parents);
$order_storage = \Drupal::entityTypeManager()
->getStorage('commerce_order');
$order = $order_storage
->load($inline_form['#configuration']['order_id']);
$coupon_ids = array_column($order
->get('coupons')
->getValue(), 'target_id');
$coupon_index = array_search($triggering_element['#coupon_id'], $coupon_ids);
$order
->get('coupons')
->removeItem($coupon_index);
$order
->save();
$form_state
->setRebuild();
}
}