View source
<?php
require_once drupal_get_path('module', 'webform') . '/components/select.inc';
function _webform_defaults_productfield() {
return array(
'name' => '',
'form_key' => NULL,
'mandatory' => 0,
'pid' => 0,
'weight' => 0,
'value' => '',
'extra' => array(
'items' => '',
'product_type' => '',
'multiple' => NULL,
'choose_quantity' => NULL,
'aslist' => NULL,
'optrand' => 0,
'other_option' => NULL,
'other_text' => t('Other...'),
'title_display' => 0,
'description' => '',
'custom_keys' => FALSE,
'options_source' => '',
'private' => FALSE,
),
);
}
function _webform_edit_productfield($component) {
$form = array();
$items = isset($component['extra']['items']) && is_array($component['extra']['items']) ? $component['extra']['items'] : array();
$product_ids = array();
$skus = array();
foreach ($items as $item) {
$product_ids[] = $item['product_id'];
$skus[] = $item['sku'];
}
$form['extra']['product_type'] = array(
'#type' => 'select',
'#multiple' => TRUE,
'#options' => commerce_product_type_options_list(),
'#title' => t('Product type'),
'#default_value' => $component['extra']['product_type'],
'#description' => t('Use either this OR the product skus field below. By selecting a product type here, all products of this type will be available for selection on the webform.'),
'#weight' => 4,
);
$form['extra']['items'] = array(
'#type' => 'textfield',
'#title' => t('Product skus'),
'#description' => t('Use this instead of setting a product type above. List the product skus you would like to offer as options on this webform. When the webform is saved, the user has that product added to thier basket.'),
'#default_value' => implode(', ', $skus),
'#autocomplete_path' => 'commerce_webform/autocomplete',
'#size' => 128,
'#maxlength' => 2048,
'#element_validate' => array(
'_webform_edit_validate_productfield',
),
'#weight' => 5,
);
$form['value'] = array(
'#type' => 'textfield',
'#title' => t('Default sku'),
'#default_value' => $component['value'],
'#description' => t('Enter the product sku which should be selected by default or leave blank for no default. A token can be used here, e.g. [current-page:query:sku] to retrieve it from the URL query parameter sku.'),
'#size' => 60,
'#maxlength' => 1024,
'#weight' => 3,
);
$form['extra']['choose_quantity'] = array(
'#type' => 'checkbox',
'#title' => t('Allow the user to set the quantity.'),
'#default_value' => empty($component['extra']['choose_quantity']) ? 0 : $component['extra']['choose_quantity'],
'#description' => t('Check this option if the user should be allowed to set the number of products selected. The default is 1 for single selections and 0 if it is possbile to select multiple products.'),
'#weight' => 0,
);
$form['extra']['multiple'] = array(
'#type' => 'checkbox',
'#title' => t('Multiple'),
'#default_value' => $component['extra']['multiple'],
'#description' => t('Check this option if the user should be allowed to choose multiple values.'),
'#weight' => 0,
);
$form['display']['aslist'] = array(
'#type' => 'checkbox',
'#title' => t('Listbox'),
'#default_value' => $component['extra']['aslist'],
'#description' => t('Check this option if you want the select component to be of listbox type instead of radio buttons or checkboxes.'),
'#weight' => 0,
'#parents' => array(
'extra',
'aslist',
),
);
return $form;
}
function _webform_edit_validate_productfield($element, &$form_state) {
if (!empty($element['#value'])) {
$typed_skus = drupal_explode_tags($element['#value']);
$value = array();
foreach ($typed_skus as $typed_sku) {
if ($product = commerce_product_load_by_sku(trim($typed_sku))) {
$value[$product->product_id] = array(
'product_id' => $product->product_id,
'title' => $product->title,
'sku' => $product->sku,
'type' => $product->type,
);
}
}
}
else {
$value = array();
}
form_set_value($element, $value, $form_state);
}
function _webform_render_productfield($component, $value = NULL, $filter = TRUE) {
$node = isset($component['nid']) ? node_load($component['nid']) : NULL;
$product_ids = _webform_productfield_product_ids($component);
return array(
'#type' => 'webform_productfield',
'#choose_quantity' => !empty($component['extra']['choose_quantity']),
'#multiple' => !empty($component['extra']['multiple']),
'#productids' => $product_ids,
'#required' => !empty($component['required']),
'#default_value' => isset($value) ? $value : _webform_filter_values($component['value'], NULL, NULL, NULL, FALSE),
'#weight' => $component['weight'],
'#aslist' => !empty($component['extra']['aslist']),
'#name' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
'#description' => $filter ? _webform_filter_descriptions($component['extra']['description'], $node) : $component['extra']['description'],
'#title_display' => $component['extra']['title_display'],
'#theme_wrappers' => array(
'webform_element',
),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'commerce_webform') . '/commerce_webform.js',
),
),
);
}
function _commerce_webform_productfield_expand($element) {
$element += element_info('webform_productfield');
$product_ids = empty($element['#productids']) ? array() : $element['#productids'];
$choose_quantity = !empty($element['#choose_quantity']);
$required = !empty($element['#required']);
$value = $element['#default_value'];
$aslist = !empty($element['#aslist']);
$multiple = !empty($element['#multiple']);
$name = $element['#name'];
$description = $element['#description'];
$title_display = !empty($element['#title_display']) ? $element['#title_display'] : 'before';
$hidden_elements_html = '';
$options = array();
if (!$multiple) {
$options[''] = ' - ' . ($required ? t('Select') : t('None')) . ' - ';
}
$products = commerce_product_load_multiple($product_ids);
foreach ($products as $product) {
if ($product->status == 1) {
$price = commerce_product_calculate_sell_price($product);
$options[$product->product_id] = theme('commerce_webform_product_display', array(
'product' => $product,
'price' => $price,
'element' => $element,
));
$hidden_elements_html .= "<input type='hidden' name='commerce_webform_product[{$product->product_id}]' value='{$price['amount']}' />\n";
}
}
$default_product_ids = $multiple ? array() : 0;
$default_quantities = $multiple ? array() : 1;
$disabled = FALSE;
if (is_array($value)) {
foreach ($value as $id => $encoded_details) {
$details = json_decode($encoded_details);
if ($details->paid && !user_access('alter product field on paid webform')) {
$disabled = TRUE;
}
if ($multiple) {
$default_product_ids[] = $details->product_id;
if ($choose_quantity) {
$default_quantities[$details->product_id] = $details->quantity;
}
else {
$default_quantities = $details->quantity;
}
}
else {
$default_product_ids = $details->product_id;
$default_quantities = $details->quantity;
}
}
}
elseif (!empty($value)) {
$defaults = explode(',', $value);
foreach ($defaults as $default) {
$product = commerce_product_load_by_sku(trim($default));
if (!empty($product) && array_key_exists($product->product_id, $options)) {
if ($multiple) {
$default_product_ids[] = $product->product_id;
$default_quantities[$product->product_id] = 1;
}
else {
$default_product_ids = $product->product_id;
}
}
}
}
if (!$multiple || !$choose_quantity) {
if ($disabled) {
$rows = array();
$element[] = array(
'#type' => 'value',
'#value' => $default_product_ids,
);
$element[] = array(
'#type' => 'value',
'#value' => $default_quantities,
);
if (is_array($default_product_ids)) {
foreach ($default_product_ids as $product_id) {
$rows[] = array(
$product_id,
$options[$product_id],
$default_quantities,
);
}
}
elseif ($default_product_ids > 0) {
$rows[] = array(
$default_product_ids,
$options[$default_product_ids],
$default_quantities,
);
}
$element['#markup'] = '<strong>' . $name . '</strong>';
$element['#markup'] .= theme('table', array(
'header' => array(
t('Product ID'),
t('Product name'),
t('Quantity'),
),
'rows' => $rows,
));
$element['#markup'] .= '<p>' . t('This order has been completed and products choices cannot be edited online.') . '</p>';
}
else {
$element[] = array(
'#type' => $aslist ? 'select' : ($multiple ? 'checkboxes' : 'radios'),
'#multiple' => $multiple,
'#size' => $aslist && $multiple ? 4 : 0,
'#title' => $name,
'#title_display' => $title_display,
'#required' => $required,
'#description' => $description,
'#translatable' => array(
'title',
'description',
'options',
),
'#options' => $options,
'#default_value' => $default_product_ids,
'#suffix' => $hidden_elements_html,
'#pre_render' => array(),
'#element_validate' => array(
'_webform_productfield_selection_validate',
),
);
$editable = empty($multiple) && !empty($choose_quantity);
$element[] = array(
'#type' => $editable ? 'textfield' : 'value',
'#title' => t('@product quantity', array(
'@product' => $name,
)),
'#default_value' => $choose_quantity ? is_array($default_quantities) ? 1 : $default_quantities : 1,
'#element_validate' => array(
'_webform_productfield_quantity_validate',
),
'#required' => $required,
'#weight' => 1,
'#attributes' => array(
'class' => array(
'productfield-quantity',
),
),
);
}
}
else {
$i = 1;
if ($disabled) {
$rows = array();
foreach ($default_quantities as $product_id => $quantity) {
$element[$product_id] = array(
'#type' => 'value',
'#value' => $quantity,
);
$rows[] = array(
$product_id,
$options[$product_id],
$quantity,
);
}
$element['#markup'] = '<strong>' . $name . '</strong>';
$element['#markup'] .= theme('table', array(
'header' => array(
t('Product ID'),
t('Product name'),
t('Quantity'),
),
'rows' => $rows,
));
$element['#markup'] .= '<p>' . t('This order has been completed and products choices cannot be edited online.') . '</p>';
}
else {
$element['multiple_product_quantities'] = array(
'#type' => 'fieldset',
'#title' => $name,
'#title_display' => $title_display,
'#element_validate' => array(
'_webform_productfield_required_multiple_quantities_validate',
),
'#required' => $required,
'#weight' => 0,
'#pre_render' => array(
'webform_element_title_display',
),
);
foreach ($options as $product_id => $product_name) {
$element['multiple_product_quantities'][$product_id] = array(
'#type' => 'textfield',
'#title' => $product_name,
'#title_display' => 'after',
'#size' => 2,
'#default_value' => isset($default_quantities[$product_id]) ? $default_quantities[$product_id] : 0,
'#element_validate' => array(
'_webform_productfield_quantity_validate',
),
'#weight' => $i++,
);
}
}
}
return $element;
}
function _webform_display_productfield($component, $value, $format = 'html') {
$options = array();
foreach ($component['extra']['items'] as $product_id => $details) {
$options[$product_id] = "{$details['sku']}: {$details['title']} ";
}
return array(
'#title' => $component['name'],
'#weight' => $component['weight'],
'#theme' => 'webform_display_productfield',
'#theme_wrappers' => $format == 'html' ? array(
'webform_element',
) : array(
'webform_element_text',
),
'#format' => $format,
'#options' => $options,
'#value' => (array) $value,
'#translatable' => array(
'title',
'options',
),
);
}
function _webform_submit_productfield($component, $value) {
$return = array();
$multiple = $component['extra']['multiple'];
$choose_quantity = !empty($component['extra']['choose_quantity']);
if ($multiple && $choose_quantity) {
foreach ($value['multiple_product_quantities'] as $product_id => $quantity) {
if ($quantity > 0) {
$details = array(
'product_id' => $product_id,
'quantity' => $quantity,
'order_id' => FALSE,
'line_item_id' => FALSE,
'paid' => FALSE,
);
$return[] = json_encode($details);
}
}
}
else {
if (is_array($value[0])) {
foreach ($value[0] as $id => $product_id) {
$details = array(
'product_id' => $product_id,
'quantity' => 1,
'order_id' => FALSE,
'line_item_id' => FALSE,
'paid' => FALSE,
);
$return[] = json_encode($details);
}
}
else {
$details = array(
'product_id' => $value[0],
'quantity' => empty($value[0]) ? '0' : $value[1],
'order_id' => FALSE,
'line_item_id' => FALSE,
'paid' => FALSE,
);
$return[] = json_encode($details);
}
}
return $return;
}
function theme_webform_display_productfield($variables) {
$element = $variables['element'];
$options = $element['#options'];
$items = array();
foreach ($element['#value'] as $value) {
$value = json_decode($value);
if (!empty($value->product_id)) {
if (isset($options[$value->product_id])) {
$paid_display_option = empty($value->paid) ? t('Unpaid') : t('Paid');
$paid_display_option = empty($value->order_id) ? $paid_display_option : l($paid_display_option, "admin/commerce/orders/{$value->order_id}/view");
$name = _webform_filter_xss($options[$value->product_id]);
$items[] = "{$value->quantity} x {$name} (<strong>{$paid_display_option}</strong>)";
}
else {
$items[] = check_plain($value->product_id);
}
}
}
if ($element['#format'] == 'html') {
$output = count($items) > 1 ? theme('item_list', array(
'items' => $items,
)) : (isset($items[0]) ? $items[0] : t('Not selected'));
}
else {
if (count($items) > 1) {
foreach ($items as $key => $item) {
$items[$key] = ' - ' . $item;
}
$output = implode("\n", $items);
}
else {
$output = isset($items[0]) ? $items[0] : t('Not selected');
}
}
return $output;
}
function _webform_analysis_productfield($component, $sids = array(), $single = FALSE) {
$query = db_select('webform_submitted_data', 'wsd', array(
'fetch' => PDO::FETCH_ASSOC,
))
->fields('wsd', array(
'data',
))
->condition('nid', $component['nid'])
->condition('cid', $component['cid'])
->condition('data', '', '<>')
->groupBy('data');
if (count($sids)) {
$query
->condition('sid', $sids, 'IN');
}
$results = $query
->execute();
$rows = array();
foreach ($results as $result) {
$submission = json_decode($result['data']);
if (isset($component['extra']['items'][$submission->product_id])) {
$display_option = _webform_filter_xss($component['extra']['items'][$submission->product_id]['title']);
$paid_display_option = !empty($submission->paid) ? 'Paid' : 'Unpaid';
if (isset($rows[$submission->product_id . '_' . $paid_display_option])) {
$rows[$submission->product_id . '_' . $paid_display_option]++;
}
else {
$rows[$submission->product_id . '_' . $paid_display_option] = array(
$display_option . ' (' . _webform_filter_xss(t($paid_display_option)) . ')',
1,
);
}
}
}
return $rows;
}
function _webform_table_productfield($component, $value) {
$options = $component['extra']['items'];
$value = (array) $value;
$items = array();
foreach ($value as $option_value) {
$option_value = json_decode($option_value);
if (!empty($option_value->product_id)) {
if (isset($options[$option_value->product_id])) {
$item = $option_value->quantity . ' x ' . _webform_filter_xss($options[$option_value->product_id]['title']);
}
else {
$item = check_plain($option_value->product_id);
}
$paid_display_option = empty($option_value->paid) ? t('Unpaid') : t('Paid');
$paid_display_option = empty($option_value->order_id) ? $paid_display_option : l($paid_display_option, "admin/commerce/orders/{$option_value->order_id}/view");
$item .= " (<strong>{$paid_display_option}</strong>)";
$items[] = $item;
}
}
return implode('<br />', $items);
}
function _webform_csv_headers_productfield($component, $export_options) {
$options = $component['extra']['items'];
$headers = array(
0 => array(),
1 => array(),
2 => array(),
);
$headers[0][] = '';
$headers[1][] = '';
foreach ($options as $product_id => $details) {
$headers[2][] = $details['sku'] . ': PAID';
$headers[2][] = $details['sku'] . ': UNPAID';
}
return $headers;
}
function _webform_csv_data_productfield($component, $export_options, $values) {
$options = $component['extra']['items'];
foreach ($values as $id => $value) {
$values[$id] = json_decode($value);
}
$return = array();
foreach ($options as $key => $item) {
$index = FALSE;
foreach ($values as $value) {
if ($value->product_id == $key) {
$index = $value;
}
}
if ($index !== FALSE) {
if (!empty($index->paid)) {
$return[] = $index->quantity;
$return[] = '0';
}
else {
$return[] = '0';
$return[] = $index->quantity;
}
}
else {
$return[] = '0';
$return[] = '0';
}
}
return $return;
}
function _webform_productfield_quantity_validate($element, &$form_state, $form) {
$value = $form_state['values'];
foreach ($element['#parents'] as $parent) {
$value = $value[$parent];
}
$name = implode('][', $element['#parents']);
if (!isset($value) || empty($value)) {
$value = 0;
}
if (!is_numeric($value)) {
form_set_error($name, 'Quantity must be a number.');
}
elseif ($element['#required'] && $value < 1) {
form_set_error($name, 'Quantity must be greater than 0.');
}
elseif ($element['#required'] && $value < 0) {
form_set_error($name, 'Quantity must be a positive number or 0.');
}
}
function _webform_productfield_selection_validate($element, &$form_state, $form) {
if ($element['#required'] && $element['#multiple'] == '0') {
$value = $form_state['values'];
$name = '';
foreach ($element['#parents'] as $index => $container) {
$value = $value[$container];
$name .= !empty($name) ? '][' : '';
$name .= $element['#parents'][$index];
}
if (!isset($value[0]) || $value[0] < 1) {
form_set_error($name, t('!name field is required', array(
'!name' => $element['#title'],
)));
}
}
}
function _webform_productfield_required_multiple_quantities_validate($element, &$form_state, $form) {
if ($element['#required']) {
$value = $form_state['values'];
foreach ($element['#parents'] as $parent) {
$value = $value[$parent];
}
foreach ($value as $product_id => $quantity) {
if ($quantity > 0) {
return;
}
}
$name = implode('][', $element['#parents']);
form_set_error($name, t('You must choose at least one product from this selection by setting its quantity to something greater than 1'));
}
}
function theme_commerce_webform_product_display($variables) {
$product = $variables['product'];
$price = $variables['price'];
return filter_xss($product->title) . ' [' . commerce_currency_format($price['amount'], $price['currency_code'], $product) . ']';
}
function _webform_productfield_product_ids_from_type($product_type) {
$products_ids = array();
$query = new EntityFieldQuery();
$result = $query
->entityCondition('entity_type', 'commerce_product')
->entityCondition('bundle', $product_type)
->execute();
if (!empty($result['commerce_product'])) {
$product_ids = array_keys($result['commerce_product']);
}
return $product_ids;
}
function _webform_productfield_product_ids($component) {
$items = isset($component['extra']['items']) ? $component['extra']['items'] : array();
$product_type = isset($component['extra']['product_type']) ? $component['extra']['product_type'] : '';
$product_ids = array();
if (!empty($product_type)) {
$product_ids = _webform_productfield_product_ids_from_type($product_type);
}
else {
foreach ($items as $item) {
$product_ids[] = $item['product_id'];
}
}
return $product_ids;
}
function _commerce_webform_conditional_operator_info() {
$operators = array();
$operators['productfield']['product_is'] = array(
'label' => t('is a product'),
'comparison callback' => 'webform_conditional_operator_product_is',
'js comparison callback' => 'conditionalOperatorProductEqual',
'form callback' => 'commerce_webform_conditional_product_select',
);
$operators['productfield']['product_is_not'] = array(
'label' => t('is not a product'),
'comparison callback' => 'webform_conditional_operator_product_is_not',
'js comparison callback' => 'conditionalOperatorProductNotEqual',
'form callback' => 'commerce_webform_conditional_product_select',
);
$operators['productfield']['product_is_of_type'] = array(
'label' => t('is a product of type'),
'comparison callback' => 'webform_conditional_operator_product_is_of_type',
'js comparison callback' => 'conditionalOperatorProductOfType',
'form callback' => 'commerce_webform_conditional_product_type_select',
'comparison prepare js' => 'webform_conditional_prepare_productfield_type_js',
);
$operators['productfield']['product_is_not_of_type'] = array(
'label' => t('is not a product of type'),
'comparison callback' => 'webform_conditional_operator_product_is_not_of_type',
'js comparison callback' => 'conditionalOperatorProductNotOfType',
'form callback' => 'commerce_webform_conditional_product_type_select',
'comparison prepare js' => 'webform_conditional_prepare_productfield_type_js',
);
$operators['productfield']['quantity_equals'] = array(
'label' => t('total quantity is equal to'),
'comparison callback' => 'webform_conditional_operator_product_quantity_equals',
'js comparison callback' => 'conditionalOperatorProductQuantityEquals',
);
$operators['productfield']['quantity_less_than'] = array(
'label' => t('total quantity is less than'),
'comparison callback' => 'webform_conditional_operator_product_quantity_less_than',
'js comparison callback' => 'conditionalOperatorProductQuantityLessThan',
);
$operators['productfield']['quantity_greater_than'] = array(
'label' => t('total quantity is greater than'),
'comparison callback' => 'webform_conditional_operator_product_quantity_greater_than',
'js comparison callback' => 'conditionalOperatorProductQuantityGreaterThan',
);
return $operators;
}
function webform_conditional_prepare_productfield_type_js($rule_value) {
return _webform_productfield_product_ids_from_type($rule_value);
}
function commerce_webform_conditional_product_select($node) {
$forms = array();
webform_component_include('productfield');
foreach ($node->webform['components'] as $cid => $component) {
if (webform_component_property($component['type'], 'conditional_type') == 'productfield') {
$options = array();
$product_ids = _webform_productfield_product_ids($component);
$products = commerce_product_load_multiple($product_ids);
foreach ($products as $id => $product) {
$options[$product->product_id] = $product->title;
}
$element = array(
'#type' => 'select',
'#multiple' => FALSE,
'#size' => NULL,
'#attributes' => array(),
'#id' => NULL,
'#name' => NULL,
'#options' => $options,
'#parents' => array(),
);
$forms[$cid] = drupal_render($element);
}
}
return $forms;
}
function commerce_webform_conditional_product_type_select($node) {
$forms = array();
webform_component_include('productfield');
foreach ($node->webform['components'] as $cid => $component) {
if (webform_component_property($component['type'], 'conditional_type') == 'productfield') {
$options = commerce_product_type_options_list();
$element = array(
'#type' => 'select',
'#multiple' => FALSE,
'#size' => NULL,
'#attributes' => array(),
'#id' => NULL,
'#name' => NULL,
'#options' => $options,
'#parents' => array(),
);
$forms[$cid] = drupal_render($element);
}
}
return $forms;
}
function webform_conditional_operator_product_is($input_values, $rule_value) {
$selected_products = _commerce_webform_get_selected_products_from_input_values($input_values);
foreach ($selected_products as $product_id => $quantity) {
if ($quantity > 0 && $product_id == $rule_value) {
return TRUE;
}
}
return FALSE;
}
function webform_conditional_operator_product_is_not($input_values, $rule_value) {
return !webform_conditional_operator_product_is($input_values, $rule_value);
}
function webform_conditional_operator_product_quantity_equals($input_values, $rule_value) {
return _commerce_webform_get_total_quantity_from_input_values($input_values) == $rule_value;
}
function webform_conditional_operator_product_quantity_less_than($input_values, $rule_value) {
return _commerce_webform_get_total_quantity_from_input_values($input_values) < $rule_value;
}
function webform_conditional_operator_product_quantity_greater_than($input_values, $rule_value) {
return _commerce_webform_get_total_quantity_from_input_values($input_values) > $rule_value;
}
function webform_conditional_operator_product_is_of_type($input_values, $rule_value) {
$selected_products = _commerce_webform_get_selected_products_from_input_values($input_values);
foreach ($selected_products as $product_id => $quantity) {
if ($quantity > 0) {
$product = commerce_product_load($product_id);
if ($product->type == $rule_value) {
return TRUE;
}
}
}
return FALSE;
}
function webform_conditional_operator_product_is_not_of_type($input_values, $rule_value) {
return !webform_conditional_operator_product_is_of_type($input_values, $rule_value);
}
function _commerce_webform_get_selected_products_from_input_values(array $input_values) {
if (!empty($input_values['multiple_product_quantities'])) {
return $input_values['multiple_product_quantities'];
}
$selected_products = array();
if (is_array($input_values[0])) {
foreach ($input_values[0] as $product_id) {
if ($product_id > 0) {
$selected_products[$product_id] = 1;
}
}
}
else {
$selected_products[$input_values[0]] = $input_values[1];
}
return $selected_products;
}
function _commerce_webform_get_total_quantity_from_input_values($input_values) {
$selected_products = _commerce_webform_get_selected_products_from_input_values($input_values);
$total = 0;
foreach ($selected_products as $product_id => $quantity) {
$total += $quantity;
}
return $total;
}