commercetools-8.x-1.2-alpha1/modules/commercetools_content/src/Form/CartForm.php
modules/commercetools_content/src/Form/CartForm.php
<?php
namespace Drupal\commercetools_content\Form;
use Drupal\commercetools\CommercetoolsCarts;
use Drupal\commercetools\Exception\CommercetoolsGraphqlErrorException;
use Drupal\commercetools\Form\UiModuleSettingsFormBase;
use Drupal\commercetools\Routing\UiModulesRouteProviderBase;
use Drupal\commercetools_content\Routing\RouteProvider;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides cart form.
*/
class CartForm extends FormBase {
/**
* Current cart.
*
* @var ?array
*/
protected $cart = NULL;
/**
* The commercetools cart service.
*
* @var \Drupal\commercetools\CommercetoolsCarts
*/
protected CommercetoolsCarts $ctCart;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->ctCart = $container->get('commercetools.carts');
return $instance;
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'commercetools_content_cart_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $install_state = NULL) {
$cart = $this->getCart();
$form['#theme'] = 'commercetools_cart_form';
$form['#attributes']['id'][] = 'commercetools-cart-form';
$form['#attached']['library'][] = 'commercetools_content/carts';
$form['#cart'] = $cart;
$form['lineItems'] = [
'#type' => 'container',
'#tree' => TRUE,
];
foreach ($cart['lineItems'] as $lineItem) {
$form['lineItems'][$lineItem['id']]['quantity'] = [
'#type' => 'hidden',
'#default_value' => $lineItem['quantity'],
'#attributes' => ['class' => ['line-item-quantity']],
];
$form['lineItems'][$lineItem['id']]['remove'] = [
'#type' => 'hidden',
'#default_value' => FALSE,
'#attributes' => ['class' => ['line-item-quantity']],
];
}
$form['cartUpdate'] = [
'#type' => 'submit',
'#value' => $this->t('Update'),
'#submit' => ['::updateCart'],
'#ajax' => [
'callback' => '::ajaxCallback',
'disable-refocus' => FALSE,
'event' => 'click',
'wrapper' => 'commercetools-cart-form',
'progress' => [
'type' => 'fullscreen',
'message' => $this->t('Updating...'),
],
],
'#attributes' => ['class' => ['cart-update-button']],
];
$form['discounts'] = [
'#type' => 'container',
'#attributes' => ['id' => 'discounts-wrapper'],
];
$form['discounts']['discount_code'] = [
'#type' => 'textfield',
'#title' => $this->t('Your discount code (optional)'),
];
$form['discounts']['wrap'] = [
'#type' => 'container',
'#attributes' => ['class' => 'form-actions', 'mb-3'],
];
$form['discounts']['wrap']['submit_discounts'] = [
'#type' => 'submit',
'#value' => $this->t('Redeem Code'),
'#submit' => ['::submitDiscounts'],
'#states' => [
'enabled' => [
':input[name="discount_code"]' => ['filled' => TRUE],
],
],
];
if (!empty($cart['discountCodes'])) {
$form['discounts_wrap'] = [
'#type' => 'container',
'#attributes' => [
'class' => ['d-flex', 'flex-nowrap', 'gap-2', 'mb-3'],
],
];
foreach ($cart['discountCodes'] as $discountCode) {
$discountCodeId = $discountCode['id'];
$form['discounts_wrap']['discounts'][$discountCodeId] = [
'#type' => 'container',
'#attributes' => [
'class' => ['bg-success', 'd-flex', 'p-1', 'align-items-center'],
],
];
$form['discounts_wrap']['discounts'][$discountCodeId]['text'] = ['#markup' => "<span>{$discountCode['name']}</span>"];
$form['discounts_wrap']['discounts'][$discountCodeId]['remove'] = [
'#type' => 'button',
'#name' => 'remove-' . $discountCodeId,
'#value' => '',
'#attributes' => [
'class' => ['btn-close', 'ms-2'],
'aria-label' => ['Remove'],
'data-key' => $discountCode['code'],
'data-id' => $discountCodeId,
],
'#submit' => ['::removeDiscountSubmit'],
];
}
}
$checkoutPath = $this->config(ContentSettingsForm::CONFIGURATION_NAME)
->get(UiModuleSettingsFormBase::CONFIG_CHECKOUT_PATH);
$form['actions'] = [
'#type' => 'actions',
'#access' => !empty($cart['lineItems']),
'submit' => [
'#type' => 'link',
'#title' => $this->t('Checkout'),
'#url' => isset($checkoutPath)
? Url::fromRoute(RouteProvider::ROUTE_PREFIX . UiModulesRouteProviderBase::PAGE_CHECKOUT_ROUTE)
: Url::fromUserInput('#'),
'#attributes' => [
'class' => [
'btn',
'btn-primary',
isset($checkoutPath) ? '' : 'disabled',
],
],
],
];
$form['#cache']['contexts'] = [
'commercetools_cart',
];
return $form;
}
/**
* Ajax callback to update product variant.
*/
public function ajaxCallback(array &$form, FormStateInterface $form_state) {
return $form;
}
/**
* Submit function to update a user cart.
*/
public function updateCart(array $form, FormStateInterface $form_state) {
$cart = $this->getCart();
$actions = [];
foreach ($form_state->getValue('lineItems') as $lineItemId => $lineItem) {
$actions[] = $lineItem['remove']
? ['removeLineItem' => ['lineItemId' => $lineItemId]]
: ['changeLineItemQuantity' => ['lineItemId' => $lineItemId, 'quantity' => (int) $lineItem['quantity']]];
}
$this->ctCart->updateCart($cart['id'], $cart['version'], $actions);
$this->cart = NULL;
$form_state->setRebuild();
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
/**
* Submit discount callback.
*/
public function submitDiscounts(array &$form, FormStateInterface $form_state) {
$cart = $this->getCart();
$code = trim($form_state->getValue('discount_code'));
try {
$response = $this->ctCart->updateCart($cart['id'], $cart['version'], [
[
'addDiscountCode' => [
'code' => $code,
],
],
]);
}
catch (CommercetoolsGraphqlErrorException $e) {
$knownError = FALSE;
foreach ($e->getMessages() as $message) {
if (str_starts_with($message, 'The discount code \'')) {
$this->messenger()->addWarning($this->t(
"The discount code '@code' was not found.",
['@code' => $code]
));
$knownError = TRUE;
break;
}
}
if (!$knownError) {
throw $e;
}
}
if (!empty($response)) {
$this->cart = $response->getData();
$this->messenger()->addMessage($this->t("Successfully redeemed code: '@code'", ['@code' => $code]));
}
else {
$this->cart = NULL;
}
}
/**
* Remove discount callback.
*/
public function removeDiscountSubmit(array &$form, FormStateInterface $form_state) {
$cart = $this->getCart();
$actions_element = $form_state->getTriggeringElement();
$codeId = $actions_element["#attributes"]["data-id"];
try {
$response = $this->ctCart->updateCart($cart['id'], $cart['version'], [
[
'removeDiscountCode' => [
'discountCode' => [
'typeId' => 'discount-code',
'id' => $codeId,
],
],
],
]);
}
catch (CommercetoolsGraphqlErrorException $e) {
foreach ($e->getMessages() as $message) {
$this->messenger()->addWarning($message);
}
}
if (!empty($response)) {
$this->cart = $response->getData();
$code = $actions_element['#attributes']['data-key'];
$this->messenger()->addMessage($this->t("The following code has been removed from the cart: '@code'", ['@code' => $code]));
}
else {
$this->cart = NULL;
}
}
/**
* Get cart.
*/
protected function getCart(bool $refresh = FALSE) {
if (!empty($this->cart) && !$refresh) {
return $this->cart;
}
$cartResponse = $this->ctCart->getCurrentCart();
$cart = !empty($cartResponse)
? $cartResponse->getData()
: [
'totalLineItemQuantity' => 0,
'lineItems' => [],
];
$this->cart = $cart;
return $cart;
}
}
