Adding products with attributes to cart programmatically using Ubercart

Adding products with attributes to cart programmatically using Ubercart

Difficulty: 
Piece of Cake

While still using Ubercart on some legacy application, I found the need to add a product to the cart programmatically with attributes already set. So I uncovered the dust from this old Ubercart utility library and thought it would be nice to share.

There are a few interesting methods in it:

  • GetProductAttributeByName: when dealing with attributes Ubercart will not use attribute name's in the stored data. Instead, it will use numeric ID's. Use this to retrieve attribute information from a product by using it's friendly name.
  • GetProductAttributes: just a cached wrapper for uc_product_get_attributes.
  • AddProductToCartWithAttributes: add a product to the user's cart while specifing attribute values.
  • UbercartProductAddAttribute: Add an attribute - with value - to a product object.
<?php

namespace Drupal\pi\Managers;

use \Drupal\fdf\Utilities\UtilsEntity;

class ManagerUbercart {

  /**
   * Get product attribute from it's name.
   *
   * @param int $nid 
   * @param mixed $cart_item 
   * @param string $attribute_name
   * 
   * @return array
   */
  public static function GetProductAttributeByName($nid, $cart_item, $attribute_name) {
    $attributes = static::GetProductAttributes($nid);
    $inscription_id = null;

    $inscription_attribute_key = null;
    foreach($attributes as $key => $attribute) {
      if ($attribute->name !== $attribute_name) {
        continue;
      }

      $aid = $attribute->aid;

      if (isset($cart_item->data['attributes'][$aid])) {
        $inscription_id = $cart_item->data['attributes'][$aid];
        $inscription_attribute_key = $aid;
        break;
      }

      // Once an order is complete, attribute data is stored differently.
      if (isset($cart_item->data['attributes_detail'][$aid])) {
        $inscription_id = $cart_item->data['attributes_detail'][$aid]['option']['name'];
        $inscription_attribute_key = null;
        break;
      }
    }

    $result = array('key' => $inscription_attribute_key, 'value' => $inscription_id);

    return $result;
  }
  
  /**
   * Cached version of get product attributes.
   */
  private static function GetProductAttributes($nid) {
    $key = 'managerubercart:' . $nid;
    if ($cache = cache_get($key)) {
      return $cache->data;
    }
    $data = uc_product_get_attributes($nid);
    // We have no true invalidation mechanism here, so just
    // set a time based expiration of 24H.
    cache_set($key, $data, 'cache', time() + (3600 * 24));
    return $data;
  }
  
  /**
   * Add an attribute to a product.
   * 
   * @param mixed $product
   *   Product object.
   * @param array $attributes
   *   Attribute values, keyed by friendly name.
   */
  public static function UbercartProductAddAttribute(&$product, array $attributes) {
    $atts = static::GetProductAttributes($product->nid);
    $data = $product->data;
    if (empty($data)) {
      $data = array();
    }
    foreach($attributes as $name => $value) {
      foreach($atts as $key => $attribute) {
        if (strcasecmp($attribute->name, $name) != 0) {
          continue;
        }

        $aid = $attribute->aid;
        $data['attributes'][$aid] = $value;
        unset($attributes[$name]);
        break;
      }
    }
    $product->data = $data;
  }
  
  /**
   * Add a product to the current cart with attributes.
   *
   * @param $nid int
   *  Id of the product.
   *
   * @param $attributes array
   *   Associative array with attributes name's as keys.
   *
   * @return void
   */
  public static function AddProductToCartWithAttributes($nid, array $attributes, $qty = 1) {
    
    $data = array();
    
    $atts = static::GetProductAttributes($nid);

    foreach($attributes as $name => $value) {
      foreach($atts as $key => $attribute) {
        if ($attribute->name !== $name) {
          continue;
        }

        $aid = $attribute->aid;
        $data['attributes'][$aid] = $value;
        unset($attributes[$name]);
        break;
      }
    }
    
    if(!empty($attributes)) {
      drupal_set_message('Not all product attributes could be binded.');
    }
    
    uc_cart_add_item($nid, $qty, $data, NULL, TRUE, TRUE, TRUE);
  }
}

 

Add new comment

By: root Sunday, January 3, 2016 - 00:00