View source
<?php
define('BAT_OPTIONS_ADD', 'add');
define('BAT_OPTIONS_ADD_DAILY', 'add-daily');
define('BAT_OPTIONS_SUB', 'sub');
define('BAT_OPTIONS_SUB_DAILY', 'sub-daily');
define('BAT_OPTIONS_ADD_PERSON', 'add_person');
define('BAT_OPTIONS_ADD_DAILY_PERSON', 'add-daily_person');
define('BAT_OPTIONS_SUB_PERSON', 'sub_person');
define('BAT_OPTIONS_SUB_DAILY_PERSON', 'sub-daily_person');
define('BAT_OPTIONS_REPLACE', 'replace');
define('BAT_OPTIONS_INCREASE', 'increase');
define('BAT_OPTIONS_DECREASE', 'decrease');
define('BAT_OPTIONS_NOCHARGE', 'no_charge');
define('BAT_OPTIONS_OPTIONAL', 'optional');
define('BAT_OPTIONS_MANDATORY', 'mandatory');
define('BAT_OPTIONS_ONREQUEST', 'on_request');
function bat_options_menu() {
$items['bat_options/ajax'] = array(
'title' => 'Remove item callback',
'page callback' => 'bat_options_remove_js',
'delivery callback' => 'ajax_deliver',
'access callback' => TRUE,
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
'file path' => 'includes',
'file' => 'form.inc',
);
return $items;
}
function bat_options_field_info() {
return array(
'bat_options' => array(
'label' => t('BAT Type Options'),
'description' => t('BAT Type Options.'),
'settings' => array(),
'default_widget' => 'bat_options_combined',
'default_formatter' => 'bat_options_default',
'property_type' => 'bat_options',
'property_callbacks' => array(
'bat_options_property_info_callback',
),
),
);
}
function bat_options_property_info_callback(&$info, $entity_type, $field, $instance, $field_type) {
entity_metadata_field_default_property_callback($info, $entity_type, $field, $instance, $field_type);
$name = $field['field_name'];
$property =& $info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
$property['type'] = $field['cardinality'] != 1 ? 'list<bat_options>' : 'bat_options';
$property['property info'] = bat_options_data_property_info('Type options');
$property['getter callback'] = 'entity_metadata_field_verbatim_get';
$property['setter callback'] = 'entity_metadata_field_verbatim_set';
}
function bat_options_data_property_info($name = NULL) {
$properties = array(
'name' => array(
'label' => 'Name',
'type' => 'text',
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
),
'quantity' => array(
'label' => 'Quantity',
'type' => 'integer',
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
),
'operation' => array(
'label' => 'Operation',
'type' => 'text',
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
),
'value' => array(
'label' => 'Value',
'type' => 'integer',
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
),
'type' => array(
'label' => 'Type',
'type' => 'text',
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
),
);
foreach ($properties as &$value) {
$value += array(
'description' => !empty($name) ? t('!label of field %name', array(
'!label' => $value['label'],
'%name' => $name,
)) : '',
);
}
return $properties;
}
function bat_options_field_is_empty($item, $field) {
$per_person = isset($field['settings']['per_person']) ? $field['settings']['per_person'] : FALSE;
return empty($item['name']) || empty($item['quantity']) || !(is_numeric($item['quantity']) && is_int((int) $item['quantity'])) || (empty($item['value']) || !is_numeric($item['value'])) && $item['operation'] != 'no_charge' || empty($item['operation']) || !in_array($item['operation'], array_keys(bat_options_price_options($per_person)));
}
function bat_options_field_widget_info() {
return array(
'bat_options_combined' => array(
'label' => t('Combined text field'),
'field types' => array(
'bat_options',
),
'settings' => array(),
),
);
}
function bat_options_field_formatter_info() {
return array(
'bat_options_default' => array(
'label' => t('BAT Options Default'),
'field types' => array(
'bat_options',
),
),
'bat_options_price' => array(
'label' => t('BAT Options Price'),
'field types' => array(
'bat_options',
),
),
'bat_options_admin' => array(
'label' => t('BAT Options Administrator'),
'field types' => array(
'bat_options',
),
),
);
}
function bat_options_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
case 'bat_options_default':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#markup' => "{$item['quantity']} x {$item['name']}",
);
}
break;
case 'bat_options_price':
$currency_setting = commerce_currency_load(commerce_default_currency());
$currency_symbol = $currency_setting['symbol'];
foreach ($items as $delta => $item) {
$price = t('@currency_symbol@amount', array(
'@currency_symbol' => $currency_symbol,
'@amount' => number_format($item['value'], 2, '.', ''),
));
if ($item['value'] > 0) {
$element[$delta] = array(
'#markup' => "{$item['quantity']} x {$item['name']} - {$price}",
);
}
else {
$element[$delta] = array(
'#markup' => "{$item['quantity']} x {$item['name']}",
);
}
}
break;
case 'bat_options_admin':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#markup' => "{$item['quantity']} x {$item['name']} - {$item['operation']} {$item['value']}",
);
}
break;
}
return $element;
}
function bat_options_field_settings_form($field, $instance, $has_data) {
$settings = $field['settings'];
$form = array();
$form['per_person'] = array(
'#type' => 'checkbox',
'#title' => t('Enable "Per person" options'),
'#default_value' => isset($settings['per_person']) ? $settings['per_person'] : 0,
);
return $form;
}
function bat_options_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
if ($instance['widget']['type'] == 'bat_options_combined') {
$field_parents = $element['#field_parents'];
$field_name = $element['#field_name'];
$language = $element['#language'];
$parents = array_merge($field_parents, array(
$field_name,
$language,
$delta,
));
$element['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#default_value' => isset($items[$delta]['name']) ? $items[$delta]['name'] : NULL,
'#attributes' => array(
'class' => array(
'bat_options-option--name',
),
),
);
$element['quantity'] = array(
'#type' => 'select',
'#title' => t('Quantity'),
'#options' => drupal_map_assoc(range(1, 10, 1)),
'#default_value' => isset($items[$delta]['quantity']) ? $items[$delta]['quantity'] : NULL,
'#description' => t('How many of this add-on should be available'),
'#attributes' => array(
'class' => array(
'bat_options-option--quantity',
),
),
);
$per_person = isset($field['settings']['per_person']) ? $field['settings']['per_person'] : FALSE;
$price_options = bat_options_price_options($per_person);
$element['operation'] = array(
'#type' => 'select',
'#title' => t('Operation'),
'#options' => $price_options,
'#default_value' => isset($items[$delta]['operation']) ? $items[$delta]['operation'] : NULL,
'#attributes' => array(
'class' => array(
'bat_options-option--operation',
),
),
);
$element['value'] = array(
'#type' => 'textfield',
'#title' => t('Value'),
'#size' => 10,
'#default_value' => isset($items[$delta]['value']) && $items[$delta]['value'] != 0 ? $items[$delta]['value'] : NULL,
'#element_validate' => array(
'bat_options_element_value_validate',
),
'#attributes' => array(
'class' => array(
'bat_options-option--value',
),
),
'#states' => array(
'disabled' => array(
':input[name="field_addons[en][' . $delta . '][operation]"]' => array(
'value' => 'no_charge',
),
),
),
);
$type_options = array(
BAT_OPTIONS_OPTIONAL => t('Optional'),
BAT_OPTIONS_MANDATORY => t('Mandatory'),
BAT_OPTIONS_ONREQUEST => t('On Request'),
);
$element['type'] = array(
'#type' => 'select',
'#title' => t('Type'),
'#options' => $type_options,
'#default_value' => isset($items[$delta]['type']) ? $items[$delta]['type'] : 'optional',
'#attributes' => array(
'class' => array(
'bat_options-option--type',
),
),
);
$element['remove'] = array(
'#delta' => $delta,
'#name' => implode('_', $parents) . '_remove_button',
'#type' => 'submit',
'#value' => t('Remove'),
'#validate' => array(),
'#submit' => array(
'bat_options_remove_submit',
),
'#limit_validation_errors' => array(),
'#ajax' => array(
'path' => 'bat_options/ajax',
'effect' => 'fade',
),
'#attributes' => array(
'class' => array(
'bat_options-option--remove-button',
),
),
);
$element['#attached']['css'] = array(
drupal_get_path('module', 'bat_options') . '/css/bat_options_widget.css',
);
return $element;
}
}
function bat_options_element_value_validate($element, &$form_state) {
$value = $element['#value'];
if ($value == '') {
form_set_value($element, 0, $form_state);
}
elseif (!is_numeric($value) || $value <= 0) {
form_error($element, t('%name must be a positive number.', array(
'%name' => $element['#title'],
)));
}
}
function bat_options_remove_js() {
if (isset($_POST['ajax_html_ids'])) {
unset($_POST['ajax_html_ids']);
}
list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form();
drupal_process_form($form['#form_id'], $form, $form_state);
$button = $form_state['triggering_element'];
$element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -3));
$commands[] = ajax_command_replace('#' . $element['#id'], drupal_render($element));
$return = array(
'#type' => 'ajax',
'#commands' => $commands,
);
$messages = theme('status_messages');
if ($messages) {
$return['#commands'][] = ajax_command_prepend('#' . $element['#id'], $messages);
}
return $return;
}
function bat_options_remove_submit($form, &$form_state) {
$button = $form_state['triggering_element'];
$delta = $button['#delta'];
$address = array_slice($button['#array_parents'], 0, -2);
$parent_element = drupal_array_get_nested_value($form, $address);
$field_name = $parent_element['#field_name'];
$langcode = $parent_element['#language'];
$parents = $parent_element['#field_parents'];
$field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
for ($i = $delta; $i <= $field_state['items_count']; $i++) {
$old_element_address = array_merge($address, array(
$i + 1,
));
$new_element_address = array_merge($address, array(
$i,
));
$moving_element = drupal_array_get_nested_value($form, $old_element_address);
$moving_element_value = drupal_array_get_nested_value($form_state['values'], $old_element_address);
$moving_element_input = drupal_array_get_nested_value($form_state['input'], $old_element_address);
$moving_element_field = drupal_array_get_nested_value($form_state['field'], $old_element_address);
$moving_element['#parents'] = $new_element_address;
form_set_value($moving_element, $moving_element_value, $form_state);
drupal_array_set_nested_value($form_state['input'], $moving_element['#parents'], $moving_element_input);
drupal_array_set_nested_value($form_state['field'], $moving_element['#parents'], $moving_element_field);
}
if ($field_state['items_count'] > 0) {
$field_state['items_count']--;
}
$input = drupal_array_get_nested_value($form_state['input'], $address);
uasort($input, '_field_sort_items_helper');
$weight = -1 * $field_state['items_count'];
foreach ($input as $key => $item) {
if ($item) {
$input[$key]['_weight'] = $weight++;
}
}
drupal_array_set_nested_value($form_state['input'], $address, $input);
field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
$form_state['rebuild'] = TRUE;
}
function bat_options_price_options($per_person = FALSE) {
$options = array(
BAT_OPTIONS_ADD => t('Add to price'),
BAT_OPTIONS_ADD_DAILY => t('Add to price per night'),
BAT_OPTIONS_SUB => t('Subtract from price'),
BAT_OPTIONS_SUB_DAILY => t('Subtract from price per night'),
BAT_OPTIONS_REPLACE => t('Replace price'),
BAT_OPTIONS_INCREASE => t('Increase price by % amount'),
BAT_OPTIONS_DECREASE => t('Decrease price by % amount'),
BAT_OPTIONS_NOCHARGE => t('No charge'),
);
if ($per_person) {
$options[BAT_OPTIONS_ADD_PERSON] = t('Add to price per person');
$options[BAT_OPTIONS_ADD_DAILY_PERSON] = t('Add to price per night per person');
$options[BAT_OPTIONS_SUB_PERSON] = t('Subtract from price per person');
$options[BAT_OPTIONS_SUB_DAILY_PERSON] = t('Subtract from price per night per person');
}
drupal_alter('bat_options_price_options', $options);
return $options;
}
function bat_options_get_type_options(BatType $type) {
$options =& drupal_static(__FUNCTION__);
if (isset($options['types'][$type->type_id])) {
return $options['types'][$type->type_id];
}
$type_options = is_array(field_get_items('bat_type', $type, 'field_addons')) ? field_get_items('bat_type', $type, 'field_addons') : array();
$options['types'][$type->type_id] = $type_options;
return $options['types'][$type->type_id];
}
function bat_options_get_machine_name($option_name, $pattern = '/[^a-z0-9_]+/', $replacement = '_') {
return preg_replace($pattern, $replacement, drupal_strtolower($option_name));
}
function bat_options_get_operation_label($option) {
$label = '';
$currency_setting = commerce_currency_load(commerce_default_currency());
$currency_symbol = $currency_setting['symbol'];
switch ($option['operation']) {
case 'add':
$label = t('+@amount@currency_symbol to price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'add-daily':
$label = t('+@amount@currency_symbol per night to price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'sub-daily':
$label = t('-@amount@currency_symbol per night from price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'replace':
$label = t('Replace price with @amount@currency_symbol', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'increase':
$label = t('Increase price by @amount%', array(
'@amount' => $option['value'],
));
break;
case 'decrease':
$label = t('Decrease price by @amount%', array(
'@amount' => $option['value'],
));
break;
case 'sub':
$label = t('-@amount@currency_symbol from price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'add_person':
$label = t('+@amount@currency_symbol per person to price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'add-daily_person':
$label = t('+@amount@currency_symbol per night per person to price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'sub_person':
$label = t('-@amount@currency_symbol per person from price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
case 'sub-daily_person':
$label = t('-@amount@currency_symbol per night per person from price', array(
'@amount' => $option['value'],
'@currency_symbol' => $currency_symbol,
));
break;
}
return $label;
}
function bat_options_get_option_price($booking_price, $option, $quantity, $nights, $persons = 0) {
$price = 0;
switch ($option['operation']) {
case BAT_OPTIONS_ADD:
$price += $option['value'];
break;
case BAT_OPTIONS_ADD_DAILY:
$price += $option['value'] * $nights;
break;
case BAT_OPTIONS_SUB:
$price -= $option['value'];
break;
case BAT_OPTIONS_SUB_DAILY:
$price -= $option['value'] * $nights;
break;
case BAT_OPTIONS_REPLACE:
$price = $option['value'] - $booking_price;
break;
case BAT_OPTIONS_INCREASE:
$price += $booking_price * ($option['value'] / 100);
break;
case BAT_OPTIONS_DECREASE:
$price -= $booking_price * ($option['value'] / 100);
break;
case BAT_OPTIONS_ADD_PERSON:
$price += $option['value'] * $persons;
break;
case BAT_OPTIONS_ADD_DAILY_PERSON:
$price += $option['value'] * $nights * $persons;
break;
case BAT_OPTIONS_SUB_PERSON:
$price -= $option['value'] * $persons;
break;
case BAT_OPTIONS_SUB_DAILY_PERSON:
$price -= $option['value'] * $nights * $persons;
break;
}
return $price * 100;
}