You are here

function _uc_attribute_alter_form in Ubercart 8.4

Same name and namespace in other branches
  1. 5 uc_attribute/uc_attribute.module \_uc_attribute_alter_form()
  2. 6.2 uc_attribute/uc_attribute.module \_uc_attribute_alter_form()
  3. 7.3 uc_attribute/uc_attribute.module \_uc_attribute_alter_form()

Helper function for uc_attribute_form_alter().

Parameters

$id: The unique id to use to wrap these form elements.

&$product: The product node for which the attribute form elements are to be attached.

bool $use_ajax: TRUE to add ajax to the form. Note that ajax may be added even if this is FALSE, if there are multiple attributes and one or more of them is set to display total price.

Return value

array Form API array with attribute elements to add to the product form.

See also

uc_attribute_option_ajax()

2 calls to _uc_attribute_alter_form()
hook_uc_form_alter in uc_store/uc_store.api.php
Allows modules to modify forms before Drupal invokes hook_form_alter().
uc_attribute_uc_form_alter in uc_attribute/uc_attribute.module
Implements hook_uc_form_alter().

File

uc_attribute/uc_attribute.module, line 1178
Ubercart Attribute module.

Code

function _uc_attribute_alter_form($id, &$product, $use_ajax) {

  // If the product doesn't have attributes, return the form as it is.
  if (empty($product->attributes) || !is_array($product->attributes)) {
    return [];
  }
  $nid = $product
    ->id();
  $attributes = $product->attributes;
  $priced_attributes = uc_attribute_priced_attributes($nid);

  // If the form is being built for the first time, populate attributes
  // with their default values.
  if (!isset($product->data['attributes'])) {
    $values = [];
    foreach ($priced_attributes as $aid) {
      if (!$attributes[$aid]->required && ($attributes[$aid]->display == 1 || $attributes[$aid]->display == 2)) {
        $values[$aid] = $attributes[$aid]->default_option;
      }
    }
    if (!empty($values)) {
      $data = $product->data;
      $data['attributes'] = $values;
      if (isset($product->qty)) {

        // Preserve the quantity (for product-kit sub-products).
        $qty = $product->qty;
      }
      $product = uc_product_load_variant($product
        ->id(), $data);
      if (isset($qty)) {
        $product->qty = $qty;
      }
    }
  }
  if (empty($product->data) || !is_array($product->data)) {
    $product->data = [];
  }

  // Initialize the form element.
  $form_attributes = [
    '#type' => 'container',
    '#attributes' => [
      'id' => $id,
      'class' => [
        'product-attributes',
      ],
    ],
  ];
  $price_format = \Drupal::config('uc_attribute.settings')
    ->get('option_price_format');

  // Loop through each product attribute and generate its form element.
  foreach ($attributes as $attribute) {

    // Build the attribute's options array.
    $options = [];
    foreach ($attribute->options as $option) {
      $display_price = '';
      if (in_array($attribute->aid, $priced_attributes)) {
        $data = [
          'display_only' => TRUE,
        ] + $product->data;
        if (empty($data['attributes'])) {
          $data['attributes'] = [];
        }
        switch ($price_format) {
          case 'total':

            // Only display total price for non-checkbox options.
            // @todo Fix attribute option total price display for product kits.
            if ($attribute->display != 3 && !isset($product->data['kit_id'])) {
              $use_ajax = $use_ajax || count($priced_attributes) > 1;
              $data['attributes'] = [
                $attribute->aid => $option->oid,
              ] + $data['attributes'];
              $variant = uc_product_load_variant($product
                ->id(), $data);
              $display_price = uc_currency_format($variant->display_price);
              break;
            }
          case 'adjustment':
            if ($attribute->display == 3 || !$use_ajax) {

              // For checkboxes, or if the node totals are not being updated,
              // we compare this attribute against base price.
              if (empty($base)) {

                // Only build the base once.
                unset($data['attributes']);
                $base = uc_product_load_variant($product
                  ->id(), $data);
              }
              $data['attributes'] = [
                $attribute->aid => $option->oid,
              ];
              $variant = uc_product_load_variant($product
                ->id(), $data);
              $adjustment = $variant->display_price - $base->display_price;
            }
            else {

              // Otherwise we compare against current total price.
              if (empty($selected)) {
                $selected = uc_product_load_variant($product
                  ->id(), $data);
              }
              $data['attributes'] = [
                $attribute->aid => $option->oid,
              ] + $data['attributes'];
              $variant = uc_product_load_variant($product
                ->id(), $data);
              $adjustment = $variant->display_price - $selected->display_price;
            }
            if ($adjustment != 0) {
              $display_price = $adjustment > 0 ? '+' : '-';
              $display_price .= uc_currency_format(abs($adjustment));
            }
            break;
        }
      }

      // Select options are sanitized, but radio button labels are not.
      $build = [
        '#theme' => 'uc_attribute_option',
        '#option' => $attribute->display == 2 ? SafeMarkup::checkPlain($option->name) : $option->name,
        '#price' => $display_price,
      ];
      $options[$option->oid] = drupal_render($build);
    }
    if (count($attribute->options) && $attribute->display > 0) {
      if ($attribute->required) {
        if ($attribute->display == 1) {
          $options = [
            '' => t('Please select'),
          ] + $options;
        }
        $attribute->default_option = NULL;
      }
      $attr_type = '';
      switch ($attribute->display) {
        case 1:
          $attr_type = 'select';
          break;
        case 2:
          $attr_type = 'radios';
          break;
        case 3:
          $attr_type = 'checkboxes';
          $attribute->default_option = [];
          break;
      }
      $form_attributes[$attribute->aid] = [
        '#type' => $attr_type,
        '#default_value' => $attribute->default_option,
        '#options' => $options,
      ];
      if ($use_ajax) {
        $form_attributes[$attribute->aid]['#ajax'] = [
          'callback' => 'uc_attribute_option_ajax',
          'wrapper' => $id,
        ];
      }
    }
    elseif ($attribute->display > 0) {
      $form_attributes[$attribute->aid] = [
        '#type' => 'textfield',
        '#default_value' => '',
      ];
      if (!$attribute->required && isset($attribute->options[$attribute->default_option])) {
        $form_attributes[$attribute->aid]['#default_value'] = $attribute->options[$attribute->default_option]->name;
      }
    }
    else {
      $form_attributes[$attribute->aid] = [
        '#type' => 'textfield',
        '#default_value' => '',
      ];
    }
    $name = _uc_attribute_get_name($attribute, FALSE);
    if (!is_null($name)) {
      $form_attributes[$attribute->aid]['#title'] = SafeMarkup::checkPlain($name);
    }
    $form_attributes[$attribute->aid]['#description'] = Xss::filter($attribute->description);
    $form_attributes[$attribute->aid]['#required'] = $attribute->required;
  }
  return $form_attributes;
}