You are here

uc_cart.module in Ubercart 8.4

Handles all things concerning Ubercart's shopping cart.

The Ubercart cart system functions much like the e-commerce cart at its base level... in fact, most carts do. This module handles the cart display, adding items to a cart, and checking out. The module enables the cart, products, and checkout to be extensible.

File

uc_cart/uc_cart.module
View source
<?php

/**
 * @file
 * Handles all things concerning Ubercart's shopping cart.
 *
 * The Ubercart cart system functions much like the e-commerce cart at its base
 * level... in fact, most carts do. This module handles the cart display,
 * adding items to a cart, and checking out. The module enables the cart,
 * products, and checkout to be extensible.
 */
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\uc_cart\CartInterface;
use Drupal\uc_order\Entity\Order;
use Drupal\uc_payment\PaymentReceiptInterface;

/**
 * Implements hook_cron().
 */
function uc_cart_cron() {
  $cart_manager = \Drupal::service('uc_cart.manager');
  $cart_config = \Drupal::config('uc_cart.settings');
  $connection = \Drupal::database();

  // Empty anonymous carts.
  $time = strtotime($cart_config
    ->get('anon_duration') . ' ' . $cart_config
    ->get('anon_unit') . ' ago');
  $result = $connection
    ->query('SELECT DISTINCT cart_id FROM {uc_cart_products} WHERE changed <= :changed', [
    ':changed' => $time,
  ]);
  foreach ($result as $row) {
    if (strlen($row->cart_id) >= 22) {
      $cart_manager
        ->emptyCart($row->cart_id);
    }
  }

  // Empty authenticated carts.
  $time = strtotime($cart_config
    ->get('auth_duration') . ' ' . $cart_config
    ->get('auth_unit') . ' ago');
  $result = $connection
    ->query('SELECT DISTINCT cart_id FROM {uc_cart_products} WHERE changed <= :changed', [
    ':changed' => $time,
  ]);
  foreach ($result as $row) {
    if (strlen($row->cart_id) < 22) {
      $cart_manager
        ->emptyCart($row->cart_id);
    }
  }

  // Update status of abandoned orders.
  $result = $connection
    ->query('SELECT order_id FROM {uc_orders} WHERE order_status = :status AND changed < :time', [
    ':status' => 'in_checkout',
    ':time' => \Drupal::time()
      ->getRequestTime() - CartInterface::ORDER_TIMEOUT,
  ])
    ->fetchCol();
  foreach ($result as $order_id) {
    Order::load($order_id)
      ->setStatusId('abandoned')
      ->save();
  }
}

/**
 * Implements hook_theme().
 */
function uc_cart_theme() {
  return [
    'uc_cart_block_title' => [
      'variables' => [
        'title' => NULL,
        'show_icon' => FALSE,
        'cart_empty' => NULL,
        'collapsible' => TRUE,
        'collapsed' => TRUE,
      ],
      'template' => 'uc-cart-block-title',
    ],
    'uc_cart_block' => [
      'variables' => [
        'items' => NULL,
        'item_count' => NULL,
        'total' => NULL,
        'summary_links' => NULL,
        'collapsed' => TRUE,
      ],
      'template' => 'uc-cart-block',
    ],
    'uc_cart_view_form' => [
      'render element' => 'form',
      'template' => 'uc-cart-form',
    ],
    'uc_cart_checkout_buttons' => [
      'render element' => 'buttons',
      'template' => 'uc-cart-checkout-buttons',
    ],
    'uc_cart_empty' => [
      'variables' => [],
      'template' => 'uc-cart-empty',
    ],
    'uc_cart_review_table' => [
      'variables' => [
        'items' => [],
        'show_subtotal' => TRUE,
      ],
      'file' => 'uc_cart.theme.inc',
      'function' => 'theme_uc_cart_review_table',
    ],
    'uc_cart_checkout_review' => [
      'variables' => [
        'panes' => NULL,
        'form' => NULL,
      ],
      'file' => 'uc_cart.theme.inc',
      'function' => 'theme_uc_cart_checkout_review',
    ],
    'uc_cart_complete_sale' => [
      'variables' => [
        'message' => '',
        'order' => NULL,
      ],
      'template' => 'uc-cart-complete-sale',
    ],
  ];
}

/**
 * Prepares variables for the cart block title template.
 *
 * Default template: uc-cart-block-title.html.twig.
 */
function template_preprocess_uc_cart_block_title(&$variables) {
  $variables['cart_url'] = Url::fromRoute('uc_cart.cart');
}

/**
 * Prepares variables for the cart block template.
 *
 * Default template: uc-cart-block.html.twig.
 */
function template_preprocess_uc_cart_block(&$variables) {
  $variables['attributes']['class'][] = 'cart-block-items';
  if ($variables['collapsed']) {
    $variables['attributes']['class'][] = 'collapsed';
  }
  $variables['total'] = uc_currency_format($variables['total']);
  foreach ($variables['items'] as $key => $item) {
    $variables['items'][$key]['price'] = uc_currency_format($item['price']);
  }
  $variables['summary_links'] = [
    '#theme' => 'links',
    '#links' => $variables['summary_links'],
    '#attributes' => [
      'class' => [
        'cart-block-summary-links',
      ],
    ],
  ];
}

/**
 * Prepares variables for the checkout completion template.
 *
 * Default template: uc-cart-complete-sale.html.twig.
 */
function template_preprocess_uc_cart_complete_sale(&$variables) {
  $variables['front_page'] = Url::fromRoute('<front>');
}

/**
 * Prepares variables for the cart checkout buttons template.
 *
 * Default template: uc-cart-checkout-buttons.html.twig.
 */
function template_preprocess_uc_cart_checkout_buttons(&$variables) {
  $buttons = [];
  foreach (Element::children($variables['buttons']) as $button) {
    $buttons[] = $variables['buttons'][$button];
  }
  $variables['buttons'] = $buttons;
}

/**
 * Preprocesses the cart block output to include the icon.
 */
function uc_cart_preprocess_block(&$variables) {
  $cart = \Drupal::service('uc_cart.manager')
    ->get();
  if ($variables['plugin_id'] == 'uc_cart_block' && $variables['label']) {
    $variables['label'] = [
      '#theme' => 'uc_cart_block_title',
      '#title' => $variables['label'],
      '#show_icon' => $variables['configuration']['show_image'],
      '#cart_empty' => !$cart
        ->getContents(),
      '#collapsible' => $variables['configuration']['collapsible'],
      '#collapsed' => $variables['configuration']['collapsed'],
    ];
  }
}

/**
 * Implements hook_node_delete().
 */
function uc_cart_node_delete($node) {
  if (uc_product_is_product($node)) {
    $result = \Drupal::entityQuery('uc_cart_item')
      ->condition('nid', $node
      ->id())
      ->execute();
    if (!empty($result)) {
      $storage = \Drupal::entityTypeManager()
        ->getStorage('uc_cart_item');
      $entities = $storage
        ->loadMultiple(array_keys($result));
      $storage
        ->delete($entities);
    }
  }
}

/**
 * Implements hook_user_login().
 *
 * Updates cart to include items from the user's anonymous session.
 */
function uc_cart_user_login($account) {
  $session = \Drupal::service('session');
  if (!$session
    ->has('uc_cart_id')) {

    // No anonymous cart, so nothing to do here.
    return;
  }

  // If there are items in the anonymous cart, consolidate them.
  $cart_manager = \Drupal::service('uc_cart.manager');
  $anonymous_cart = $cart_manager
    ->get($session
    ->get('uc_cart_id'));
  if ($items = $anonymous_cart
    ->getContents()) {

    // Remove the anonymous cart items.
    $anonymous_cart
      ->emptyCart();

    // Merge the anonymous items into the user cart.
    $user_cart = $cart_manager
      ->get($account
      ->id());
    foreach ($items as $item) {
      $user_cart
        ->addItem($item->nid->target_id, $item->qty->value, $item->data
        ->first()
        ->toArray(), FALSE);
    }

    // Unset the anonymous cart ID, it's no longer needed.
    $session
      ->remove('uc_cart_id');
  }
}

/**
 * Implements hook_uc_payment_receipt_insert().
 *
 * Ensure the user has an account when payment is made.
 */
function uc_cart_uc_payment_receipt_insert(PaymentReceiptInterface $payment) {
  \Drupal::service('uc_cart.manager')
    ->completeSale($payment
    ->getOrder(), FALSE);
}

/**
 * Implements hook_uc_checkout_complete().
 *
 * Sends basic e-mail notifications if Rules is not installed.
 */
function uc_cart_uc_checkout_complete($order) {

  // @todo Uncomment this conditional when Rules actually works.

  //if (!\Drupal::moduleHandler()->moduleExists('rules')) {
  \Drupal::moduleHandler()
    ->loadInclude('uc_order', 'inc', 'uc_order.rules');
  $cart_config = \Drupal::config('uc_cart.settings');
  if ($cart_config
    ->get('checkout_email_customer')) {
    $subject = t('Your Order at @store', [
      '@store' => uc_store_name(),
    ]);
    uc_order_action_email_invoice($order, uc_store_email_from(), $order
      ->getEmail(), $subject, 'customer', 'checkout-mail');
  }
  if ($cart_config
    ->get('checkout_email_admin')) {
    $subject = t('New Order at @store', [
      '@store' => uc_store_name(),
    ]);
    uc_order_action_email_invoice($order, uc_store_email_from(), uc_store_email(), $subject, 'admin', 'admin-mail');
  }

  //}
}

Functions

Namesort descending Description
template_preprocess_uc_cart_block Prepares variables for the cart block template.
template_preprocess_uc_cart_block_title Prepares variables for the cart block title template.
template_preprocess_uc_cart_checkout_buttons Prepares variables for the cart checkout buttons template.
template_preprocess_uc_cart_complete_sale Prepares variables for the checkout completion template.
uc_cart_cron Implements hook_cron().
uc_cart_node_delete Implements hook_node_delete().
uc_cart_preprocess_block Preprocesses the cart block output to include the icon.
uc_cart_theme Implements hook_theme().
uc_cart_uc_checkout_complete Implements hook_uc_checkout_complete().
uc_cart_uc_payment_receipt_insert Implements hook_uc_payment_receipt_insert().
uc_cart_user_login Implements hook_user_login().