You are here

commerce_autosku.module in Commerce AutoSKU 7

Same filename and directory in other branches
  1. 8.2 commerce_autosku.module

Module hooks and helper functions for commerce_autosku

File

commerce_autosku.module
View source
<?php

/**
 * @file
 * Module hooks and helper functions for commerce_autosku
 */
define('COMMERCE_AUTOSKU_DISALLOWED', '@[^A-Z|a-z|0-9|\\-|_]@');
define('COMMERCE_AUTOSKU_REPLACEMENT', '');

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_autosku_form_commerce_product_ui_product_type_form_alter(&$form, &$form_state) {
  if (!empty($form_state['product_type']['autosku']['pattern'])) {
    $pattern = $form_state['product_type']['autosku']['pattern'];
    $advanced = $form_state['product_type']['autosku']['advanced'];
  }
  else {
    $pattern = NULL;
    $advanced = array();
  }
  $advanced += _commerce_autosku_default_settings();
  $form['product_type']['autosku_status'] = array(
    '#type' => 'checkbox',
    '#title' => t('Automatically Generate SKU'),
    '#default_value' => !empty($pattern),
  );
  $autosku =& $form['product_type']['autosku'];
  $autosku = array(
    '#type' => 'fieldset',
    '#title' => t('AutoSKU Parameters'),
    '#states' => array(
      'visible' => array(
        ':input[name="product_type[autosku_status]"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $autosku['pattern'] = array(
    '#type' => 'textfield',
    '#title' => t('SKU Pattern'),
    '#default_value' => $pattern,
    '#maxlength' => 255,
    '#size' => 128,
    '#states' => array(
      'required' => array(
        ':input[name="product_type[autosku_status]"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
    '#element_validate' => array(
      'commerce_autosku_element_validate_sku_pattern',
    ),
  );
  if (module_exists('token')) {
    $autosku['pattern']['#element_validate'][] = 'token_element_validate';
    $autosku['pattern']['#token_type'] = array(
      'commerce-product',
    );
    $autosku['pattern']['#min_tokens'] = 1;
    $autosku['help'] = array(
      '#type' => 'item',
      '#theme' => 'token_tree',
      '#token_types' => array(
        'commerce-product',
      ),
    );
  }
  else {
    $token_list = array();
    $tokens = token_info();
    $product_tokens = $tokens['tokens']['commerce-product'];
    unset($product_tokens['sku']);
    foreach (array_keys($product_tokens) as $token) {
      $token_list[] = '<b>[commerce-product:' . check_plain($token) . ']</b> ' . filter_xss_admin($product_tokens[$token]['description']);
    }
    $autosku['help'] = array(
      '#type' => 'markup',
      '#title' => 'Valid tokens:',
      '#theme' => 'item_list',
      '#items' => $token_list,
      '#description' => 'test',
    );
  }
  $autosku['advanced'] = array(
    '#type' => 'fieldset',
    '#title' => t('Advanced'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $autosku['advanced']['update_existing'] = array(
    '#type' => 'checkbox',
    '#title' => t('Always regenerate SKU'),
    '#default_value' => $advanced['update_existing'],
    '#description' => t('If enabled, the SKU will be regenerated each time the product is saved.  Disable this if you prefer that SKUs stay the same regardless of any changes to the product.'),
  );
  $autosku['advanced']['hide_sku'] = array(
    '#type' => 'checkbox',
    '#title' => t('Hide SKU Field'),
    '#default_value' => $advanced['hide_sku'],
    '#description' => t('If enabled, the SKU field will not be shown the product form.'),
  );
  $autosku['advanced']['case'] = array(
    '#type' => 'select',
    '#title' => t('SKU Case'),
    '#options' => array(
      'original' => t('Do not change'),
      'uppercase' => t('Uppercase'),
      'lowercase' => t('Lowercase'),
    ),
    '#default_value' => $advanced['case'],
  );
}
function commerce_autosku_element_validate_sku_pattern(&$element, &$form_state) {
  if ($form_state['values']['product_type']['autosku_status']) {
    $tokens = token_scan($element['#value']);
    if (empty($tokens)) {
      form_error($element, t('SKU pattern must contain at least one valid token.'));
      return;
    }
    if (isset($tokens['commerce-product']['sku'])) {
      form_error($element, t('You may not use the SKU token in the SKU Pattern.'));
      return;
    }
    if (!module_exists('token') && drupal_strlen($element['#value'])) {
      if (!isset($tokens['commerce-product']) || count($tokens) > 1) {
        form_error($element, t('You must have one or more product tokens, and no other kinds of tokens in the SKU Pattern.'));
      }
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_autosku_form_commerce_product_product_form_alter(&$form, &$form_state) {
  if ($settings = commerce_autosku_get_settings($form_state['commerce_product'])) {
    $form['sku']['#required'] = FALSE;
    $form['sku']['#disabled'] = TRUE;
    if ($settings['advanced']['hide_sku']) {
      $form['sku']['#access'] = FALSE;
    }
    else {
      $form['sku']['#description'] = t('SKU will be automatically generated.');
    }
    $product = $form_state['commerce_product'];

    //@todo: See http://drupal.org/node/733332
    if (isset($form['sku']['#element_validate'])) {
      unset($form['sku']['#element_validate']);
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_autosku_form_commerce_bpc_create_bulk_form_alter(&$form, &$form_state) {
  if (!isset($form_state['commerce_product'])) {
    $form_state['commerce_product'] = $form['static_values']['#entity'];
  }
  if ($settings = commerce_autosku_get_settings($form_state['commerce_product'])) {
    $form['product']['sku_fragment']['#required'] = FALSE;
    $form['product']['sku_fragment']['#disabled'] = TRUE;
    if ($settings['advanced']['hide_sku']) {
      $form['product']['sku_fragment']['#access'] = FALSE;
    }
    else {
      $form['product']['sku_fragment']['#description'] = t('SKU will be automatically generated.');
    }
    if (isset($form['product']['sku_fragment']['#element_validate'])) {
      unset($form['product']['sku_fragment']['#element_validate']);
    }
  }
}

/**
 * Generate a random, temporary SKU to use when saving a new node.
 */
function _commerce_autosku_get_temporary_sku() {
  return 'temporary:' . mt_rand(1, 9999999);
}

/**
 * Check to see if a given SKU is one we generated.
 */
function _commerce_autosku_is_temporary_sku($sku) {
  return substr($sku, 0, 10) == 'temporary:';
}

/**
 * Check if a product needs a temporary value.
 */
function _commerce_autosku_needs_temporary_sku($product, $settings) {
  if (isset($product->is_new) && $product->is_new) {
    $tokens = token_scan($settings['pattern']);
    return isset($tokens['commerce-product']['product-id']);
  }
  return FALSE;
}

/**
 * API Helper to get AutoSKU settings for a given product.
 */
function commerce_autosku_get_settings($product) {
  $types = commerce_product_types();
  return empty($types[$product->type]['autosku']['pattern']) ? FALSE : $types[$product->type]['autosku'];
}

/**
 * Centralized storage of defaults for the advanced array.
 */
function _commerce_autosku_default_settings() {
  return array(
    'update_existing' => TRUE,
    'hide_sku' => TRUE,
    'case' => 'original',
  );
}

/**
 * API helper to reduce a SKU to a set of allowed characters.
 */
function commerce_autosku_cleanstring($string) {
  if (module_exists('transliteration')) {
    $string = transliteration_get($string);
  }
  return preg_replace(COMMERCE_AUTOSKU_DISALLOWED, COMMERCE_AUTOSKU_REPLACEMENT, $string);
}

/**
 * Implements hook_features_pipe_COMPONENT_alter().
 *
 * Add the autosku settings to the export when the product type is selected.
 */
function commerce_autosku_features_pipe_commerce_product_type_alter(&$pipe, $data, $export) {
  if ($export['component'] == 'commerce_product_type') {
    foreach ($data as $type) {
      $pipe['commerce_autosku_patterns'][] = $type;
    }
  }
}

/**
 * Generates a SKU for the product passed in using the given pattern.
 *
 * @param $product
 *   The product whose SKU should be generated.
 * @param $pattern
 *   The pattern to use to determine the product SKU.
 * @param $case
 *   String indicating the casing to use for letters in the SKU, one of:
 *   - 'original': do not change the casing used in any of the tokens.
 *   - 'uppercase': convert the SKU to all upper case letters.
 *   - 'lowercase': convert the SKU to all lower case letters.
 *
 * @return
 *   A string containing a unique SKU for the product pass in using the given
 *   pattern with a numeric suffix in the event of a pre-existing matching SKU.
 */
function commerce_autosku_generate_sku($product, $pattern, $case = 'original') {

  // Create the new SKU using token replacement, clean out illegitimate values,
  // and trim it to the maximum SKU length - 255 characters.
  $sku = token_replace($pattern, array(
    'commerce-product' => $product,
  ), array(
    'clear' => TRUE,
  ));
  $sku = commerce_autosku_cleanstring($sku);
  $sku = drupal_substr($sku, 0, 255);

  // Adjust the casing as specified.
  switch ($case) {
    case 'uppercase':
      $sku = drupal_strtoupper($sku);
      break;
    case 'lowercase':
      $sku = drupal_strtolower($sku);
      break;
  }

  // Check to ensure the current SKU is unique...
  if (!commerce_product_validate_sku_unique($sku, $product->product_id)) {

    // If not, retain the originally generated SKU and begin to append numerals
    // to it in search of a unique SKU.
    $original_sku = $sku;
    $i = 0;
    do {
      $sku = drupal_substr($original_sku, 0, 255 - drupal_strlen(COMMERCE_AUTOSKU_REPLACEMENT . $i));
      $sku = commerce_autosku_cleanstring($sku . COMMERCE_AUTOSKU_REPLACEMENT . $i);
      $i++;
    } while (!commerce_product_validate_sku_unique($sku, $product->product_id));
  }
  return $sku;
}

Functions

Namesort descending Description
commerce_autosku_cleanstring API helper to reduce a SKU to a set of allowed characters.
commerce_autosku_element_validate_sku_pattern
commerce_autosku_features_pipe_commerce_product_type_alter Implements hook_features_pipe_COMPONENT_alter().
commerce_autosku_form_commerce_bpc_create_bulk_form_alter Implements hook_form_FORM_ID_alter().
commerce_autosku_form_commerce_product_product_form_alter Implements hook_form_FORM_ID_alter().
commerce_autosku_form_commerce_product_ui_product_type_form_alter Implements hook_form_FORM_ID_alter().
commerce_autosku_generate_sku Generates a SKU for the product passed in using the given pattern.
commerce_autosku_get_settings API Helper to get AutoSKU settings for a given product.
_commerce_autosku_default_settings Centralized storage of defaults for the advanced array.
_commerce_autosku_get_temporary_sku Generate a random, temporary SKU to use when saving a new node.
_commerce_autosku_is_temporary_sku Check to see if a given SKU is one we generated.
_commerce_autosku_needs_temporary_sku Check if a product needs a temporary value.

Constants

Namesort descending Description
COMMERCE_AUTOSKU_DISALLOWED @file Module hooks and helper functions for commerce_autosku
COMMERCE_AUTOSKU_REPLACEMENT