backdrop-contrib / ubercart

A flexible but easy-to-use e-commerce system for Backdrop.
https://backdropcms.org/project/ubercart
GNU General Public License v2.0
4 stars 10 forks source link

New feature: block visibility condition based on whether a cart contains a SKU #513

Open herbdool opened 6 days ago

herbdool commented 6 days ago

I've got a small, working module which adds a new visibility condition for blocks. It allows someone to enter various SKUs and then it will check if any of them are in the cart. Then can choose whether to show or hide the block based on that.

2024-11-06 12 03 47 bd3 lndo site ed8870c8c7b5

I may just add it as a contrib module, but wondering if you want it as part of ubercart. @bugfolder

herbdool commented 6 days ago

Just going to add the code here and can figure it out later where to put it. For lack of a better name, the module is called uc_layout_access.

In uc_layout_access.module:

/**
 * @file
 * Ubercart Layout access
 */

/**
 * Implements hook_autoload_info().
 */
function uc_layout_access_autoload_info() {
  return array(
    'UbercartCartLayoutAccess' => 'plugins/access/ubercart_cart_layout_access.inc',
  );
}

/**
 * Implements hook_layout_access_info().
 */
function uc_layout_access_layout_access_info() {
  $info['ubercart_cart'] = array(
    'title' => t('Ubercart cart'),
    'description' => t('Does the cart contain one of these products.'),
    'class' => 'UbercartCartLayoutAccess',
  );

  return $info;
}

/**
 * Check if a cart item matches any pattern in a set of products.
 *
 * @param string $cart_item
 *   The cart_item to match.
 * @param string $products
 *   String containing a set of products separated by \n, \r or \r\n.
 *
 * @return bool
 *   Boolean value: TRUE if the cart_item matches a pattern, FALSE otherwise.
 */
function uc_layout_access_match_cart_item($cart_item, $products) {
  $regexps = &backdrop_static(__FUNCTION__);

  if (!isset($regexps[$products])) {
    // Convert cart_item settings to a regular expression.
    $to_replace = array(
      '/(\r\n?|\n)/', // newlines
      '/\\\\\*/',     // asterisks
    );
    $replacements = array(
      '|',
      '.*',
    );
    $products_quoted = preg_quote($products, '/');
    $regexps[$products] = '/^(' . preg_replace($to_replace, $replacements, $products_quoted) . ')$/';
  }
  return (bool) preg_match($regexps[$products], (string) $cart_item);
}

In plugins/access/ubercart_cart_layout_access.inc:

/**
 * @file
 * Class for loading, modifying, and saving a layout access rule (condition).
 */
class UbercartCartLayoutAccess extends LayoutAccessNegatable {
  /**
   * Constructor for a Layout access rule.
   */
  function __construct($plugin_name, array $data = array()) {
    parent::__construct($plugin_name, $data);
    $this->settings += array(
      'negate' => 1,
      'products' => '',
    );
  }

  /**
   * {@inheritdoc}
   */
  function form(&$form, &$form_state) {
    parent::form($form, $form_state);
    $form['negate'] = array(
      '#type' => 'radios',
      '#options' => array(
        0 => t('Allow access if the following products are in the cart'),
        1 => t('Deny access if any of the following products are in the cart'),
      ),
      '#default_value' => (int) $this->settings['negate'],
    );
    $form['products'] = array(
      '#type' => 'textarea',
      '#title' => t('Products'),
      '#default_value' => $this->settings['products'],
      '#description' => t('Enter a product SKU, one per line. Only if one of the listed products is in the cart will this be visible, or hidden, if "Reverse" is checked.'),
      '#required' => TRUE,
    );
  }

  /**
   * {@inheritdoc}
   */
  function checkAccess() {
    $product_match = FALSE;
    $cart_items = uc_cart_get_contents();
    foreach ($cart_items as $cart_item) {
      $product_match = riseup_ubercart_match_cart_item($cart_item->model, $this->settings['products']);
      if ($product_match) {
        break;
      }
    }
    if ($this->settings['negate']) {
      return !$product_match;
    }
    else {
      return $product_match;
    }
  }

  /**
   * {@inheritdoc}
   */
  function summary() {

    $products = explode("\n", $this->settings['products']);
    if ($this->settings['negate']) {
      return format_plural(count($products), 'Cart items does not contain "@products" product', 'Cart items does not contain one of "@products" products', array('@products' => implode(', ', $products)));
    }
    else {
      return format_plural(count($products), 'Cart items contains "@products" product', 'Cart items contains one of "@products" products', array('@products' => implode(', ', $products)));
    }
  }
}