You are here

rooms_booking_manager.module in Rooms - Drupal Booking for Hotels, B&Bs and Vacation Rentals 7

Rooms Booking Manager brings together all the pieces required to find a room and book it - including the DrupalCommerce integration

File

modules/rooms_booking_manager/rooms_booking_manager.module
View source
<?php

/**
 * @file
 * Rooms Booking Manager brings together all the pieces required to find a room
 * and book it - including the DrupalCommerce integration
 */

/**
 * Implements hook_permission().
 */
function rooms_booking_manager_permission() {
  $permissions = array(
    'book units' => array(
      'title' => t('Book units'),
      'description' => t('Allows users to book units.'),
    ),
    'book in advance without limitation' => array(
      'title' => t('Book in advance without time limitation'),
      'description' => t('Disregards any time limitations for advance bookings'),
    ),
    'make same-day bookings' => array(
      'title' => t('Make same-day bookings'),
      'description' => t('Disregards the rooms booking start date limitations'),
    ),
  );
  return $permissions;
}

/**
 * Implements hook_menu().
 */
function rooms_booking_manager_menu() {
  $items = array();
  $items['booking'] = array(
    'title' => 'Create your booking',
    'title callback' => 'rooms_booking_manager_menu_title_callback',
    'title arguments' => array(
      'booking',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'rooms_booking_availability_search_form_page',
    ),
    'file' => 'rooms_booking_manager.availability_search.inc',
    'access arguments' => array(
      'book units',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  $items['booking/%start_date/%end_date'] = array(
    'title' => 'Select your stay',
    'title callback' => 'rooms_booking_manager_menu_title_callback',
    'title arguments' => array(
      'select_your_stay',
    ),
    'page callback' => 'rooms_booking_manager_results_page',
    'page arguments' => array(
      1,
      2,
    ),
    'access arguments' => array(
      'book units',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['booking-override-confirmation/%start_date/%end_date'] = array(
    'title' => 'Select your stay',
    'page callback' => 'rooms_booking_manager_override_confirmation_page',
    'page arguments' => array(
      1,
      2,
    ),
    'file' => 'rooms_booking_manager.confirmation_override.inc',
    'access arguments' => array(
      'book units',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['enquiry/%start_date/%end_date'] = array(
    'title' => 'Ask about availability',
    'page callback' => 'rooms_booking_manager_enquiry_page',
    'page arguments' => array(
      1,
      2,
    ),
    'access arguments' => array(
      'book units',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['bookings'] = array(
    'title' => 'Review your reservation',
    'title callback' => 'rooms_booking_manager_menu_title_callback',
    'title arguments' => array(
      'bookings',
    ),
    'page callback' => 'rooms_booking_manager_cart_view',
    'access arguments' => array(
      'access checkout',
    ),
  );
  $items['enquiry-confirmation'] = array(
    'title' => 'Availability enquiry',
    'page callback' => 'rooms_booking_manager_enquiry_confirmation',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_mail().
 */
function rooms_booking_manager_mail($key, &$message, $params) {
  switch ($key) {
    case 'enquiry_booking':
      $message['subject'] = t('Booking');
      $message['body'] = array(
        theme('rooms_booking_email', $params),
      );
  }
}

/**
 * Display 'Booking confirmed' message.
 */
function rooms_booking_manager_enquiry_confirmation() {
  return array(
    '#theme' => 'rooms_booking_enquiry_confirmation',
    '#message' => variable_get_value('rooms_booking_manager_enquiry_form_confirmation'),
  );
}

/**
 * Display the shopping cart form and associated information.
 */
function rooms_booking_manager_cart_view() {
  global $user;

  // Default to displaying an empty message.
  $content = theme('commerce_cart_empty_page');
  commerce_cart_order_refresh(commerce_cart_order_load($user->uid));

  // First check to make sure we have a valid order.
  if ($order = commerce_cart_order_load($user->uid)) {
    $wrapper = entity_metadata_wrapper('commerce_order', $order);

    // Only show the cart form if we found product line items.
    if (commerce_line_items_quantity($wrapper->commerce_line_items, commerce_product_line_item_types()) > 0) {
      drupal_add_css(drupal_get_path('module', 'commerce_cart') . '/theme/commerce_cart.theme.css');

      // Add the form for editing the cart contents.
      $content = commerce_embed_view('booking_cart_form', 'default', array(
        $order->order_id,
      ), 'cart');
    }
  }
  return $content;
}

/**
 * Page callback for enquiry search.
 */
function rooms_booking_manager_enquiry_page($start_date = 0, $end_date = 0, $unit = NULL) {
  $form = drupal_get_form('rooms_booking_manager_enquiry_page_form', $start_date, $end_date, $unit, 0, 1);
  $change_search_form = drupal_get_form('rooms_booking_manager_change_search_form', $start_date, $end_date, $unit, 0, 1);
  return array(
    $change_search_form,
    $form,
  );
}

/**
 * Enquiry search page form.
 */
function rooms_booking_manager_enquiry_page_form($form, $form_state, $start_date = 0, $end_date = 0, $unit = NULL) {
  if ($unit) {
    $unit_obj = rooms_unit_load($unit);
    $form['room_description'] = array(
      '#type' => 'item',
      '#markup' => t('Unit: @unit_name', array(
        '@unit_name' => $unit_obj->name,
      )),
    );
    $form['enquiry']['unit'] = array(
      '#type' => 'hidden',
      '#value' => $unit_obj->name,
    );
    if (isset($_GET['options'])) {
      $form['options'] = array(
        '#type' => 'hidden',
        '#value' => serialize($_GET['options']),
      );
      foreach ($_GET['options'] as $option => $quantity) {
        $printable_options[] = "{$option}: {$quantity}";
      }
      $printable_options = theme('item_list', array(
        'items' => $printable_options,
      ));
      $form['options_description'] = array(
        '#markup' => t('Options: !options', array(
          '!options' => $printable_options,
        )),
      );
    }

    // Added unit name to enquiry email
    $form['unit'] = array(
      '#type' => 'hidden',
      '#value' => $unit_obj->name,
    );
  }
  $form['#tree'] = TRUE;
  $form['#attributes']['class'][] = 'rooms-enquiry-form';
  $form['start_date'] = array(
    '#type' => 'hidden',
    '#value' => $start_date
      ->format('Y-m-d'),
  );
  $form['end_date'] = array(
    '#type' => 'hidden',
    '#value' => $end_date
      ->format('Y-m-d'),
  );
  if (isset($_GET['order'])) {
    foreach ($_GET['order'] as $type => $units) {
      $i = 1;
      $printed = FALSE;
      foreach ($units as $unit) {
        for ($index = 1; $index <= $unit['quantity']; $index++) {
          if (!$printed) {
            $room_type = rooms_unit_type_load($type);
            $form['units'][$type] = array(
              '#type' => 'fieldset',
              '#collapsible' => FALSE,
              '#title' => check_plain($room_type->label),
            );
            $printed = TRUE;
          }
          $form['units'][$type]["{$type}_{$i}"] = array(
            '#type' => 'container',
            '#attributes' => array(
              'class' => array(
                'container-inline',
              ),
            ),
          );
          $form['units'][$type]["{$type}_{$i}"]["markup"] = array(
            '#prefix' => '<h3>',
            '#markup' => t('Unit @unit', array(
              '@unit' => $i,
            )),
            '#suffix' => '</h3>',
          );
          $options = array();
          if (isset($unit['fieldset'][$index])) {
            foreach ($unit['fieldset'][$index] as $option => $value) {
              if (strpos($option, ':quantity') === FALSE && $value && $option != 'persons' && $option != 'children' && $option != 'childrens_age') {
                if (isset($unit['fieldset'][$index][$option . ':quantity'])) {
                  $options[] = $option . ': ' . ($unit['fieldset'][$index][$option . ':quantity'] + 1);
                }
                else {
                  $options[] = $option . ': 1';
                }
              }
            }
            if (!empty($options)) {
              $form['units'][$type]["{$type}_{$i}"]['markup_options'] = array(
                '#prefix' => '<h4>',
                '#markup' => t('Options: !options', array(
                  '!options' => theme('item_list', array(
                    'items' => $options,
                  )),
                )),
                '#suffix' => '</h4>',
              );
              $form['units'][$type]["{$type}_{$i}"]['options'] = array(
                '#type' => 'hidden',
                '#value' => t('Options: @options', array(
                  '@options' => implode(',', $options),
                )),
              );
            }
          }
          $i++;
        }
      }
    }
  }
  $form['customer_name'] = array(
    '#title' => t('Name') . ':',
    '#type' => 'textfield',
    '#size' => 50,
    '#required' => TRUE,
  );
  $form['customer_email'] = array(
    '#title' => t('Email') . ':',
    '#type' => 'textfield',
    '#size' => 50,
    '#required' => TRUE,
  );
  if (variable_get('rooms_enquiry_form_address', 1)) {
    $form['customer_add1'] = array(
      '#title' => t('Address Line 1') . ':',
      '#type' => 'textfield',
      '#size' => 80,
      '#required' => variable_get('rooms_enquiry_form_address_required', 1),
    );
    $form['customer_add2'] = array(
      '#title' => t('Address Line 2') . ':',
      '#type' => 'textfield',
      '#size' => 80,
    );
    $form['customer_city'] = array(
      '#title' => t('City') . ':',
      '#type' => 'textfield',
      '#size' => 60,
      '#required' => variable_get('rooms_enquiry_form_address_required', 1),
    );
    $form['customer_state'] = array(
      '#title' => t('State/Province') . ':',
      '#type' => 'textfield',
      '#size' => 60,
      '#required' => variable_get('rooms_enquiry_form_address_required', 1),
    );
    $form['customer_country'] = array(
      '#title' => t('Country') . ':',
      '#type' => 'textfield',
      '#size' => 60,
      '#required' => variable_get('rooms_enquiry_form_address_required', 1),
    );
  }
  if (variable_get('rooms_enquiry_form_comments', 1)) {
    $form['comments'] = array(
      '#title' => t('Comments') . ':',
      '#type' => 'textarea',
      '#cols' => 50,
      '#resizable' => TRUE,
      '#rows' => 5,
      '#required' => variable_get('rooms_enquiry_form_comments_required', 1),
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

/**
 * Enquiry search page form validation handler.
 */
function rooms_booking_manager_enquiry_page_form_validate($form, $form_state) {
  if (!valid_email_address($form_state['values']['customer_email'])) {
    form_set_error('customer_email', t('You must enter a valid email address'));
  }
}

/**
 * Submit callback for rooms_booking_manager_enquiry_page_form form.
 *
 * @todo - check that original availability still holds
 * @todo - fix the user ownership of products
 */
function rooms_booking_manager_enquiry_page_form_submit(&$form, &$form_state) {
  global $language;
  $email = variable_get('site_mail', ini_get('sendmail_from'));
  $module = 'rooms_booking_manager';
  $key = 'enquiry_booking';
  $language = language_default();
  $params = array();
  $params['customer_name'] = t('Name') . ': ' . $form_state['values']['customer_name'];
  $params['customer_email'] = t('Email') . ': ' . $form_state['values']['customer_email'];
  if (variable_get('rooms_enquiry_form_address', 1)) {
    $params['customer_add1'] = t('Address Line 1') . ': ' . $form_state['values']['customer_add1'];
    $params['customer_add2'] = t('Address Line 2') . ': ' . $form_state['values']['customer_add2'];
    $params['customer_city'] = t('City') . ': ' . $form_state['values']['customer_city'];
    $params['customer_state'] = t('State/Province') . ': ' . $form_state['values']['customer_state'];
    $params['customer_country'] = t('Country') . ': ' . $form_state['values']['customer_country'];
  }
  if (variable_get('rooms_enquiry_form_comments', 1)) {
    $params['comments'] = t('Comments') . ': ' . $form_state['values']['comments'];
  }
  $params['booking_request'] = array();
  if (isset($form_state['values']['unit'])) {
    $params['booking_request'][] = t('Unit: @unit', array(
      '@unit' => $form_state['values']['unit'],
    ));
  }
  if (isset($form_state['values']['start_date'])) {
    $params['booking_request'][] = t('Start date: @start_date', array(
      '@start_date' => $form_state['values']['start_date'],
    ));
  }
  if (isset($form_state['values']['end_date'])) {
    $params['booking_request'][] = t('End date: @end_date', array(
      '@end_date' => $form_state['values']['end_date'],
    ));
  }
  if (isset($form_state['values']['options'])) {
    $options = unserialize($form_state['values']['options']);
    $printable_options = '';
    foreach ($options as $option => $quantity) {
      $printable_options[] = "{$option}: {$quantity}";
    }
    $params['booking_request'][] = t('Options: @options', array(
      '@options' => implode(', ', $printable_options),
    ));
  }
  if (isset($form_state['values']['units'])) {
    foreach ($form_state['values']['units'] as $unit_type_id => $rooms) {
      $unit_type = rooms_unit_type_load($unit_type_id);
      $index = 1;
      foreach ($rooms as $room) {
        $output = t('@unit_type unit No. @index: @options', array(
          '@unit_type' => $unit_type->label,
          '@index' => $index,
          '@options' => isset($room['options']) ? $room['options'] : t('No options selected.'),
        ));
        $params['booking_request'][] = $output;
        $index++;
      }
    }
  }
  drupal_mail($module, $key, $email, $language, $params, $email);
  $form_state['redirect'] = 'enquiry-confirmation';
}

/**
 * Constructs the booking results page following an availability search.
 *
 * @param DateTime $start_date
 *   Start date for the search.
 * @param DateTime $end_date
 *   End date for the search.
 * @param int $booking_units
 *   In how many units are we to accommodate them.
 *
 * @return string
 *   The themed result page string.
 */
function rooms_booking_manager_results_page(DateTime $start_date, DateTime $end_date, $booking_units = 1, $single_day_bookings = FALSE) {

  // Validate the dates.
  $errors = rooms_check_dates_validity($start_date, $end_date, TRUE, $single_day_bookings);

  // Check validity of the rest of the booking parameters that are stored in
  // $_GET. Again this is to ensure that any direct links were structured
  // appropriately.
  $booking_parameters = rooms_booking_manager_retrieve_booking_parameters($booking_units, $_GET);

  // The array of content to render.
  $content = array();

  // Add dates information to template.
  if (!empty($start_date) && !empty($end_date)) {
    $content['start_date'] = $start_date;
    $content['end_date'] = $end_date;
    $content['nights'] = $end_date
      ->diff($start_date)->days;
  }
  if (empty($errors) && is_array($booking_parameters)) {
    $content['booking_results'] = 1;
    $unit_types = array();
    $type = '';
    if (isset($_GET['type'])) {
      $type = check_plain($_GET['type']);
      if ($_GET['type'] == 'all') {
        $types = variable_get('rooms_unit_type_selector', array());
        foreach ($types as $element) {
          $unit_types[] = $element;
        }
      }
      else {
        $type = check_plain($_GET['type']);
        if (rooms_unit_type_load($type) !== FALSE) {
          $unit_types[] = $type;
        }
      }
    }

    // Get all the units.
    $agent = new AvailabilityAgent($start_date, $end_date, $booking_parameters, $booking_units, array_keys(array_filter(variable_get('rooms_valid_availability_states', drupal_map_assoc(array(
      ROOMS_AVAILABLE,
      ROOMS_ON_REQUEST,
    ))))), $unit_types);
    $units_per_type = $agent
      ->checkAvailability();

    // Give other modules a chance to change the search results.
    drupal_alter('rooms_booking_results', $units_per_type, $start_date, $end_date, $booking_parameters);

    // If we don't have any useful result to show just display a failure message
    // and the search form.
    if ($units_per_type == ROOMS_NO_ROOMS || $units_per_type == ROOMS_SIZE_FAILURE) {
      $content['booking_results'] = 0;

      // Add the search availability form.
      module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.availability_search');
      $booking_search_form = drupal_get_form('rooms_booking_availability_search_form_page');

      // Alter the page title.
      drupal_set_title(variable_get_value('rooms_booking_manager_create_your_booking'));

      // Store and clean old messages.
      $old_messages = drupal_get_messages();

      // Create a warning message.
      drupal_set_message(variable_get_value('rooms_booking_manager_warning_no_units_available'), 'warning');

      // Show the themed warning message inside our form.
      $content['no_results'] = array(
        '#prefix' => '<div class="no-booking-data">',
        '#markup' => theme('status_messages'),
        '#suffix' => '</div>',
      );

      // Restore old messages.
      $_SESSION['messages'] = $old_messages;
      $content['booking_search_form'] = $booking_search_form;
    }
    elseif (variable_get('rooms_presentation_style', ROOMS_PER_TYPE) == ROOMS_PER_TYPE) {

      // Alter the page title.
      drupal_set_title(variable_get_value('rooms_booking_manager_select_your_stay'));
      $content = rooms_booking_manager_present_types($units_per_type, $content, $start_date, $end_date, $booking_parameters, $booking_units, $type);
    }
    elseif (variable_get('rooms_presentation_style', ROOMS_PER_TYPE) == ROOMS_INDIVIDUAL) {

      // Alter the page title.
      drupal_set_title(variable_get_value('rooms_booking_manager_select_your_stay'));
      $content = rooms_booking_manager_present_individual_rooms($units_per_type, $content, $start_date, $end_date, $booking_parameters);
    }
  }
  else {
    drupal_set_message(t('Perform a search to get availability information'));
    drupal_goto('booking');
    exit;
  }
  $type = '';
  if (isset($_GET['type'])) {
    $type = check_plain($_GET['type']);
    if ($type == '' || rooms_unit_type_load($type) === FALSE) {
      $type = '';
    }
  }
  if ($content['booking_results']) {
    $content['change_search'] = drupal_get_form('rooms_booking_manager_change_search_form', $start_date, $end_date, $booking_parameters, $booking_units, $type);
  }
  return theme('rooms_booking_results', $content);
}

/**
 * Provides a single integrated group of form elements storing the current
 * availability search along with a "change search" button that will take you
 * back to the initial booking search page.
 */
function rooms_booking_manager_change_search_form($form, &$form_state, $start_date, $end_date, $booking_parameters, $b_units, $type = '') {

  // Ensure stylesheets are added to the page.
  $form['#attached']['css'] = array(
    drupal_get_path('module', 'rooms_booking_manager') . '/css/rooms_booking_search.css',
  );
  $date_format = variable_get('rooms_date_format', 'd-m-Y');
  if (!isset($form['info'])) {
    $form['info'] = array(
      '#type' => 'fieldset',
      '#title' => variable_get_value('rooms_booking_manager_your_current_search'),
      '#tree' => FALSE,
      '#attributes' => array(
        'class' => array(
          'rooms-current-search__info',
          'form-item',
        ),
      ),
    );
  }
  if (!isset($form['info']['params'])) {
    $form['info']['params'] = array(
      '#type' => 'container',
      '#tree' => FALSE,
      '#attributes' => array(
        'class' => array(
          'rooms-current-search__params',
          'form-item',
        ),
      ),
      '#weight' => 10,
    );
  }
  $form['info']['arrival_date'] = array(
    '#theme' => 'container',
    '#markup' => '<label>' . variable_get_value('rooms_booking_manager_arrival_date') . '</label> <span class="info">' . check_plain($start_date
      ->format($date_format)) . '</span>',
    '#attributes' => array(
      'class' => array(
        'rooms-current-search__arrival',
        'form-item',
      ),
    ),
  );
  $form['info']['params']['start_date'] = array(
    '#type' => 'hidden',
    '#value' => $start_date
      ->format('Y-m-d'),
  );
  $form['info']['departure_date'] = array(
    '#theme' => 'container',
    '#markup' => '<label>' . variable_get_value('rooms_booking_manager_departure_date') . '</label> <span class="info">' . check_plain($end_date
      ->format($date_format)) . '</span>',
    '#attributes' => array(
      'class' => array(
        'rooms-current-search__departure',
        'form-item',
      ),
    ),
  );
  $form['info']['params']['end_date'] = array(
    '#type' => 'hidden',
    '#value' => $end_date
      ->format('Y-m-d'),
  );
  $form['info']['nights'] = array(
    '#theme' => 'container',
    '#markup' => '<label>' . variable_get_value('rooms_booking_manager_nights') . '</label> <span class="info">' . $end_date
      ->diff($start_date)->days . '</span>',
    '#attributes' => array(
      'class' => array(
        'rooms-current-search__nights',
        'form-item',
      ),
    ),
  );
  if ($b_units) {
    $form['info']['units'] = array(
      '#theme' => 'container',
      '#markup' => '<label>' . variable_get_value('rooms_booking_manager_units') . '</label> <span class="info">' . check_plain($b_units) . '</span>',
      '#attributes' => array(
        'class' => array(
          'rooms-current-search__units',
          'form-item',
        ),
      ),
    );
    $form['info']['params']['b_units'] = array(
      '#type' => 'hidden',
      '#value' => check_plain($b_units),
    );
  }
  if ($type && ($type_obj = rooms_unit_get_types($type))) {
    $form['info']['type'] = array(
      '#theme' => 'container',
      '#markup' => '<label>' . variable_get_value('rooms_booking_manager_unit_type') . '</label> <span class="info">' . check_plain($type_obj->label) . '</span>',
      '#attributes' => array(
        'class' => array(
          'rooms-current-search__type',
          'form-item',
        ),
      ),
    );
    $form['info']['params']['type'] = array(
      '#type' => 'hidden',
      '#value' => check_plain($type),
    );
  }
  if (!empty($booking_parameters)) {
    $form['info']['params']['booking_parameters'] = array(
      '#type' => 'hidden',
      '#value' => serialize($booking_parameters),
    );
  }

  // Include form elements provided by other availability search plugins.
  ctools_include('plugins');
  $filters = ctools_get_plugins('rooms_booking', 'availabilityagent_filter');
  foreach ($filters as $filter) {
    $class = ctools_plugin_get_class($filter, 'handler');
    $class::availabilityChangeSearchForm($form, $form_state);
  }
  if (isset($_GET['rooms_id'])) {
    $form['rooms_id'] = array(
      '#type' => 'hidden',
      '#value' => $_GET['rooms_id'],
    );
  }

  // We add the form's #submit array to this button along with the actual submit
  // handler to preserve any submit handlers added by a form callback_wrapper.
  $submit = array(
    'rooms_booking_manager_change_search_form_submit',
  );
  if (!empty($form['#submit'])) {
    $submit += $form['#submit'];
    $form['#submit'] = $submit;
  }
  $form['info']['actions'] = array(
    '#type' => 'container',
    '#tree' => FALSE,
    '#attributes' => array(
      'class' => array(
        'rooms-current-search__actions',
        'form-item',
      ),
    ),
  );
  $form['info']['actions']['change_search'] = array(
    '#type' => 'submit',
    '#value' => variable_get_value('rooms_booking_manager_button_change_search'),
    '#attributes' => array(
      'class' => array(
        'rooms-current-search__change-search-button',
      ),
    ),
  );
  return $form;
}
function rooms_booking_manager_change_search_form_validate($form, &$form_state) {

  // validate form elements provided by other availability search plugins.
  ctools_include('plugins');
  $filters = ctools_get_plugins('rooms_booking', 'availabilityagent_filter');
  foreach ($filters as $filter) {
    $class = ctools_plugin_get_class($filter, 'handler');
    $class::availabilityChangeSearchFormValidate($form, $form_state);
  }
}

/**
 * Checks that the booking parameters given are valid. This is mainly used to
 * clean up values that came through the URL and are set in $_GET.
 *
 * @param int $booking_units
 *   The amount of booking units
 * @param array $booking_info
 *   Booking info supplied
 *
 * @return array
 *   An array of booking parameters
 */
function rooms_booking_manager_retrieve_booking_parameters($booking_units, $booking_info) {
  $booking_units = check_plain($booking_units);
  $booking_parameters = array();
  if (variable_get('rooms_presentation_style', ROOMS_PER_TYPE) == ROOMS_INDIVIDUAL) {
    if (variable_get('rooms_display_children', ROOMS_DISPLAY_CHILDREN_NO) == ROOMS_DISPLAY_CHILDREN) {
      if (isset($booking_info['rooms_group_size1']) && isset($booking_info['rooms_children1'])) {
        $booking_parameters[1]['adults'] = check_plain($booking_info['rooms_group_size1']);
        $booking_parameters[1]['children'] = check_plain($booking_info['rooms_children1']);
      }
      else {
        $booking_parameters = 0;
      }
    }
    else {
      if (isset($booking_info['rooms_group_size1'])) {
        $booking_parameters[1]['adults'] = check_plain($booking_info['rooms_group_size1']);
      }
      else {
        $booking_parameters = 0;
      }
    }

    // If the booking parameter data was not valid invalidate the data.
    if ($booking_parameters == 0) {
      return FALSE;
    }
    else {
      return $booking_parameters;
    }
  }
  else {

    // Given a certain number of units lets hunt in $booking_info for them.
    for ($i = 1; $i <= $booking_units; $i++) {

      // If not data has invalidated booking parameters yet.
      if ($booking_parameters != 0) {
        if (variable_get('rooms_display_children', ROOMS_DISPLAY_CHILDREN_NO) == ROOMS_DISPLAY_CHILDREN) {
          if (isset($booking_info['rooms_group_size' . $i]) && isset($booking_info['rooms_children' . $i])) {
            $booking_parameters[$i]['adults'] = check_plain($booking_info['rooms_group_size' . $i]);
            $booking_parameters[$i]['children'] = check_plain($booking_info['rooms_children' . $i]);
          }
          else {
            $booking_parameters = 0;
          }
        }
        else {
          if (isset($booking_info['rooms_group_size' . $i])) {
            $booking_parameters[$i]['adults'] = check_plain($booking_info['rooms_group_size' . $i]);
          }
          else {
            $booking_parameters = 0;
          }
        }
      }
    }

    // If the booking parameter data was not valid or did not correspond to the
    // number of units invalidate the data.
    if ($booking_parameters == 0 || count($booking_parameters) < $booking_units) {
      return FALSE;
    }
    else {
      return $booking_parameters;
    }
  }
}

/**
 * Prepares rooms on a per room basis for presentation.
 */
function rooms_booking_manager_present_individual_rooms($units_per_type, $content, $start_date, $end_date, $booking_parameters) {
  $content['style'] = ROOMS_INDIVIDUAL;
  drupal_add_css(drupal_get_path('module', 'rooms_booking_manager') . '/css/booking_search.css');
  foreach ($units_per_type as $type => $price_level) {
    $type_obj = rooms_unit_type_load($type);
    $content[$type] = array(
      '#prefix' => '<h3 class="rooms-search-result__unit-type-name">',
      '#markup' => t($type_obj->label),
      '#suffix' => '</h3>',
    );

    // Sort by least expensive first.
    ksort($price_level, SORT_NUMERIC);
    foreach ($price_level as $price => $units) {
      foreach ($units as $unit_id => $unit) {

        // Load the unit and render.
        $unit_obj = rooms_unit_load($unit_id);
        $controller = entity_get_controller('rooms_unit');
        $unit_content = $controller
          ->view(array(
          $unit_id => $unit_obj,
        ));
        $content['units_per_type'][$type][$price][$unit_id] = array(
          '#theme' => 'container',
          '#attributes' => array(
            'class' => array(
              'rooms-search-result__unit',
            ),
          ),
        );
        $content['units_per_type'][$type][$price][$unit_id]['unit'] = $unit_content;

        // Add purchase form.
        $form = 'book_unit_form_' . $unit_id;
        $content['units_per_type'][$type][$price][$unit_id]['book_unit_form'] = drupal_get_form($form, $unit_obj, $start_date, $end_date, $booking_parameters, $unit['state'], $unit['price'], $unit['price_log']);
      }
    }
  }
  return $content;
}

/**
 * Prepares Units on a per type basis.
 */
function rooms_booking_manager_present_types($units_per_type, $content, $start_date, $end_date, $booking_parameters, $b_units, $type = '') {

  // Flag used in tpl.
  $content['style'] = ROOMS_PER_TYPE;

  // We build all the content as a form for now.
  $content['units_per_type_form'] = drupal_get_form('book_units_per_type_form', $units_per_type, $start_date, $end_date, $booking_parameters, $b_units, $type);
  return $content;
}

/**
 * Implements hook_forms().
 *
 * We use this to be able to show a different purchase button for each choice.
 */
function rooms_booking_manager_forms($form_id, $args) {
  $forms = array();
  if (strpos($form_id, 'book_unit_form_') === 0) {
    $forms[$form_id] = array(
      'callback' => 'book_unit_form_builder',
    );
  }
  elseif (strpos($form_id, 'rooms_booking_availability_search_form_') === 0) {
    $forms[$form_id] = array(
      'callback' => 'rooms_booking_availability_search_form_builder',
    );
  }
  return $forms;
}

/**
 * The form builder builds the form (where visible is simply the purchase
 * button) for individual bookable units.
 *
 * The builder gets called for each unit from the
 * rooms_booking_manager_present_individual_rooms function above.
 *
 * The available units have already been identified by
 * rooms_booking_manager_results_page.
 */
function book_unit_form_builder($form_id, $form_state, $unit, $start_date, $end_date, $booking_parameters, $status, $price, $price_log) {

  // Add classes.
  $form['#attributes']['class'][] = 'rooms-book-unit-form';
  if (module_exists('commerce_multicurrency')) {
    $currency_code = commerce_multicurrency_get_user_currency_code();
  }
  else {
    $currency_code = commerce_default_currency();
  }
  $currency_setting = commerce_currency_load($currency_code);
  $currency_symbol = $currency_setting['symbol'];
  $form['unit_id'] = array(
    '#type' => 'hidden',
    '#value' => $unit->unit_id,
  );
  $form['status'] = array(
    '#type' => 'hidden',
    '#value' => $status,
  );
  $form['start_date'] = array(
    '#type' => 'hidden',
    '#value' => $start_date
      ->format('Y-m-d'),
  );
  $form['end_date'] = array(
    '#type' => 'hidden',
    '#value' => $end_date
      ->format('Y-m-d'),
  );
  $form['rooms_group_size'] = array(
    '#type' => 'hidden',
    '#value' => $booking_parameters[1]['adults'],
  );
  if (isset($booking_parameters[1]['children'])) {
    $form['rooms_children'] = array(
      '#type' => 'hidden',
      '#value' => $booking_parameters[1]['children'],
    );
  }

  // Calculate the period.
  $nights = $end_date
    ->diff($start_date)->days;

  // Check for a deposit.
  $deposit_amount = rooms_booking_manager_check_for_deposit($price, $start_date);
  if (empty($deposit_amount)) {
    $price_amount = $price * 100;
    if (module_exists('commerce_multicurrency')) {
      $price_amount = commerce_currency_convert($price_amount, commerce_default_currency(), $currency_code);
    }
    $form['price'] = array(
      '#prefix' => '<div class="rooms-search-result__unit-base-price" id="unit_' . $unit->unit_id . '_base_price">',
      '#markup' => rooms_string('<label>' . t('Base price') . ':</label> <span class="rooms-search-result__base-price-amount">' . commerce_currency_format($price_amount, $currency_code) . '</span>', array(
        '#component' => 'book_unit_form_builder',
        '#purpose' => 'display_base_price',
        '#data' => array(
          'price' => $price,
          'currency_symbol' => $currency_symbol,
          'amount' => $price,
          'unit' => $unit,
          'nights' => $nights,
          'arrival' => $start_date,
          'departure' => $end_date,
          'price_log' => $price_log,
        ),
      )),
      '#suffix' => '</div>',
    );
  }
  else {
    $deposit_amount = $deposit_amount * 100;
    if (module_exists('commerce_multicurrency')) {
      $deposit_amount = commerce_currency_convert($deposit_amount, commerce_default_currency(), $currency_code);
    }
    $price_amount = $price * 100;
    if (module_exists('commerce_multicurrency')) {
      $price_amount = commerce_currency_convert($price_amount, commerce_default_currency(), $currency_code);
    }
    $form['price'] = array(
      '#prefix' => '<div class="rooms-search-result__unit-base-price" id="unit_' . $unit->unit_id . '_base_price">',
      '#markup' => rooms_string('<label>' . t('Base price') . ':</label> <span class="rooms-search-result__base-price-amount">' . commerce_currency_format($price, $currency_code) . '</span>' . '<label>' . ' - ' . t('Payable now') . ':</label> <span class="rooms-search-result__base-price-amount">' . commerce_currency_format($deposit_amount, $currency_code) . '</span>', array(
        '#component' => 'book_unit_form_builder',
        '#purpose' => 'display_base_price',
        '#data' => array(
          'price' => $price,
          'currency_symbol' => $currency_symbol,
          'amount' => $price,
          'unit' => $unit,
          'nights' => $nights,
          'arrival' => $start_date,
          'departure' => $end_date,
          'price_log' => $price_log,
        ),
      )),
      '#suffix' => '</div>',
    );
  }
  if (variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) == ROOMS_PER_PERSON) {

    // Calculate the price per person for the period.
    $price_per_person = $price / $unit->max_sleeps * 100;

    // Calculate the price per person per night, too.
    $base_price = $price_per_person / $nights;
    if (module_exists('commerce_multicurrency')) {
      $price_per_person = commerce_currency_convert($price_per_person, commerce_default_currency(), $currency_code);
      $base_price = commerce_currency_convert($base_price, commerce_default_currency(), $currency_code);
    }
    $form['price']['#markup'] = rooms_string(format_plural($nights, t('Book this unit for 1 night at <b>@price per person</b> (@base_price per person per night)'), t('Book this unit for @count nights at <b>@price per person</b> (@base_price per person per night)'), array(
      '@price' => commerce_currency_format($price_per_person, $currency_code),
      '@base_price' => commerce_currency_format($base_price, $currency_code),
    )), array(
      '#component' => 'book_unit_form_builder',
      '#purpose' => 'display_base_price_per_person',
      '#data' => array(
        'price' => $price,
        'currency_symbol' => $currency_symbol,
        'amount' => $price,
        'unit' => $unit,
        'nights' => $nights,
        'arrival' => $start_date,
        'departure' => $end_date,
      ),
    ));
  }
  $form['options'] = array(
    '#tree' => TRUE,
  );

  // Add options checkboxes and convert Price options in Price modifiers.
  $price_modifiers = array();
  foreach (rooms_unit_get_unit_options($unit) as $option) {
    $option_name = rooms_options_machine_name($option['name']);
    $form['options'][$option_name] = array(
      '#type' => 'checkbox',
      '#title' => t($option['name']),
      '#ajax' => array(
        'callback' => 'rooms_booking_manager_options_change_callback',
        'wrapper' => 'unit_' . $unit->unit_id . '_price',
      ),
    );
    if ($option['type'] == ROOMS_OPTION_MANDATORY) {
      $form['options'][$option_name]['#default_value'] = '1';
      $form['options'][$option_name]['#disabled'] = TRUE;
    }

    // Show quantity field selector if in option quantity is set.
    if (is_numeric($option['quantity'])) {
      if ((isset($form_state['values']['options'][$option_name]) && $form_state['values']['options'][$option_name] == 1 || $option['type'] == ROOMS_OPTION_MANDATORY) && $option['quantity'] > 1) {
        $form['options'][$option_name . ':quantity'] = array(
          '#type' => 'select',
          '#title' => t('Quantity'),
          '#options' => range(1, $option['quantity']),
          '#ajax' => array(
            'callback' => 'rooms_booking_manager_options_change_callback',
            'wrapper' => 'unit_' . $unit->unit_id . '_price',
          ),
          '#prefix' => '<div class="rooms-search-result__unit-quantity" id="unit_' . $unit->unit_id . '_' . $option_name . '_quantity">',
          '#suffix' => '</div>',
        );
      }
      else {
        $form['options'][$option_name . ':quantity'] = array(
          '#prefix' => '<div class="rooms-search-result__unit-quantity" id="unit_' . $unit->unit_id . '_' . $option_name . '_quantity">',
          '#suffix' => '</div>',
        );
      }
    }
    if ($option['type'] == ROOMS_OPTION_MANDATORY) {
      $quantity = 1;
      if (isset($form_state['values']['options'][$option_name . ':quantity']) && $option['operation'] != ROOMS_REPLACE) {
        $quantity = $form_state['values']['options'][$option_name . ':quantity'] + 1;
      }
      $price_modifiers[$option_name] = array(
        '#type' => ROOMS_DYNAMIC_MODIFIER,
        '#op_type' => $option['operation'],
        '#amount' => $option['value'],
        '#quantity' => $quantity,
      );
    }
    elseif (isset($form_state['values']['options'][$option_name])) {
      $quantity = 1;
      if (isset($form_state['values']['options'][$option_name . ':quantity']) && $option['operation'] != ROOMS_REPLACE) {
        $quantity = $form_state['values']['options'][$option_name . ':quantity'] + 1;
      }
      if ($form_state['values']['options'][$option_name] == 1) {
        if ($option['type'] != ROOMS_OPTION_ONREQUEST) {
          $price_modifiers[$option_name] = array(
            '#type' => ROOMS_DYNAMIC_MODIFIER,
            '#op_type' => $option['operation'],
            '#amount' => $option['value'],
            '#quantity' => $quantity,
          );
        }
      }
    }
  }

  // Price is calculated as 'Price per person per night'
  if (variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) == ROOMS_PER_PERSON) {
    $form['persons'] = array(
      '#type' => 'select',
      '#field_suffix' => t('Guests'),
      '#options' => range($unit->min_sleeps, $unit->max_sleeps),
      '#default_value' => $unit->max_sleeps - $unit->min_sleeps,
      '#ajax' => array(
        'callback' => 'rooms_booking_manager_quantity_change_callback',
        'wrapper' => 'unit_' . $unit->unit_id . '_price',
      ),
      '#title' => t('How many people in this unit (including adults and children)?'),
      '#prefix' => '<div class="rooms-search-result__select-guests">',
      '#suffix' => '</div>',
    );
    $max_children = $unit->max_children;
    if (isset($form_state['values']['persons'])) {
      $persons = $form_state['values']['persons'] + $unit->min_sleeps;
      if ($persons < $unit->max_children) {
        $max_children = $persons;
      }
    }
    if ($max_children > $unit->min_children) {
      $form['children'] = array(
        '#type' => 'select',
        '#title' => t('How many of the guests are children?'),
        '#field_suffix' => t('Children'),
        '#options' => range($unit->min_children, $max_children),
        '#default_value' => 0,
        '#ajax' => array(
          'callback' => 'rooms_booking_manager_children_change_callback',
          'wrapper' => 'unit_' . $unit->unit_id . '_childrensage',
        ),
        '#prefix' => '<div class="rooms-search-result__select-children">',
        '#suffix' => '</div>',
      );
    }
    $form['childrens_age'] = array(
      '#prefix' => '<div class="rooms-search-result__select-childrensage" id="unit_' . $unit->unit_id . '_childrensage">',
      '#suffix' => '</div>',
      '#tree' => TRUE,
    );
    if (isset($form_state['values']['children'])) {
      if ($form_state['values']['children'] > 0) {
        for ($t = 1; $t <= $form_state['values']['children']; $t++) {
          $form['childrens_age'][$t] = array(
            '#type' => 'select',
            '#field_prefix' => t('Age of child @num', array(
              '@num' => $t,
            )),
            '#options' => range(0, 18),
            '#ajax' => array(
              'callback' => 'rooms_booking_manager_options_change_callback',
              'wrapper' => 'unit_' . $unit->unit_id . '_price',
            ),
            '#attributes' => array(
              'class' => array(
                'rooms-search-result__childrens-age',
              ),
            ),
          );
        }
      }
    }
  }
  $form['price_amount'] = array(
    '#type' => 'hidden',
    '#value' => $price,
  );

  // Check for a deposit.
  $deposit_amount = rooms_booking_manager_check_for_deposit($price, $start_date);
  if (!empty($deposit_amount)) {
    $form['deposit_amount'] = array(
      '#type' => 'hidden',
      '#value' => $deposit_amount,
    );
  }
  $unit_options = rooms_unit_get_unit_options($unit);
  if (variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) == ROOMS_PER_PERSON || !empty($unit_options)) {
    if (isset($form_state['values']['persons'])) {
      $group_size = $form_state['values']['persons'] + $unit->min_sleeps;
    }
    else {
      $group_size = $unit->max_sleeps;
    }
    $group_size_children = isset($form_state['values']['children']) ? $form_state['values']['children'] + $unit->min_children : 0;
    $temp_end_date = clone $end_date;
    $temp_end_date
      ->sub(new DateInterval('P1D'));
    $childrens_age = array();
    if (isset($form_state['values']['persons'])) {
      for ($t = 1; $t <= $form_state['values']['children']; $t++) {
        $childrens_age[] = $form_state['values']['childrens_age'][$t];
      }
    }
    $booking_info = array(
      'start_date' => clone $start_date,
      'end_date' => clone $end_date,
      'unit' => $unit,
      'booking_parameters' => array(
        'group_size' => $group_size,
        'group_size_children' => $group_size_children,
        'childrens_age' => $childrens_age,
      ),
    );

    // Give other modules a chance to change the price modifiers.
    drupal_alter('rooms_price_modifier', $price_modifiers, $booking_info);

    // Apply price modifiers and replace unit price.
    $price_calendar = new UnitPricingCalendar($unit->unit_id, $price_modifiers);
    if (isset($form_state['values']['persons'])) {
      $new_price = $price_calendar
        ->calculatePrice($start_date, $temp_end_date, $form_state['values']['persons'] + $unit->min_sleeps, $form_state['values']['children'] + $unit->min_children, $childrens_age);
    }
    else {
      $new_price = $price_calendar
        ->calculatePrice($start_date, $temp_end_date, $unit->max_sleeps);
    }

    // Check for a deposit.
    $deposit_amount = rooms_booking_manager_check_for_deposit($new_price['full_price'], $start_date);
    $form['price_amount']['#value'] = $new_price['full_price'];
    $new_price['full_price'] = $new_price['full_price'] * 100;
    if (module_exists('commerce_multicurrency')) {
      $new_price['full_price'] = commerce_currency_convert($new_price['full_price'], commerce_default_currency(), $currency_code);
    }
    if (empty($deposit_amount)) {
      $form['new_price'] = array(
        '#prefix' => '<div class="rooms-search-result__new-price" id="unit_' . $unit->unit_id . '_price">',
        '#markup' => '<label>' . t('Cost') . ':</label> <span class="rooms-search-result__new-price-amount">' . commerce_currency_format($new_price['full_price'], $currency_code) . '</span>',
        '#suffix' => '</div>',
      );
    }
    else {
      $form['deposit_amount']['#value'] = $deposit_amount;
      $form['new_price'] = array(
        '#prefix' => '<div class="rooms-search-result__new-price" id="unit_' . $unit->unit_id . '_price">',
        '#markup' => '<label>' . t('Cost') . ':</label> <span class="rooms-search-result__new-price-amount">' . commerce_currency_format($new_price['full_price'], $currency_code) . '</span>' . '<label>' . ' - ' . t('Payable Now') . ':</label> <span class="rooms-search-result__new-price-deposit">' . commerce_currency_format($deposit_amount * 100, $currency_code) . '</span>',
        '#suffix' => '</div>',
      );
    }
  }

  // We add the form's #submit array to this button along with the actual submit
  // handler to preserve any submit handlers added by a form callback_wrapper.
  $submit = array();
  if (!empty($form['#submit'])) {
    $submit += $form['#submit'];
  }
  $form['actions'] = array(
    '#type' => 'container',
    '#tree' => FALSE,
    '#attributes' => array(
      'class' => array(
        'rooms-search-result__actions',
      ),
    ),
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Book This'),
    '#submit' => $submit + array(
      'book_unit_form_submit',
    ),
  );

  // We append the validate handler to #validate in case a form callback_wrapper
  // is used to add validate handlers earlier.
  $form['#validate'][] = 'book_unit_form_validate';
  return $form;
}
function rooms_booking_manager_price_change_callback(&$form, $form_state) {
  return $form['price'];
}

/**
 * Validation for cart booking form.
 *
 * @todo Evaluate what to do here
 */
function book_unit_form_validate(&$form, &$form_state) {
}

/**
 * Submit callback for book_unit_form form.
 */
function book_unit_form_submit(&$form, &$form_state) {
  module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.commerce');
  global $user;
  $unit_id = $form_state['values']['unit_id'];
  $unit = rooms_unit_load($unit_id);
  $start_date = $form_state['values']['start_date'];
  $end_date = $form_state['values']['end_date'];
  $group_size = isset($form_state['values']['persons']) ? $form_state['values']['persons'] + $unit->min_sleeps : $form_state['values']['rooms_group_size'];
  $status = $form_state['values']['status'];
  $booking_parameters = array(
    'adults' => $group_size,
    'children' => 0,
  );

  // This is very inefficient right now but we need to create date objects
  // reconvert them back to strings to recreate them in the Availability Agent.
  $sd = start_date_load($start_date);
  $ed = end_date_load($end_date);

  // Let us get available rooms again and match the order against actual rooms.
  $agent = new AvailabilityAgent($sd, $ed, $booking_parameters);
  $agent
    ->setValidStates(array_keys(array_filter(variable_get('rooms_valid_availability_states', drupal_map_assoc(array(
    ROOMS_AVAILABLE,
    ROOMS_ON_REQUEST,
  ))))));

  // Let us make sure our bookable unit is still available.
  $available_units = $agent
    ->checkAvailabilityForUnit($unit_id);
  if (count($available_units) > 0) {
    if (variable_get('rooms_checkout_style', ROOMS_COMMERCE_CHECKOUT) == ROOMS_COMMERCE_CHECKOUT) {
      $unit = array_pop($available_units);
      $price_modifiers = array();
      if (isset($form_state['values']['options'])) {

        // Convert Price options in Price modifiers.
        foreach (rooms_unit_get_unit_options($unit['unit']) as $option) {
          $option_name = rooms_options_machine_name($option['name']);
          if (isset($form_state['values']['options'][$option_name])) {
            if ($form_state['values']['options'][$option_name] == 1) {
              $quantity = 1;
              if (isset($form_state['values']['options'][$option_name . ':quantity']) && $option['operation'] != ROOMS_REPLACE) {
                $quantity = $form_state['values']['options'][$option_name . ':quantity'] + 1;
              }
              if ($option['type'] == ROOMS_OPTION_ONREQUEST) {
                $option['value'] = 0;
              }
              $price_modifiers[$option_name] = array(
                '#name' => $option['name'],
                '#type' => ROOMS_DYNAMIC_MODIFIER,
                '#op_type' => $option['operation'],
                '#amount' => $option['value'],
                '#quantity' => $quantity,
              );
            }
          }
        }
      }

      // Check if there are line_items with overlapping dates.
      module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.confirmation_override');
      $line_items = rooms_booking_manager_find_overlapping_line_items($sd, $ed, $unit['unit']->unit_id);
      if (!empty($line_items)) {

        // Redirect user to the override confirmation page.
        $booking_parameters = array(
          'unit_id' => $unit_id,
          'group_size' => $group_size,
        );
        $options = array();
        if (isset($form_state['values']['options'])) {
          foreach ($form_state['values']['options'] as $option => $value) {
            if (strpos($option, ':quantity') === FALSE && $value) {
              if (isset($form_state['values']['options'][$option . ':quantity'])) {
                $options[$option] = $form_state['values']['options'][$option . ':quantity'] + 1;
              }
              else {
                $options[$option] = 1;
              }
            }
          }
          $booking_parameters['options'] = $options;
        }
        $form_state['redirect'] = array(
          'booking-override-confirmation/' . $start_date . '/' . $end_date . '/' . $unit_id,
          array(
            'query' => $booking_parameters,
          ),
        );
      }
      else {

        // Create line item.
        if (isset($form_state['values']['children'])) {
          $children = $form_state['values']['children'];
          if (isset($form_state['values']['childrens_age'])) {
            $childrens_age = $form_state['values']['childrens_age'];
            $line_item = rooms_create_line_item($unit, $agent, array(
              'adults' => $group_size,
              'children' => $children,
              'childrens_age' => $childrens_age,
            ), $price_modifiers);
          }
          else {
            $line_item = rooms_create_line_item($unit, $agent, array(
              'adults' => $group_size,
              'children' => $children,
            ), $price_modifiers);
          }
        }
        else {
          $line_item = rooms_create_line_item($unit, $agent, array(
            'adults' => $group_size,
            'children' => 0,
          ), $price_modifiers);
        }

        // Add line item to cart.
        $line_item = commerce_cart_product_add($user->uid, $line_item, FALSE);

        // Refresh line items price and redirect to bookings page.
        commerce_cart_order_refresh(commerce_cart_order_load($user->uid));
        $form_state['redirect'] = variable_get('rooms_booking_manager_post_add_booking_path', 'bookings');
      }
    }
    elseif (variable_get('rooms_checkout_style', ROOMS_COMMERCE_CHECKOUT) == ROOMS_ENQ_CHECKOUT) {
      $booking_parameters = array();
      $options = array();
      if (isset($form_state['values']['options'])) {
        foreach ($form_state['values']['options'] as $option => $value) {
          if (strpos($option, ':quantity') === FALSE && $value) {
            if (isset($form_state['values']['options'][$option . ':quantity'])) {
              $options[$option] = $form_state['values']['options'][$option . ':quantity'] + 1;
            }
            else {
              $options[$option] = 1;
            }
          }
        }
        $booking_parameters['options'] = $options;
      }
      $form_state['redirect'] = array(
        'enquiry/' . $start_date . '/' . $end_date . '/' . $unit_id,
        array(
          'query' => $booking_parameters,
        ),
      );
    }
  }
  else {
    drupal_set_message(t('We apologize for the inconvenience; this unit is no longer available.'));
    $form_state['redirect'] = '<front>';
  }
}

/**
 * Book units per type booking form callback.
 */
function book_units_per_type_form($form, $form_state, $units_per_type, $start_date, $end_date, $booking_parameters, $b_units, $type = '') {
  if (isset($form_state['storage']['confirm'])) {
    $form['#attached']['css'][] = array(
      'data' => '.rooms-current-search__info { float: none; }',
      'type' => 'inline',
    );
    $current_path = array(
      'path' => current_path(),
      'query' => drupal_get_query_parameters(),
    );
    return confirm_form($form, 'You have a booking request with overlapping dates, continuing will replace it.', $current_path, '', t('Continue'), 'Go Back To Search');
  }
  module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.units_per_type_form');

  // Add stylesheets and classes.
  $form['#attached']['css'] = array(
    drupal_get_path('module', 'rooms_booking_manager') . '/css/booking_search.css',
  );
  $form['#attributes']['class'][] = 'rooms-availability-search-results';
  $form = _rooms_booking_manager_setup_hidden_fields($form, $start_date, $end_date, $booking_parameters, $b_units);
  if (module_exists('commerce_multicurrency')) {
    $currency_code = commerce_multicurrency_get_user_currency_code();
  }
  else {
    $currency_code = commerce_default_currency();
  }
  $currency_setting = commerce_currency_load($currency_code);
  $currency_symbol = $currency_setting['symbol'];

  // Check if there are multiple units chosen, and keep a running tally of
  // the number of elements chosen.
  $multiple_chosen = FALSE;
  $chosen_unit_counter = 0;

  // Sort the types by the one who has the cheapest option.
  $sortorder = array();

  // Before building our output, we execute one preliminary run through the
  // types and units found, to gather some statistics and update sort order
  // by price.
  foreach ($units_per_type as $type => $units_per_price) {
    foreach ($units_per_price as $price => $j) {

      // Detect if units are chosen at each given price point for each type
      // by inspecting the form state's "quanity" value, if some are
      // selected, increment the counter.
      if (isset($form_state['values']) && isset($form_state['values'][$type][$price]['quantity'])) {
        $chosen_unit_counter += $form_state['values'][$type][$price]['quantity'];
      }

      // Build an array with the least expensive unit price per unit type.
      // This is used below to sort which type should appear first.
      if (!isset($sortorder[$type]) || $price < $sortorder[$type]) {
        $sortorder[$type] = $price;
      }
    }
  }
  if ($chosen_unit_counter > 1) {
    $multiple_chosen = TRUE;
  }

  // Reset the counter back to zero, so it can be used below as an incremental
  // index.
  $chosen_unit_counter = 0;

  // Sort the types by least expensive first.
  asort($sortorder);

  // Calculate the period.
  $nights = $form['end_date']['#value']
    ->diff($form['start_date']['#value'])->days;
  foreach ($sortorder as $type => $least_expensive_base_price) {

    // Load the units per price.
    $units_per_price = $units_per_type[$type];

    // Load the type obj and set a title.
    $type_obj = rooms_unit_type_load($type);

    // Decorate the available units by type as rows inside a table, which
    // sits inside a container wrapper.
    $form[$type] = array(
      '#type' => 'container',
      '#tree' => TRUE,
      '#attributes' => array(
        'class' => array(
          'rooms-search-result__unit-type',
        ),
      ),
    );
    $form[$type]['title'] = array(
      '#prefix' => '<h3 class="rooms-search-result__unit-type-name">',
      '#markup' => t($type_obj->label),
      '#suffix' => '</h3>',
    );
    $form[$type]['open-markup'] = array(
      '#markup' => '<table class="rooms-search-result__booking-form">',
    );

    // Sort by least expensive first.
    ksort($units_per_price, SORT_NUMERIC);
    foreach ($units_per_price as $price => $units) {
      $form[$type][$price] = array();
      $form = _rooms_booking_manager_load_description($form, $type_obj, $type, $price);
      $form = _rooms_booking_manager_load_price_info($form, $type_obj, $type, $price, $currency_code, $units_per_price, $units);
      $form = _rooms_booking_manager_display_book_button($form, $type, $price);

      // Display price options.
      $form[$type][$price]['field_start'] = array(
        '#markup' => '<tr id="rooms_' . $type . '_' . $price . '" style="display:none;"><td class="rooms-search-result__unit_options_wrapper" colspan="2">',
      );
      $form[$type][$price]['fieldset'] = array(
        '#prefix' => '<div class="rooms-search-result__unit_options form-wrapper" id="' . $type . '_' . $price . '_container">',
        '#type' => 'container',
        '#suffix' => '</div>',
      );
      if (isset($form_state['values'][$type][$price]['quantity'])) {
        $units_keys = array_keys($units);
        for ($c = 1; $c <= $form_state['values'][$type][$price]['quantity']; $c++) {

          // Looking for unit options.
          $rooms_unit_options = rooms_unit_get_unit_options($units[$units_keys[$c - 1]]['unit']);

          // Display each row as a fieldset.
          $form[$type][$price]['fieldset'][$c]['#type'] = 'fieldset';

          // If there are options or pricing is not "PER PERSON" add a css
          // class and remove fieldset style.
          if (empty($rooms_unit_options) && variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) != ROOMS_PER_PERSON) {
            $form[$type][$price]['fieldset'][$c]['#attributes']['class'][] = 'no-unit-fieldset';
          }

          // Display a clean title for each unit. If there are multiple units
          // chosen, add a cumulative index to the unit label. You can disable
          // this feature by overriding the string used below in your
          // settings.php file.
          // Eg:
          // $conf['locale_custom_strings_en']['']['Unit @num - @label'] = '@label';
          //
          $unit_label = $type_obj->label;
          if ($multiple_chosen) {
            $unit_label = rooms_string(t('Unit @num - @label', array(
              '@num' => ++$chosen_unit_counter,
              '@label' => $type_obj->label,
            )), $context = array(
              '#component' => 'units_results_fieldset_legend_label',
              '#purpose' => 'display_fieldset_label',
              '#data' => array(
                'chosen_unit_counter' => $chosen_unit_counter,
                'type' => $type_obj,
              ),
            ));
          }
          $form[$type][$price]['fieldset'][$c]['#title'] = $unit_label;

          // Add options checkboxes.
          foreach ($rooms_unit_options as $option) {
            $form = _rooms_booking_manager_add_options($form, $form_state, $type, $price, $c, $option);
          }
          $tmp_unit = $units[$units_keys[$c - 1]]['unit'];
          if (variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) == ROOMS_PER_PERSON) {
            $form = _rooms_booking_manager_handle_per_person_pricing($form, $form_state, $tmp_unit, $units, $units_keys, $c, $type, $price);
          }

          // When prices are shown as per person, display this one as a subtotal
          // for all people in the room.
          $unit_type_label = rooms_unit_get_types($units[$units_keys[$c - 1]]['unit']->type)->label;
          if (variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) == ROOMS_PER_PERSON) {
            $label = rooms_string(t('Subtotal'), $context = array(
              '#component' => 'units_per_type_form_subtotal_label',
              '#purpose' => 'display_base_subtotal_label',
              '#data' => array(
                'type' => $unit_type_label,
                'nights' => $nights,
                'unit_number' => $c,
              ),
            ));
          }
          else {
            $label = rooms_string(t('Price'), $context = array(
              '#component' => 'units_per_type_form_price_label',
              '#purpose' => 'display_base_price_label',
              '#data' => array(
                'type' => $unit_type_label,
                'nights' => $nights,
                'unit_number' => $c,
              ),
            ));
          }

          // Check for a deposit.
          $deposit_amount = rooms_booking_manager_check_for_deposit($price, $start_date);
          if (empty($deposit_amount)) {
            $price_amount = $price * 100;
            if (module_exists('commerce_multicurrency')) {
              $price_amount = commerce_currency_convert($price_amount, commerce_default_currency(), $currency_code);
            }
            $form[$type][$price]['fieldset'][$c]['price'] = array(
              '#prefix' => '<div class="rooms-search-result__unit-price" id="' . $type . '_' . $price . '_' . $c . '_price"><label>' . $label . ':</label> <span class="rooms-search-result__unit-price-amount">',
              '#markup' => commerce_currency_format($price_amount, $currency_code),
              '#suffix' => '</span></div>',
            );
          }
          else {
            $deposit_amount = $deposit_amount * 100;
            if (module_exists('commerce_multicurrency')) {
              $deposit_amount = commerce_currency_convert($deposit_amount, commerce_default_currency(), $currency_code);
            }
            $price_amount = $price * 100;
            if (module_exists('commerce_multicurrency')) {
              $price_amount = commerce_currency_convert($price_amount, commerce_default_currency(), $currency_code);
            }
            $form[$type][$price]['fieldset'][$c]['price'] = array(
              '#prefix' => '<div class="rooms-search-result__unit-price" id="' . $type . '_' . $price . '_' . $c . '_price"><label>' . $label . ':</label> <span class="rooms-search-result__unit-price-amount">',
              '#markup' => t('@@amount - Payable now: @deposit', array(
                '@amount' => commerce_currency_format($price_amount, $currency_code),
                '@deposit' => commerce_currency_format($deposit_amount, $currency_code),
              )),
              '#suffix' => '</span></div>',
            );
          }
          $price_modifiers = array();
          foreach (rooms_unit_get_unit_options($units[$units_keys[$c - 1]]['unit']) as $option) {
            $option_name = rooms_options_machine_name($option['name']);
            if ($option['type'] == ROOMS_OPTION_MANDATORY) {
              $quantity = 1;
              if (isset($form_state['values'][$type][$price]['fieldset'][$c][$option_name . ':quantity']) && $option['operation'] != ROOMS_REPLACE) {
                $quantity = $form_state['values'][$type][$price]['fieldset'][$c][$option_name . ':quantity'] + 1;
              }
              $price_modifiers[$option_name] = array(
                '#type' => ROOMS_DYNAMIC_MODIFIER,
                '#op_type' => $option['operation'],
                '#amount' => $option['value'],
                '#quantity' => $quantity,
              );
            }
            elseif (isset($form_state['values'][$type][$price]['fieldset'][$c][$option_name])) {
              $quantity = 1;
              if (isset($form_state['values'][$type][$price]['fieldset'][$c][$option_name . ':quantity']) && $option['operation'] != ROOMS_REPLACE) {
                $quantity = $form_state['values'][$type][$price]['fieldset'][$c][$option_name . ':quantity'] + 1;
              }
              if ($form_state['values'][$type][$price]['fieldset'][$c][$option_name] == 1) {
                if ($option['type'] != ROOMS_OPTION_ONREQUEST) {
                  $price_modifiers[$option_name] = array(
                    '#type' => ROOMS_DYNAMIC_MODIFIER,
                    '#op_type' => $option['operation'],
                    '#amount' => $option['value'],
                    '#quantity' => $quantity,
                  );
                }
              }
            }
          }
          if (isset($form_state['values'][$type][$price]['fieldset'][$c]['persons'])) {
            $group_size = $form_state['values'][$type][$price]['fieldset'][$c]['persons'];
          }
          else {
            $group_size = $tmp_unit->max_sleeps;
          }
          if (isset($form_state['values'][$type][$price]['fieldset'][$c]['children'])) {
            $group_size_children = $form_state['values'][$type][$price]['fieldset'][$c]['children'] + $tmp_unit->min_children;
          }
          else {
            $group_size_children = $tmp_unit->min_children;
          }
          $childrens_age = array();
          if (isset($form_state['values'][$type][$price]['fieldset'][$c]['persons'])) {
            for ($t = 1; $t <= $form_state['values'][$type][$price]['fieldset'][$c]['children']; $t++) {
              $childrens_age[] = $form_state['values'][$type][$price]['fieldset'][$c]['childrens_age'][$t];
            }
          }
          $booking_info = array(
            'start_date' => clone $start_date,
            'end_date' => clone $end_date,
            'unit' => $units[$units_keys[$c - 1]]['unit'],
            'booking_parameters' => array(
              'group_size' => $group_size,
              'group_size_children' => $group_size_children,
              'childrens_age' => $childrens_age,
            ),
          );

          // Price is calculated as 'Price per person per night'
          if (variable_get('rooms_price_calculation', ROOMS_PER_NIGHT) == ROOMS_PER_PERSON) {

            // Give other modules a chance to change the price modifiers.
            drupal_alter('rooms_price_modifier', $price_modifiers, $booking_info);

            // Apply price modifiers and replace unit price.
            $price_calendar = new UnitPricingCalendar($units[$units_keys[$c - 1]]['unit']->unit_id, $price_modifiers);
            $temp_end_date = clone $end_date;
            $temp_end_date
              ->sub(new DateInterval('P1D'));
            if (isset($form_state['values'][$type][$price]['fieldset'][$c]['persons'])) {
              if (variable_get('rooms_display_children', ROOMS_DISPLAY_CHILDREN_NO) == ROOMS_DISPLAY_CHILDREN) {
                $new_price = $price_calendar
                  ->calculatePrice($start_date, $temp_end_date, $form_state['values'][$type][$price]['fieldset'][$c]['persons'], $form_state['values'][$type][$price]['fieldset'][$c]['children'], $childrens_age);
              }
              else {
                $new_price = $price_calendar
                  ->calculatePrice($start_date, $temp_end_date, $form_state['values'][$type][$price]['fieldset'][$c]['persons']);
              }
            }
            else {
              $new_price = $price_calendar
                ->calculatePrice($start_date, $temp_end_date, $tmp_unit->max_sleeps);
            }
          }
          else {

            // Give other modules a chance to change the price modifiers.
            drupal_alter('rooms_price_modifier', $price_modifiers, $booking_info);

            // Apply price modifiers and replace unit price.
            $price_calendar = new UnitPricingCalendar($units[$units_keys[$c - 1]]['unit']->unit_id, $price_modifiers);

            // Let us make sure we remove a day.
            $temp_end_date = clone $end_date;
            $temp_end_date
              ->sub(new DateInterval('P1D'));
            $new_price = $price_calendar
              ->calculatePrice($start_date, $temp_end_date);
          }
          $new_price = $new_price['full_price'];
          $deposit_amount = rooms_booking_manager_check_for_deposit($new_price, $start_date);
          if (empty($deposit_amount)) {
            $new_price_amount = $new_price * 100;
            if (module_exists('commerce_multicurrency')) {
              $new_price_amount = commerce_currency_convert($new_price_amount, commerce_default_currency(), $currency_code);
            }

            // Replace old price with the new calculated value.
            $form[$type][$price]['fieldset'][$c]['price']['#markup'] = rooms_string(commerce_currency_format($new_price_amount, $currency_code), $context = array(
              '#component' => 'units_per_type_form',
              '#purpose' => 'display_room_recalculated_price',
              '#data' => array(
                'unit_id' => $units[$units_keys[$c - 1]]['unit']->unit_id,
                'unit_type' => $type_obj->label,
                'price' => $price,
                'new_price' => $new_price,
                'currency_symbol' => $currency_symbol,
                'amount' => $price,
                'units' => $units_per_price,
              ),
            ));
          }
          else {
            $new_price_amount = $new_price * 100;
            if (module_exists('commerce_multicurrency')) {
              $new_price_amount = commerce_currency_convert($new_price_amount, commerce_default_currency(), $currency_code);
            }
            $deposit_amount = $deposit_amount * 100;
            if (module_exists('commerce_multicurrency')) {
              $deposit_amount = commerce_currency_convert($deposit_amount, commerce_default_currency(), $currency_code);
            }

            // Replace old price with the new calculated value.
            $form[$type][$price]['fieldset'][$c]['price']['#markup'] = rooms_string(t('@amount - Payable now: @deposit', array(
              '@amount' => commerce_currency_format($new_price_amount, $currency_code),
              '@deposit' => commerce_currency_format($deposit_amount, $currency_code),
            )), $context = array(
              '#component' => 'units_per_type_form',
              '#purpose' => 'display_room_recalculated_price',
              '#data' => array(
                'unit_id' => $units[$units_keys[$c - 1]]['unit']->unit_id,
                'unit_type' => $type_obj->label,
                'price' => $price,
                'new_price' => $new_price,
                'currency_symbol' => $currency_symbol,
                'amount' => $price,
                'units' => $units_per_price,
              ),
            ));
          }
        }
      }
      $form[$type][$price]['close-row'] = array(
        '#markup' => '</td></tr>',
      );
    }
    $form[$type]['close-markup'] = array(
      '#markup' => '</table> <!-- /.rooms-search-result__booking-form -->',
    );
  }
  $form['actions'] = array(
    '#type' => 'actions',
    '#tree' => FALSE,
    '#weight' => 400,
    '#attributes' => array(
      'class' => array(
        'rooms-search-result__actions',
      ),
    ),
  );
  $form['actions']['place_booking'] = array(
    '#type' => 'submit',
    '#value' => variable_get_value('rooms_booking_manager_button_place_booking'),
    '#submit' => array(
      'book_units_per_type_form_submit',
    ),
  );

  // We append the validate handler to #validate in case a form callback_wrapper
  // is used to add validate handlers earlier.
  $form['#validate'][] = 'book_units_per_type_form_validate';
  return $form;
}

/**
 * AJAX callback on booking search results page when quantity change.
 */
function rooms_booking_manager_quantity_change_callback(&$form, $form_state) {
  list($type, $price) = preg_split('/[\\[(.)\\]]/', $form_state['triggering_element']['#name']);

  // Show availability of individual units.
  if ($price == '') {
    return $form['new_price'];
  }
  else {
    return $form[$type][$price]['fieldset'];
  }
}

/**
 * Ajax callback on booking search results page when an Options state change.
 */
function rooms_booking_manager_options_change_callback(&$form, $form_state) {
  list($type, $price, $tmp, $fieldset, $tmp, $index, $tmp, $option) = preg_split('/[\\[(.)\\]]/', $form_state['triggering_element']['#name']);
  $commands = array();

  // Show availability of individual units.
  if ($fieldset == '') {
    $option = $price;
    $commands[] = ajax_command_replace('#unit_' . $form['unit_id']['#value'] . '_' . $option . '_quantity', render($form['options'][$option . ':quantity']));
    $commands[] = ajax_command_replace('#unit_' . $form['unit_id']['#value'] . '_price', render($form['new_price']));
  }
  else {
    $commands[] = ajax_command_replace('#' . $type . '_' . $price . '_' . $index . '_' . $option . '_quantity', render($form[$type][$price]['fieldset'][$index][$option . ':quantity']));
    $commands[] = ajax_command_replace('#' . $type . '_' . $price . '_' . $index . '_price', render($form[$type][$price][$fieldset][$index]['price']));
  }
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * AJAX callback on booking search results page when Children selector change.
 */
function rooms_booking_manager_children_change_callback(&$form, $form_state) {
  list($type, $price, $tmp, $fieldset, $tmp, $index) = preg_split('/[\\[(.)\\]]/', $form_state['triggering_element']['#name']);
  $commands = array();

  // Show availability of individual units.
  if ($price == '') {
    $commands[] = ajax_command_replace('#unit_' . $form['unit_id']['#value'] . '_childrensage', render($form['childrens_age']));
    $commands[] = ajax_command_replace('#unit_' . $form['unit_id']['#value'] . '_price', render($form['new_price']));
  }
  else {
    $commands[] = ajax_command_replace('#' . $type . '_' . $price . '_' . $index . '_childrensage', render($form[$type][$price][$fieldset][$index]['childrens_age']));
    $commands[] = ajax_command_replace('#' . $type . '_' . $price . '_' . $index . '_price', render($form[$type][$price][$fieldset][$index]['price']));
  }
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Validate callback for book_units_per_type_form form.
 */
function book_units_per_type_form_validate(&$form, &$form_state) {
  if (isset($form_state['storage']['values'])) {
    $form_state['values'] = $form_state['storage']['values'];
    unset($form_state['storage']['values']);
  }
  if (isset($form_state['complete form']['comments'])) {
    return;
  }
  foreach ($form_state['values'] as $type) {
    if (is_array($type)) {
      foreach ($type as $price_level) {
        if (isset($price_level['quantity'])) {
          if ($price_level['quantity'] != 0) {
            return;
          }
        }
      }
    }
  }
  form_set_error('', variable_get_value('rooms_booking_manager_error_select_unit'));
}

/**
 * Submit callback for book_units_per_type_form form.
 *
 * @todo - check that original availability still holds
 * @todo - fix the user ownership of products
 */
function book_units_per_type_form_submit(&$form, &$form_state) {
  module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.commerce');
  global $user;
  $start_date = $form_state['values']['start_date'];
  $end_date = $form_state['values']['end_date'];
  $booking_parameters = unserialize($form_state['values']['booking_parameters']);
  $b_units = $form_state['values']['b_units'];

  // Create an "order" based on the form submitted.
  $order = array();
  foreach ($form_state['values'] as $type => $value) {
    if (is_array($value)) {
      foreach ($value as $value2) {
        if (!empty($value2['quantity'])) {
          $order[$type] = $value;
        }
      }
    }
  }
  if (variable_get('rooms_checkout_style', ROOMS_COMMERCE_CHECKOUT) == ROOMS_ENQ_CHECKOUT) {
    $sd = $start_date
      ->format('Y-m-d');
    $ed = $end_date
      ->format('Y-m-d');
    $form_state['redirect'] = array(
      "enquiry/{$sd}/{$ed}",
      array(
        'query' => array(
          'order' => $order,
        ),
      ),
    );
    return;
  }

  // Check the rooms availability and match the order against actual rooms.
  $agent = new AvailabilityAgent($start_date, $end_date, $booking_parameters, $b_units, array());
  $agent
    ->setValidStates(array_keys(array_filter(variable_get('rooms_valid_availability_states', drupal_map_assoc(array(
    ROOMS_AVAILABLE,
    ROOMS_ON_REQUEST,
  ))))));
  $units_per_type = $agent
    ->checkAvailability();

  // We are going to check that this is still true.
  foreach ($order as $type => $price_serving) {
    foreach ($price_serving as $price_level => $unit_order) {
      if ($unit_order['quantity'] > 0) {
        for ($i = 1; $i <= $unit_order['quantity']; $i++) {
          $unit = array_shift($units_per_type[$type][$price_level]);
          $childrens_age = array();
          if (isset($form_state['values'][$type][$price_level]['fieldset'][$i]['children'])) {
            for ($t = 1; $t <= $form_state['values'][$type][$price_level]['fieldset'][$i]['children']; $t++) {
              $childrens_age[] = $form_state['values'][$type][$price_level]['fieldset'][$i]['childrens_age'][$t];
            }
          }
          $persons = isset($form_state['values'][$type][$price_level]['fieldset'][$i]['persons']) ? $form_state['values'][$type][$price_level]['fieldset'][$i]['persons'] : (isset($booking_parameters[$i]['adults']) ? $booking_parameters[$i]['adults'] : $unit['unit']->min_sleeps);
          $children = isset($form_state['values'][$type][$price_level]['fieldset'][$i]['children']) ? $form_state['values'][$type][$price_level]['fieldset'][$i]['children'] + $unit['unit']->min_children : (isset($booking_parameters[$i]['children']) ? $booking_parameters[$i]['children'] : 0);

          // Fill group_size with unit size.
          $group_size = array(
            'adults' => $persons,
            'children' => $children,
            'childrens_age' => $childrens_age,
          );

          // Convert Price options in Price modifiers.
          $price_modifiers = array();
          foreach (rooms_unit_get_unit_options($unit['unit']) as $option) {
            if (isset($form_state['values'][$type][$price_level]['fieldset'][$i][rooms_options_machine_name($option['name'])])) {
              if ($form_state['values'][$type][$price_level]['fieldset'][$i][rooms_options_machine_name($option['name'])] == 1) {
                $quantity = 1;
                if (isset($form_state['values'][$type][$price_level]['fieldset'][$i][rooms_options_machine_name($option['name']) . ':quantity']) && $option['operation'] != ROOMS_REPLACE) {
                  $quantity = $form_state['values'][$type][$price_level]['fieldset'][$i][rooms_options_machine_name($option['name']) . ':quantity'] + 1;
                }
                if ($option['type'] == ROOMS_OPTION_ONREQUEST) {
                  $option['value'] = 0;
                }
                $price_modifiers[rooms_options_machine_name($option['name'])] = array(
                  '#name' => $option['name'],
                  '#type' => ROOMS_DYNAMIC_MODIFIER,
                  '#op_type' => $option['operation'],
                  '#amount' => $option['value'],
                  '#quantity' => $quantity,
                );
              }
            }
          }

          // Check if there are line_items with overlapping dates.
          module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.confirmation_override');
          $line_items = rooms_booking_manager_find_overlapping_line_items($start_date, $end_date, $unit['unit']->unit_id);
          if (!empty($line_items)) {
            if (isset($form_state['storage']['confirm'])) {
              $commerce_order = commerce_cart_order_load($user->uid);
              foreach ($line_items as $line_item_id) {
                commerce_cart_order_product_line_item_delete($commerce_order, $line_item_id);
              }
            }
            else {

              // Save the current form_state.
              $form_state['storage']['values'] = $form_state['values'];

              // Rebuild this form to show the confirmation form.
              $form_state['storage']['confirm'] = TRUE;
              $form_state['rebuild'] = TRUE;
              return;
            }
          }

          // Create line item.
          $line_item = rooms_create_line_item($unit, $agent, $group_size, $price_modifiers);

          // Add line item to cart.
          if (!empty($line_item)) {
            $line_item = commerce_cart_product_add($user->uid, $line_item, FALSE);
          }
        }
      }
    }
  }

  // Refresh line items price and redirect to bookings page.
  commerce_cart_order_refresh(commerce_cart_order_load($user->uid));
  $form_state['redirect'] = variable_get('rooms_booking_manager_post_add_booking_path', 'bookings');
}

/**
 * This function redirects the user back to the search box and sets up the
 * values of the search as a convenient way to modify the search.
 */
function rooms_booking_manager_change_search_form_submit($form, &$form_state) {
  $booking_parameters = is_array(unserialize($form_state['values']['booking_parameters'])) ? unserialize($form_state['values']['booking_parameters']) : array();
  $b_parameters = array();
  foreach ($booking_parameters as $b_key => $param) {
    foreach ($param as $key => $value) {
      if ($key == 'adults') {
        $b_parameters['rooms_group_size' . $b_key] = $value;
      }
      else {
        $b_parameters['rooms_' . $key . $b_key] = $value;
      }
    }
  }
  $query = rooms_booking_manager_get_plugin_parameters($form_state);

  // Build query parameters from the provided form fields.
  $query['rooms_start_date'] = $form_state['values']['start_date'];
  $query['rooms_end_date'] = $form_state['values']['end_date'];
  if (isset($form_state['values']['b_units']) && !empty($form_state['values']['b_units'])) {
    $query['rooms_b_units'] = $form_state['values']['b_units'];
  }
  if (isset($form_state['values']['type']) && !empty($form_state['values']['type'])) {
    $query['type'] = $form_state['values']['type'];
  }
  $query += $b_parameters;

  // Redirect back to the search page.
  $form_state['redirect'] = array(
    'booking',
    array(
      'query' => $query,
    ),
  );
}

/**
 * Retrieves parameters defined by plugins and return them as an array.
 *
 * @param $form_state
 * @return array
 */
function rooms_booking_manager_get_plugin_parameters($form_state) {
  $plugins_values = array();
  $query = array();
  ctools_include('plugins');
  $filters = ctools_get_plugins('rooms_booking', 'availabilityagent_filter');
  foreach ($filters as $filter) {
    $class = ctools_plugin_get_class($filter, 'handler');
    $plugins_values += $class::availabilitySearchParameters();
  }

  // Collect the values for booking parameters.
  foreach ($plugins_values as $value) {
    if (isset($form_state['values'][$value])) {
      $query[$value] = is_array($form_state['values'][$value]) ? implode(',', $form_state['values'][$value]) : $form_state['values'][$value];
    }
  }
  return $query;
}

/**
 * Loads a DateTime object from a string.
 *
 * @param string $start_date
 *   Expects to see a date in the form Y-m-d
 *
 * @return DateTime
 *   Object or null if invalid
 */
function start_date_load($start_date) {
  $start_date = check_plain($start_date);

  // Try to create a date time object.
  try {
    $sd = new DateTime($start_date);
  } catch (Exception $e) {
    $sd = 0;
  }
  return $sd;
}

/**
 * Loads a DateTime object from a string.
 *
 * @param string $end_date
 *   Expects to see a date in the form Y-m-d
 *
 * @return DateTime
 *   Object or null if invalid
 */
function end_date_load($end_date) {
  $end_date = check_plain($end_date);

  // Try to create a date time object.
  try {
    $ed = new DateTime($end_date);
  } catch (Exception $e) {
    $ed = 0;
  }
  return $ed;
}

/**
 * Implements hook_theme().
 */
function rooms_booking_manager_theme() {
  return array(
    'rooms_booking_results' => array(
      'template' => 'rooms_booking_results',
    ),
    'rooms_booking_override_confirmation_page' => array(
      'template' => 'rooms_booking_override_confirmation_page',
    ),
    'rooms_booking_email' => array(
      'template' => 'rooms_booking_email',
    ),
    'rooms_booking_enquiry_confirmation' => array(
      'template' => 'rooms_booking_enquiry_confirmation',
      'variables' => array(
        'message' => NULL,
      ),
    ),
  );
}

/**
 * Implements hook_commerce_checkout_complete().
 */
function rooms_booking_manager_commerce_checkout_complete($order) {
  $profile = commerce_customer_profile_load($order->commerce_customer_billing[LANGUAGE_NONE][0]['profile_id']);

  // Cycle through orders looking for booking products.
  foreach ($order->commerce_line_items as $lang => $item) {

    // First check all proposed bookings a final time to ensure they do not conflict with any existing bookings.
    foreach ($item as $item_id) {
      $line_item = commerce_line_item_load($item_id['line_item_id']);
      if ($line_item->type == 'rooms_booking') {
        $uc = new \UnitCalendar($line_item->rooms_booked_unit_id[LANGUAGE_NONE][0]['value']);
        $start_date = new DateTime($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value']);
        $end_date = new DateTime($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value2']);
        $adjusted_end_date = clone $end_date;
        $adjusted_end_date
          ->modify('-1 day');
        $states_confirmed = $uc
          ->getStates($start_date, $adjusted_end_date);
        $valid_states = array_keys(array_filter(variable_get('rooms_valid_availability_states', drupal_map_assoc(array(
          ROOMS_AVAILABLE,
          ROOMS_ON_REQUEST,
        )))));
        $valid_states = array_merge($valid_states, array(
          ROOMS_UNCONFIRMED_BOOKINGS,
        ));
        $state_diff_confirmed = array_diff($states_confirmed, $valid_states);
        if (count($state_diff_confirmed) > 0) {

          // A conflicting confirmed booking was found, bail out.
          drupal_set_message(t('Unfortunately, availability for your selected bookings has changed since placing them in your cart. Please re-start your search.'));
          $bookings_url = url('bookings', array(
            'absolute' => TRUE,
          ));
          drupal_goto($bookings_url);
        }
      }
    }

    // If we got this far, it's safe to go ahead and create the bookings.
    foreach ($item as $item_id) {
      $line_item = commerce_line_item_load($item_id['line_item_id']);
      if ($line_item->type == 'rooms_booking') {

        // Create a booking.
        $booking_type = variable_get('rooms_booking_type', 'standard_booking');
        $booking = rooms_booking_create(array(
          'type' => $booking_type,
        ));
        $booking->created = time();
        $booking->start_date = substr($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value'], 0, 10);
        $booking->end_date = substr($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value2'], 0, 10);

        // Associate it with this order.
        $booking->order_id = $order->order_number;
        $booking->unit_id = $line_item->rooms_booked_unit_id[LANGUAGE_NONE][0]['value'];

        // Load the unit to get its type.
        $unit = rooms_unit_load($booking->unit_id);
        $booking->unit_type = $unit->type;
        $booking->customer_id = $order->commerce_customer_billing[LANGUAGE_NONE][0]['profile_id'];
        $booking->name = $profile->commerce_customer_address[LANGUAGE_NONE][0]['name_line'];
        if (isset($line_item->rooms_booking_options[LANGUAGE_NONE])) {
          foreach ($line_item->rooms_booking_options[LANGUAGE_NONE] as $option) {
            $option_name = rooms_options_machine_name($option['name']);
            $booking->data[$option_name] = 1;
            $booking->data[$option_name . ':quantity'] = $option['quantity'] - 1;
          }
        }
        if (isset($line_item->rooms_booking_number_people[LANGUAGE_NONE])) {
          $booking->data['group_size'] = $line_item->rooms_booking_number_people[LANGUAGE_NONE][0]['value'];
          $booking->data['group_size_children'] = $line_item->rooms_booking_number_people[LANGUAGE_NONE][1]['value'];
        }
        if (isset($line_item->rooms_booking_children_ages[LANGUAGE_NONE])) {
          $booking->data['childrens_age'] = $line_item->rooms_booking_children_ages[LANGUAGE_NONE];
        }
        $booking->price = $line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount'];
        $booking->booking_status = 1;
        $booking->uid = $unit->uid;
        $booking
          ->save();

        // Line item 'Entity Reference field' that points to the booking.
        $line_item->rooms_booking_reference[LANGUAGE_NONE][0]['target_id'] = $booking->booking_id;
        commerce_line_item_save($line_item);

        // Now let us lock availability
        // First - we get an event id.
        $id = rooms_availability_assign_id($booking->booking_id, '1');

        // Set the start and end dates for the booking event.
        // They are the same as the booking above but the end date is not the
        // departure date rather it is the last night spend in the room.
        $sd = new DateTime($booking->start_date);

        // End date is actually a day less.
        $ed = new DateTime($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value2']);
        $ed
          ->sub(new DateInterval('P1D'));

        // Create a booking event.
        $be = new BookingEvent($booking->unit_id, $id, $sd, $ed);

        // Call up the UnitCalendar for this unit and add the event to it.
        $rc = new UnitCalendar($booking->unit_id);
        $responses = $rc
          ->updateCalendar(array(
          $be,
        ));

        // If the event addition was succesful lock the event.
        if ($responses[$id] == ROOMS_UPDATED) {
          $be
            ->lock();
          watchdog('rooms_booking_manager', 'Unit availability has been updated.', array(), WATCHDOG_NOTICE);
        }
        else {
          watchdog('rooms_booking_manager', 'Unit availability could not be updated.', array(), WATCHDOG_ERROR);
        }
      }
    }
  }
}

/**
 * Implements hook_commerce_order_state_info().
 */
function rooms_booking_manager_commerce_order_state_info() {
  $order_states = array();
  $order_states['rooms_unit_booking'] = array(
    'name' => 'rooms_unit_booking',
    'title' => t('Rooms Booking'),
    'description' => t('Orders related to Rooms bookings.'),
    'weight' => 0,
    'default_status' => 'confirmed',
  );
  return $order_states;
}

/**
 * Implements hook_commerce_order_status_info().
 */
function rooms_booking_manager_commerce_order_status_info() {
  $order_statuses = array();
  $order_statuses['rooms_unit_confirmed'] = array(
    'name' => 'rooms_unit_confirmed',
    'title' => t('Booking Confirmed'),
    'state' => 'rooms_unit_booking',
  );
  $order_statuses['rooms_unit_canceled'] = array(
    'name' => 'rooms_unit_canceled',
    'title' => t('Booking Canceled'),
    'state' => 'rooms_unit_booking',
  );
  $order_statuses['rooms_unit_pending'] = array(
    'name' => 'rooms_unit_pending',
    'title' => t('Booking Pending'),
    'state' => 'rooms_unit_booking',
  );
  return $order_statuses;
}

/**
 * Submit callback when cancelling the checkout process.
 */
function rooms_booking_manager_commerce_checkout_form_cancel_submit($form, &$form_state) {
  $form_state['redirect'] = 'bookings';
}

/**
 * Implements hook_form_alter().
 */
function rooms_booking_manager_form_alter(&$form, &$form_state, $form_id) {

  // Commerce checkout form alters.
  if ($form_id == 'commerce_checkout_form_checkout') {
    rooms_booking_manager_alter_commerce_checkout_form_checkout($form, $form_state, $form_id);
  }

  // Commerce cart view for booking form alters.
  if (strpos($form_id, 'views_form_booking_cart_form_') === 0) {
    rooms_booking_manager_views_form_booking_cart_form_($form, $form_state, $form_id);
  }

  // Adding extra settings to rooms booking settings.
  if ($form_id == 'rooms_booking_settings') {
    rooms_booking_manager_alter_rooms_booking_settings($form, $form_state, $form_id);
  }

  // Remove the option to add a booking line item on the administrative "add
  // order" page. (/admin/commerce/orders/add)
  if ($form_id == 'commerce_order_ui_order_form') {
    rooms_booking_manager_alter_commerce_order_ui_order_form($form, $form_state, $form_id);
  }
  if ($form_id == 'rooms_booking_edit_form') {
    rooms_booking_manager_alter_rooms_booking_edit_form($form, $form_state, $form_id);
  }
}

/**
 * Alters for the 'commerce_checkout_form_checkout' form.
 */
function rooms_booking_manager_alter_commerce_checkout_form_checkout(&$form, &$form_state, $form_id) {

  // Extract the View and display keys from the cart contents pane setting.
  list($view_id, $display_id) = explode('|', variable_get('commerce_cart_contents_pane_view', 'commerce_cart_summary|default'));
  global $user;
  $order = commerce_cart_order_load($user->uid);
  $form['cart_contents']['cart_contents_view'] = array(
    '#markup' => commerce_embed_view('booking_checkout_form', 'booking_checkout_form', array(
      $order->order_id,
    )),
  );
  $form['buttons']['cancel']['#submit'][] = 'rooms_booking_manager_commerce_checkout_form_cancel_submit';
}

/**
 * Alters for the 'views_form_booking_cart_form_*' form.
 */
function rooms_booking_manager_views_form_booking_cart_form_(&$form, &$form_state, $form_id) {
  unset($form['actions']['submit']);
  $form['#action'] = str_replace('cart', 'bookings', $form['#action']);

  // Change any Delete buttons to say Remove.
  if (!empty($form['edit_delete'])) {
    foreach (element_children($form['edit_delete']) as $key) {

      // Load and wrap the line item to have the title in the submit phase.
      if (!empty($form['edit_delete'][$key]['#line_item_id'])) {
        $line_item_id = $form['edit_delete'][$key]['#line_item_id'];
        $form_state['line_items'][$line_item_id] = commerce_line_item_load($line_item_id);
        $form['edit_delete'][$key]['#value'] = variable_get_value('rooms_booking_manager_button_remove');
        $form['edit_delete'][$key]['#submit'] = array_merge($form['#submit'], array(
          'commerce_cart_line_item_delete_form_submit',
        ));
      }
    }
  }
  $form['actions']['checkout'] = array(
    '#type' => 'submit',
    '#value' => variable_get_value('rooms_booking_manager_button_checkout'),
    '#weight' => 5,
    '#access' => user_access('access checkout'),
    '#submit' => array_merge($form['#submit'], array(
      'commerce_checkout_line_item_views_form_submit',
    )),
  );
}

/**
 * Alters for the 'rooms_booking_settings' form.
 */
function rooms_booking_manager_alter_rooms_booking_settings(&$form, &$form_state, $form_id) {
  $form['rooms_checkout_settings'] = array(
    '#type' => 'fieldset',
    '#group' => 'rooms_settings',
    '#title' => t('Rooms checkout settings'),
  );
  $form['rooms_checkout_settings']['rooms_checkout_style'] = array(
    '#type' => 'radios',
    '#title' => t('Checkout presentation style'),
    '#options' => array(
      ROOMS_COMMERCE_CHECKOUT => t('Commerce checkout'),
      ROOMS_ENQ_CHECKOUT => t('Enquiry checkout'),
    ),
    '#default_value' => variable_get('rooms_checkout_style', ROOMS_COMMERCE_CHECKOUT),
  );
  $form['rooms_checkout_settings']['commerce_section'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#title' => t('Commerce checkout cart availability settings'),
    '#states' => array(
      'visible' => array(
        ':input[name="rooms_checkout_style"]' => array(
          'value' => ROOMS_COMMERCE_CHECKOUT,
        ),
      ),
    ),
  );
  $form['rooms_checkout_settings']['commerce_section']['rooms_use_commerce_filter'] = array(
    '#type' => 'checkbox',
    '#title' => t('Do not show units as available if they are in another user\'s cart'),
    '#options' => rooms_assoc_range(0, 1),
    '#description' => t('If this box is checked, Rooms will show units as unavailable once a booking including them has been placed in a user\'s cart. If it is unchecked, multiple users may place the same unit in their cart, and the first user to check out complete their order will successfully complete their booking. For scenarios such as hotels with multiple units of the same type it is recommended to enable this.'),
    '#default_value' => variable_get('rooms_use_commerce_filter', '1'),
  );
  $form['rooms_checkout_settings']['enquiry_section'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#title' => t('Enquiry checkout form settings'),
    '#description' => t('Select the fields that will be shown to the user in the enquiry form page. (name and email are required)'),
    '#states' => array(
      'visible' => array(
        ':input[name="rooms_checkout_style"]' => array(
          'value' => ROOMS_ENQ_CHECKOUT,
        ),
      ),
    ),
  );
  $form['rooms_checkout_settings']['enquiry_section']['rooms_enquiry_form_address'] = array(
    '#prefix' => '<div class="container-inline">',
    '#type' => 'checkbox',
    '#title' => t('Full address fields'),
    '#default_value' => variable_get('rooms_enquiry_form_address', 1),
  );
  $form['rooms_checkout_settings']['enquiry_section']['rooms_enquiry_form_address_required'] = array(
    '#suffix' => '</div>',
    '#type' => 'checkbox',
    '#title' => t('Required'),
    '#default_value' => variable_get('rooms_enquiry_form_address_required', 1),
    '#states' => array(
      'visible' => array(
        ':input[name="rooms_enquiry_form_address"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $form['rooms_checkout_settings']['enquiry_section']['rooms_enquiry_form_comments'] = array(
    '#prefix' => '<div class="container-inline">',
    '#type' => 'checkbox',
    '#title' => t('Comments field'),
    '#default_value' => variable_get('rooms_enquiry_form_comments', 1),
  );
  $form['rooms_checkout_settings']['enquiry_section']['rooms_enquiry_form_comments_required'] = array(
    '#suffix' => '</div>',
    '#type' => 'checkbox',
    '#title' => t('Required'),
    '#default_value' => variable_get('rooms_enquiry_form_comments_required', 1),
    '#states' => array(
      'visible' => array(
        ':input[name="rooms_enquiry_form_comments"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $form['rooms_checkout_settings']['enquiry_section']['rooms_booking_manager_enquiry_form_confirmation'] = array(
    '#type' => 'textarea',
    '#title' => t('Confirmation message'),
    '#default_value' => variable_get_value('rooms_booking_manager_enquiry_form_confirmation'),
  );
  $form['rooms_checkout_settings']['rooms_price_calculation'] = array(
    '#type' => 'radios',
    '#title' => t('Price calculation'),
    '#options' => array(
      ROOMS_PER_NIGHT => t('Per unit per night'),
      ROOMS_PER_PERSON => t('Per person per night'),
    ),
    '#default_value' => variable_get('rooms_price_calculation', ROOMS_PER_NIGHT),
  );
  $form['rooms_checkout_settings']['rooms_manually_booking_create_order'] = array(
    '#type' => 'checkbox',
    '#title' => t('Create orders for manually generated bookings'),
    '#options' => rooms_assoc_range(0, 1),
    '#description' => t('This will create a Commerce order for bookings created via the admin interface of Rooms.'),
    '#default_value' => variable_get('rooms_manually_booking_create_order', '1'),
  );
  rooms_booking_manager_deposit_config_form($form, $form_state);
  $booking_types = rooms_booking_get_types();
  $options = array();
  foreach ($booking_types as $type) {
    $options[$type->type] = $type->label;
  }
  $form['rooms_booking_settings']['rooms_advance_bookings_period'] = array(
    '#type' => 'rules_duration',
    '#title' => t('Advance Bookings'),
    '#description' => t('This will limit how far in the future bookings can be made. If you
    would like to allow specific rules to not have any limitations they should be
    assigned the "Book in advance without time limitations" permission.'),
    '#default_value' => variable_get('rooms_advance_bookings_period', 15552000),
  );
  $form['rooms_booking_settings']['rooms_booking_type'] = array(
    '#type' => 'select',
    '#title' => t('Active Booking type'),
    '#options' => $options,
    '#description' => t('The booking type created by Commerce.'),
    '#default_value' => variable_get('rooms_booking_type', 'standard_booking'),
  );
  $form['rooms_search_settings'] = array(
    '#type' => 'fieldset',
    '#group' => 'rooms_settings',
    '#title' => t('Rooms availability search settings'),
  );
  $form['rooms_search_settings']['rooms_presentation_style'] = array(
    '#type' => 'radios',
    '#title' => t('Results Presentation Mode'),
    '#description' => t('Choose whether to display results grouped by unit type or as single units.'),
    '#options' => array(
      ROOMS_PER_TYPE => t('Show availability on a per-type basis.'),
      ROOMS_INDIVIDUAL => t('Show availability of individual units.'),
    ),
    '#default_value' => variable_get('rooms_presentation_style', ROOMS_PER_TYPE),
  );
  $form['rooms_search_settings']['rooms_booking_manager_search_form_max_group_size'] = array(
    '#type' => 'select',
    '#title' => t('Maximum group size to display'),
    '#description' => t('Select the maximum group size to display in the availability search form select list'),
    '#options' => rooms_assoc_range(1, 20),
    '#default_value' => variable_get('rooms_booking_manager_search_form_max_group_size', 8),
  );
  $form['rooms_search_settings']['rooms_booking_manager_search_form_units'] = array(
    '#type' => 'select',
    '#title' => t('Number of units to display'),
    '#description' => t('Select the maximum number of units to display in the availability search form select list'),
    '#options' => rooms_assoc_range(1, 8),
    '#default_value' => variable_get('rooms_booking_manager_search_form_units', 6),
  );
  $form['rooms_search_settings']['rooms_display_children'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display children choice in availability search'),
    '#description' => t('Select whether both group size and children can be shown.'),
    '#default_value' => variable_get('rooms_display_children', ROOMS_DISPLAY_CHILDREN_NO),
  );
  $form['rooms_search_settings']['rooms_booking_manager_type_selector'] = array(
    '#type' => 'checkbox',
    '#description' => t('Display a drop-down list of unit types for filtering the availability search.'),
    '#title' => t('Display unit type selector in availability search'),
    '#default_value' => variable_get('rooms_booking_manager_type_selector', ROOMS_DISPLAY_TYPE_SELECTOR_NO),
  );
  $form['rooms_search_settings']['rooms_display_unit_type_selector'] = array(
    '#type' => 'fieldset',
    '#title' => t('Valid unit types'),
    '#states' => array(
      'visible' => array(
        '#edit-rooms-booking-manager-type-selector' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $unit_types = variable_get('rooms_unit_type_selector', array());
  $form['rooms_search_settings']['rooms_display_unit_type_selector']['rooms_unit_type_selector'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Select unit types to show to user in the Unit-Type selector.'),
    '#group' => 'rooms_display_unit_type_selector',
    '#options' => rooms_unit_types_ids(),
    '#default_value' => array_keys($unit_types),
  );
  $form['rooms_booking_settings']['rooms_valid_availability_states'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Valid availability states'),
    '#description' => t('Select the states for which units should show as available in a search.'),
    '#options' => array(
      ROOMS_AVAILABLE => t('Units marked as available.'),
      ROOMS_ON_REQUEST => t('Units marked as available on request.'),
    ),
    '#default_value' => variable_get('rooms_valid_availability_states', array(
      ROOMS_AVAILABLE,
      ROOMS_ON_REQUEST,
    )),
  );
  $form['rooms_admin_settings']['rooms_date_format'] = array(
    '#type' => 'item',
    '#title' => t('Rooms PHP Date Format'),
    '#description' => t("A custom date format for Booking labels, search summary and calendar pop-ups. Define a php date format string like 'm-d-Y' (see <a href=\"@link\">http://php.net/date</a> for more details).", array(
      '@link' => 'http://php.net/date',
    )),
  );
  $form['rooms_admin_settings']['rooms_date_format']['rooms_date_format'] = array(
    '#type' => 'textfield',
    '#size' => 12,
    '#prefix' => '<div class="container-inline form-item">' . t('Date format') . ': &nbsp;',
    '#suffix' => '</div>',
    '#default_value' => variable_get('rooms_date_format', 'd-m-Y'),
  );
  $form['#validate'][] = 'rooms_booking_manager_alter_rooms_booking_settings_validate';
}

/**
 * Validate the form.
 */
function rooms_booking_manager_alter_rooms_booking_settings_validate($form, &$form_state) {

  // Delete unchecked items.
  $form_state['values']['rooms_unit_type_selector'] = array_diff($form_state['values']['rooms_unit_type_selector'], array(
    0,
  ));
}

/**
 * Form snippet to configure deposit configuration form.
 */
function rooms_booking_manager_deposit_config_form(&$form, $form_state) {
  $deposit = rules_config_load('rooms_booking_manager_deposit');
  if ($deposit) {
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_enabled'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow bookings based on a deposit'),
      '#options' => rooms_assoc_range(0, 1),
      '#description' => t('Allow guests to make bookings by paying a deposit (percentage or fixed amount) instead of the full booking price of their stay.'),
      '#default_value' => $deposit->active,
    );
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset'] = array(
      '#type' => 'fieldset',
      '#title' => t('Payment deposit settings'),
      '#states' => array(
        'visible' => array(
          '#edit-rooms-booking-manager-deposit-enabled' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_type'] = array(
      '#type' => 'radios',
      '#title' => t('Select the type of deposit'),
      '#options' => array(
        'commerce_line_item_unit_price_amount' => t('Fixed amount deposit'),
        'commerce_line_item_unit_price_multiply' => t('Percentage deposit'),
      ),
      '#default_value' => 'commerce_line_item_unit_price_amount',
    );
    $fixed_amount = $multiply_amount = NULL;
    foreach ($deposit as $action) {
      if ($action instanceof RulesAction) {
        if ($action
          ->getElementName() == 'commerce_line_item_unit_price_amount') {
          $fixed_amount = $action->settings['amount'];
        }
        elseif ($action
          ->getElementName() == 'commerce_line_item_unit_price_multiply') {
          $multiply_amount = $action->settings['amount'];
        }
        $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_type']['#default_value'] = $action
          ->getElementName();
      }
    }
    list($prefix, $suffix) = explode('@amount', t('Guests must pay a fixed amount of @amount @currency at checkout to secure booking.', array(
      '@currency' => commerce_default_currency(),
    )));
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_fixed'] = array(
      '#type' => 'textfield',
      '#size' => 2,
      '#field_prefix' => $prefix,
      '#field_suffix' => $suffix,
      '#default_value' => $fixed_amount ? $fixed_amount / 100 : variable_get('rooms_booking_manager_deposit_fixed', 100),
      '#attributes' => array(
        'placeholder' => variable_get('rooms_booking_manager_deposit_fixed', 50),
      ),
      '#states' => array(
        'visible' => array(
          'input[name="rooms_booking_manager_deposit_type"]' => array(
            'value' => 'commerce_line_item_unit_price_amount',
          ),
        ),
      ),
    );
    list($prefix, $suffix) = explode('@percentage', t('Guests must pay @percentage % of the full booking price at checkout to secure booking.'));
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_multiply'] = array(
      '#type' => 'textfield',
      '#size' => 2,
      '#field_prefix' => $prefix,
      '#field_suffix' => $suffix,
      '#default_value' => $multiply_amount ? 100 * $multiply_amount : variable_get('rooms_booking_manager_deposit_multiply', 25),
      '#attributes' => array(
        'placeholder' => variable_get('rooms_booking_manager_deposit_multiply', 25),
      ),
      '#states' => array(
        'visible' => array(
          'input[name="rooms_booking_manager_deposit_type"]' => array(
            'value' => 'commerce_line_item_unit_price_multiply',
          ),
        ),
      ),
    );
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_full_payment'] = array(
      '#type' => 'checkbox',
      '#title' => t('Require full payment for close-in bookings'),
      '#default_value' => variable_get('rooms_booking_manager_full_payment', 0),
    );
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_full_payment_period'] = array(
      '#type' => 'container',
      '#states' => array(
        'visible' => array(
          '#edit-rooms-booking-manager-full-payment' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_full_payment_period']['rooms_booking_manager_full_payment_duration'] = array(
      '#type' => 'rules_duration',
      '#default_value' => variable_get('rooms_booking_manager_full_payment_duration', 86400),
    );
  }
  $form['#validate'][] = 'rooms_booking_manager_deposit_config_form_validate';
  $form['#submit'][] = 'rooms_booking_manager_deposit_config_form_submit';
}

/**
 * Custom validate callback for rooms_booking_manager_deposit_config_form.
 */
function rooms_booking_manager_deposit_config_form_validate($form, &$form_state) {
  if ($form_state['values']['rooms_booking_manager_deposit_type'] == 'commerce_line_item_unit_price_amount' && (!is_numeric($form_state['values']['rooms_booking_manager_deposit_fixed']) || $form_state['values']['rooms_booking_manager_deposit_fixed'] < 0)) {
    form_set_error('rooms_booking_manager_deposit_fixed', t('Fixed deposit value must be numeric and positive.'));
  }
  if ($form_state['values']['rooms_booking_manager_deposit_type'] == 'commerce_line_item_unit_price_multiply' && (!is_numeric($form_state['values']['rooms_booking_manager_deposit_multiply']) || $form_state['values']['rooms_booking_manager_deposit_multiply'] < 0)) {
    form_set_error('rooms_booking_manager_deposit_multiply', t('Percentage deposit value must be numeric and positive.'));
  }
}

/**
 * Custom submit callback for rooms_booking_manager_deposit_config_form.
 */
function rooms_booking_manager_deposit_config_form_submit($form, &$form_state) {
  if ($form_state['values']['rooms_booking_manager_deposit_enabled'] != $form['rooms_checkout_settings']['rooms_booking_manager_deposit_enabled']['#default_value'] || $form_state['values']['rooms_booking_manager_deposit_type'] != $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_type']['#default_value'] || $form_state['values']['rooms_booking_manager_deposit_fixed'] != $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_fixed']['#default_value'] || $form_state['values']['rooms_booking_manager_deposit_multiply'] != $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_deposit_multiply']['#default_value'] || $form_state['values']['rooms_booking_manager_full_payment_duration'] != $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_full_payment_period']['rooms_booking_manager_full_payment_duration']['#default_value'] || $form_state['values']['rooms_booking_manager_full_payment'] != $form['rooms_checkout_settings']['rooms_booking_manager_deposit_fieldset']['rooms_booking_manager_full_payment']['#default_value']) {

    // "Rooms deposit payment" rule.
    $rule = rules_config_load('rooms_booking_manager_deposit');
    if (!$form_state['values']['rooms_booking_manager_deposit_enabled']) {
      $rule->active = FALSE;
    }
    else {
      $rule->active = TRUE;
      foreach ($rule
        ->conditions() as $condition) {
        $condition
          ->delete();
      }
      $rule
        ->condition('entity_is_of_bundle', array(
        'entity:select' => 'commerce-line-item',
        'type' => 'commerce_line_item',
        'bundle' => array(
          'rooms_booking',
        ),
      ));
      $rule
        ->condition('data_is', array(
        'data:select' => 'commerce-line-item:commerce-product:type',
        'value' => 'rooms_product',
      ));
      if ($form_state['values']['rooms_booking_manager_full_payment']) {
        $rule
          ->condition('data_is', array(
          'data:select' => 'commerce-line-item:rooms-booking-dates:value',
          'op' => '>',
          'value' => '+ ' . format_interval($form_state['values']['rooms_booking_manager_full_payment_duration']),
        ));
      }
      foreach ($rule as $action) {
        if ($action instanceof RulesAction) {
          $action
            ->delete();
        }
      }
      $amount = $form_state['values']['rooms_booking_manager_deposit_type'] == 'commerce_line_item_unit_price_amount' ? 100 * $form_state['values']['rooms_booking_manager_deposit_fixed'] : $form_state['values']['rooms_booking_manager_deposit_multiply'] / 100;
      $rule
        ->action($form_state['values']['rooms_booking_manager_deposit_type'], array(
        'commerce_line_item:select' => 'commerce_line_item',
        'amount' => $amount,
        'component_name' => 'base_price',
        'round_mode' => 1,
      ));
    }
    $rule
      ->save();

    // "Adjust line item price following checkout with deposit" rule.
    $rule = rules_config_load('rules_rooms_booking_manager_deposit_checkout');
    if (!$form_state['values']['rooms_booking_manager_deposit_enabled']) {
      $rule->active = FALSE;
    }
    else {
      $rule->active = TRUE;
    }
    $rule
      ->save();
  }
}

/**
 * Alters for the 'commerce_order_ui_order_form' form.
 */
function rooms_booking_manager_alter_commerce_order_ui_order_form(&$form, &$form_state, $form_id) {
  $language = $form['commerce_line_items']['#language'];
  unset($form['commerce_line_items'][$language]['actions']['line_item_type']['#options']['rooms_booking']);
}

/**
 * Alters for the 'rooms_booking_edit' form.
 */
function rooms_booking_manager_alter_rooms_booking_edit_form(&$form, $form_state, $form_id) {
  $form['actions']['submit']['#submit'][] = 'rooms_booking_manager_rooms_booking_edit_form_submit';
}

/**
 * Submit handler for the 'rooms_booking_edit' form.
 */
function rooms_booking_manager_rooms_booking_edit_form_submit(&$form, &$form_state) {
  $booking = $form_state['booking'];
  list($start_date, $end_date) = rooms_form_values_get_start_end_dates($form_state);
  $unit_id = isset($form_state['values']['unit_id']) ? $form_state['values']['unit_id'] : 0;
  $unit = rooms_unit_load($unit_id);

  // Get the client name and client id.
  $client = explode(':', $form_state['values']['client']);
  $client_name = $client[0];
  $commerce_customer_id = rooms_booking_find_customer_by_name($client_name);
  $booking_original = entity_load_unchanged('rooms_booking', $booking->booking_id);
  if ($booking->order_id != '') {
    if (($order = commerce_order_load($booking->order_id)) !== FALSE) {
      if ($booking_original->unit_id != $booking->unit_id || $booking_original->start_date != $booking->start_date || $booking_original->end_date != $booking->end_date || $booking_original->price != $booking->price || $booking_original->data['group_size'] != $booking->data['group_size'] || $booking_original->data['group_size_children'] != $booking->data['group_size_children']) {
        $order->status = 'canceled';
        commerce_order_save($order);
        $booking->order_id = '';
      }
    }
  }
  if ($booking->order_id == '') {
    if (variable_get('rooms_manually_booking_create_order', '1')) {
      $booking_parameters = array(
        'adults' => $form_state['values']['data']['group_size'],
        'children' => isset($form_state['values']['data']['group_size_children']) ? $form_state['values']['data']['group_size_children'] : 0,
      );
      $order = rooms_booking_manager_create_order($start_date, $end_date, $booking_parameters, $unit, $booking, $commerce_customer_id);
      $booking->order_id = $order->order_number;

      // Resave booking to store order reference.
      $booking
        ->save();
    }
  }
}

/**
 * Creates a Commerce Order for a booking.
 *
 * @param DateTime $start_date
 *   start date.
 * @param DateTime $end_date
 *   end date.
 * @param array $booking_parameters
 *   Specify the people we are looking to accommodate.
 * @param RoomsUnit $unit
 *   Unit being booked.
 * @param RoomsBooking $booking
 *   Booking to attach the new order.
 * @param int $profile_id
 *   Customer profile ID for the new order.
 *
 * @return object
 *   A commerce order related to the booking.
 */
function rooms_booking_manager_create_order($start_date, $end_date, $booking_parameters, $unit, $booking, $profile_id) {
  global $user;
  module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.commerce');
  $uid = isset($booking->uid) ? $booking->uid : $user->uid;
  $order = commerce_order_new($uid, 'pending');
  commerce_order_save($order);
  $price_modifiers = array();

  // Convert Price options to Price modifiers.
  foreach (rooms_unit_get_unit_options($unit) as $option) {
    $opt_name = rooms_options_machine_name($option['name']);
    if (isset($booking->{$opt_name}) && $booking->{$opt_name}) {
      $price_modifiers[$opt_name] = array(
        '#name' => $option['name'],
        '#type' => ROOMS_DYNAMIC_MODIFIER,
        '#op_type' => $option['operation'],
        '#amount' => $option['value'],
        '#quantity' => $option['quantity'],
      );
    }
  }
  $agent = new AvailabilityAgent($start_date, $end_date, $booking_parameters, 1, array());
  $agent
    ->setValidStates(variable_get('rooms_valid_availability_states', array(
    ROOMS_AVAILABLE,
    ROOMS_ON_REQUEST,
  )));

  // Create line item.
  $line_item = rooms_create_line_item(array(
    'unit' => $unit,
    'state' => ROOMS_AVAILABLE,
  ), $agent, $booking_parameters, $price_modifiers);
  $line_item->rooms_booking_reference[LANGUAGE_NONE][0]['target_id'] = $booking->booking_id;
  commerce_line_item_save($line_item);

  // Add the line item to the order.
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $order_wrapper->commerce_line_items[] = $line_item;

  // Add customer profile id to store billing information.
  $profile_object = array(
    LANGUAGE_NONE => array(
      array(
        'profile_id' => $profile_id,
      ),
    ),
  );
  $order->commerce_customer_billing = $profile_object;

  // Save the order again to update its line item reference field.
  commerce_order_save($order);
  $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
  $line_item_wrapper->order_id = $order->order_id;
  $line_item_wrapper
    ->save();
  commerce_cart_order_refresh($order);
  $line_item_wrapper->commerce_unit_price->amount = $booking->price;
  $data = $line_item_wrapper->commerce_unit_price->data
    ->value();
  $data['components'][0]['price']['amount'] = $booking->price;
  $line_item_wrapper->commerce_unit_price->data = $data;
  $line_item_wrapper
    ->save();
  $order_wrapper->commerce_order_total->amount = $booking->price;
  $data = $order_wrapper->commerce_order_total->data
    ->value();
  $data['components'][0]['price']['amount'] = $booking->price;
  $order_wrapper->commerce_order_total->data = $data;
  $order_wrapper
    ->save();
  return $order;
}
function rooms_booking_cancel_order_booking() {
}

/**
 * Rules action: set the line item price to the booked price.
 */
function rooms_booking_manager_booked_price($line_item) {
  if ($line_item->type == 'rooms_booking') {
    $wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    $amount = $wrapper->rooms_booked_price
      ->value();
    if (is_numeric($amount)) {
      $unit_price = commerce_price_wrapper_value($wrapper, 'commerce_unit_price', TRUE);

      // Calculate the updated amount and create a price array representing the
      // difference between it and the current amount.
      $current_amount = $unit_price['amount'];
      if (module_exists('commerce_multicurrency')) {
        $amount = commerce_currency_convert($amount, commerce_default_currency(), $unit_price['currency_code']);
      }
      $difference = array(
        'amount' => $amount - $current_amount,
        'currency_code' => $unit_price['currency_code'],
        'data' => array(),
      );

      // Set the amount of the unit price and add the difference as a component.
      $wrapper->commerce_unit_price->amount = $amount;
      $wrapper->commerce_unit_price->data = commerce_price_component_add($wrapper->commerce_unit_price
        ->value(), 'base_price', $difference, TRUE);
    }
  }
}

/**
 * Calculates the price for rooms_booking line item types.
 *
 * @param object $line_item
 *   Line item to modify.
 */
function rooms_booking_manager_price_apply($line_item) {
  if ($line_item->type == 'rooms_booking') {
    if ($item = field_get_items('commerce_line_item', $line_item, 'commerce_product')) {
      $product = commerce_product_load($item[0]['product_id']);
      if ($product->sku != 'ROOMS-BASIC-BOOKING') {
        return;
      }
    }
    $amount = $line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount'];
    $start_date = new DateTime($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value']);
    $end_date = new DateTime($line_item->rooms_booking_dates[LANGUAGE_NONE][0]['value2']);
    $unit_id = $line_item->rooms_booked_unit_id[LANGUAGE_NONE][0]['value'];
    $unit = rooms_unit_load($unit_id);

    // First set up price modifiers.
    $price_options = is_array(field_get_items('commerce_line_item', $line_item, 'rooms_booking_options')) ? field_get_items('commerce_line_item', $line_item, 'rooms_booking_options') : array();

    // Convert Price options in Price modifiers.
    $price_modifiers = array();
    foreach ($price_options as $option) {
      $price_modifiers[rooms_options_machine_name($option['name'])] = array(
        '#name' => $option['name'],
        '#type' => ROOMS_DYNAMIC_MODIFIER,
        '#op_type' => $option['operation'],
        '#amount' => $option['value'],
        '#quantity' => $option['quantity'],
      );
    }
    $adults = $line_item->rooms_booking_number_people[LANGUAGE_NONE][0]['value'];
    $children = $line_item->rooms_booking_number_people[LANGUAGE_NONE][1]['value'];
    $childrens_age = isset($line_item->rooms_booking_children_ages[LANGUAGE_NONE]) ? $line_item->rooms_booking_children_ages[LANGUAGE_NONE] : array();
    $booking_info = array(
      'start_date' => clone $start_date,
      'end_date' => clone $end_date,
      'unit' => $unit,
      'booking_parameters' => array(
        'group_size' => $adults,
        'group_size_children' => $children,
        'childrens_age' => $childrens_age,
      ),
    );

    // Give other modules a chance to change the price modifiers.
    drupal_alter('rooms_price_modifier', $price_modifiers, $booking_info);
    $price_calendar = new UnitPricingCalendar($unit->unit_id, $price_modifiers);
    $temp_end_date = clone $end_date;
    $temp_end_date
      ->sub(new DateInterval('P1D'));
    $price = $price_calendar
      ->calculatePrice($start_date, $temp_end_date, $adults, $children, $childrens_age);
    $full_price = $price['full_price'] * 100;
    $line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount'] = $full_price;
    $line_item->commerce_unit_price[LANGUAGE_NONE][0]['currency_code'] = commerce_default_currency();
    foreach ($line_item->commerce_unit_price[LANGUAGE_NONE][0]['data']['components'] as $key => $component) {
      $line_item->commerce_unit_price[LANGUAGE_NONE][0]['data']['components'][$key]['price']['amount'] = $full_price / $amount * $component['price']['amount'];
      $line_item->commerce_unit_price[LANGUAGE_NONE][0]['data']['components'][$key]['price']['currency_code'] = commerce_default_currency();
    }
  }
}

/**
 * Implements hook_block_info().
 */
function rooms_booking_manager_block_info() {
  $blocks = array();
  $blocks['rooms_availability_search'] = array(
    'info' => t('Availability Search'),
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function rooms_booking_manager_block_view($block_name = '') {
  if ($block_name == 'rooms_availability_search') {
    module_load_include('inc', 'rooms_booking_manager', 'rooms_booking_manager.availability_search');
    $form = drupal_get_form('rooms_booking_availability_search_form_block');
    $block = array(
      'subject' => t('Availability Search'),
      'content' => $form,
    );
    return $block;
  }
}

/**
 * Implements hook_commerce_line_item_type_info().
 */
function rooms_booking_manager_commerce_line_item_type_info() {
  return array(
    'rooms_booking' => array(
      'name' => t('Rooms Booking'),
      'description' => t('Represents a booking of a Rooms product.'),
      'product' => TRUE,
      'add_form_submit_value' => t('Add product'),
      'base' => 'rooms_booking_manager_line_item',
    ),
  );
}

/**
 * Ensures the booking line item type contains a product reference field and
 * all other rooms fields required for a booking.
 *
 * @param array $line_item_type
 *   The line item type object.
 */
function rooms_booking_manager_line_item_configuration($line_item_type) {
  $type = $line_item_type['type'];

  // Get the info about the fields and instances we need to create.
  module_load_include('inc', 'rooms_booking_manager', 'includes/rooms_booking_manager.fields');
  $field_data = _rooms_booking_manager_line_item_type_fields();

  // Create the product reference field for the line item type.
  commerce_product_line_item_configuration($line_item_type);

  // For each field, check whether it already exists create it if it doesn't
  foreach ($field_data['fields'] as $field_name => $field_info) {
    $field = field_info_field($field_name);
    $instance = field_info_instance('commerce_line_item', $field_name, $type);
    if (empty($field)) {
      field_create_field($field_data['fields'][$field_name]);
    }
    if (empty($instance)) {
      field_create_instance($field_data['instances'][$field_name]);
    }
  }
}

/**
 * Implements hook_line_item_title().
 */
function rooms_booking_manager_line_item_title($line_item) {

  // Use the line item's label for the title.
  return $line_item->line_item_label;
}

/**
 * Implements hook_commerce_product_type_info().
 */
function rooms_booking_manager_commerce_product_type_info() {
  return array(
    'rooms_product' => array(
      'type' => 'rooms_product',
      'name' => t('Rooms product'),
      'description' => t('Products that are bookable with Rooms.'),
      'revision' => '1',
    ),
  );
}

/**
 * Implements hook_views_api().
 */
function rooms_booking_manager_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'rooms_booking_manager') . '/views',
  );
}

/**
 * Given a title argument from a hook_menu() the function returns 
 *  related variable.
 *
 * @param $string - title argument defined via hook_menu().
 *
 * @return string
 */
function rooms_booking_manager_menu_title_callback($argument) {
  switch ($argument) {
    case 'booking':
      return variable_get_value('rooms_booking_manager_create_your_booking');
    case 'bookings':
      return variable_get_value('rooms_booking_manager_review_your_reservation');
    case 'select_your_stay':
      return variable_get_value('rooms_booking_manager_select_your_stay');
  }
}

/**
 * Checks if deposit is active and returns deposit amount.
 *
 * @param $price
 * @param $start_date
 *
 * @return bool|float|null
 */
function rooms_booking_manager_check_for_deposit($price, $start_date) {
  $deposit_amount = FALSE;
  if (variable_get('rooms_booking_manager_full_payment', 0)) {
    $now = new DateTime();
    $interval = '+ ' . format_interval(variable_get('rooms_booking_manager_full_payment_duration', 86400));
    $now
      ->modify($interval);
    if ($start_date <= $now) {
      return $deposit_amount;
    }
  }
  $rule = rules_config_load('rooms_booking_manager_deposit');
  if (!empty($rule) && $rule->active) {
    $deposit_type = variable_get('rooms_booking_manager_deposit_type');
    $deposit_amount = $deposit_type == 'commerce_line_item_unit_price_amount' ? variable_get('rooms_booking_manager_deposit_fixed') : variable_get('rooms_booking_manager_deposit_multiply') * $price / 100;
  }
  return $deposit_amount;
}

Functions

Namesort descending Description
book_units_per_type_form Book units per type booking form callback.
book_units_per_type_form_submit Submit callback for book_units_per_type_form form.
book_units_per_type_form_validate Validate callback for book_units_per_type_form form.
book_unit_form_builder The form builder builds the form (where visible is simply the purchase button) for individual bookable units.
book_unit_form_submit Submit callback for book_unit_form form.
book_unit_form_validate Validation for cart booking form.
end_date_load Loads a DateTime object from a string.
rooms_booking_cancel_order_booking
rooms_booking_manager_alter_commerce_checkout_form_checkout Alters for the 'commerce_checkout_form_checkout' form.
rooms_booking_manager_alter_commerce_order_ui_order_form Alters for the 'commerce_order_ui_order_form' form.
rooms_booking_manager_alter_rooms_booking_edit_form Alters for the 'rooms_booking_edit' form.
rooms_booking_manager_alter_rooms_booking_settings Alters for the 'rooms_booking_settings' form.
rooms_booking_manager_alter_rooms_booking_settings_validate Validate the form.
rooms_booking_manager_block_info Implements hook_block_info().
rooms_booking_manager_block_view Implements hook_block_view().
rooms_booking_manager_booked_price Rules action: set the line item price to the booked price.
rooms_booking_manager_cart_view Display the shopping cart form and associated information.
rooms_booking_manager_change_search_form Provides a single integrated group of form elements storing the current availability search along with a "change search" button that will take you back to the initial booking search page.
rooms_booking_manager_change_search_form_submit This function redirects the user back to the search box and sets up the values of the search as a convenient way to modify the search.
rooms_booking_manager_change_search_form_validate
rooms_booking_manager_check_for_deposit Checks if deposit is active and returns deposit amount.
rooms_booking_manager_children_change_callback AJAX callback on booking search results page when Children selector change.
rooms_booking_manager_commerce_checkout_complete Implements hook_commerce_checkout_complete().
rooms_booking_manager_commerce_checkout_form_cancel_submit Submit callback when cancelling the checkout process.
rooms_booking_manager_commerce_line_item_type_info Implements hook_commerce_line_item_type_info().
rooms_booking_manager_commerce_order_state_info Implements hook_commerce_order_state_info().
rooms_booking_manager_commerce_order_status_info Implements hook_commerce_order_status_info().
rooms_booking_manager_commerce_product_type_info Implements hook_commerce_product_type_info().
rooms_booking_manager_create_order Creates a Commerce Order for a booking.
rooms_booking_manager_deposit_config_form Form snippet to configure deposit configuration form.
rooms_booking_manager_deposit_config_form_submit Custom submit callback for rooms_booking_manager_deposit_config_form.
rooms_booking_manager_deposit_config_form_validate Custom validate callback for rooms_booking_manager_deposit_config_form.
rooms_booking_manager_enquiry_confirmation Display 'Booking confirmed' message.
rooms_booking_manager_enquiry_page Page callback for enquiry search.
rooms_booking_manager_enquiry_page_form Enquiry search page form.
rooms_booking_manager_enquiry_page_form_submit Submit callback for rooms_booking_manager_enquiry_page_form form.
rooms_booking_manager_enquiry_page_form_validate Enquiry search page form validation handler.
rooms_booking_manager_forms Implements hook_forms().
rooms_booking_manager_form_alter Implements hook_form_alter().
rooms_booking_manager_get_plugin_parameters Retrieves parameters defined by plugins and return them as an array.
rooms_booking_manager_line_item_configuration Ensures the booking line item type contains a product reference field and all other rooms fields required for a booking.
rooms_booking_manager_line_item_title Implements hook_line_item_title().
rooms_booking_manager_mail Implements hook_mail().
rooms_booking_manager_menu Implements hook_menu().
rooms_booking_manager_menu_title_callback Given a title argument from a hook_menu() the function returns related variable.
rooms_booking_manager_options_change_callback Ajax callback on booking search results page when an Options state change.
rooms_booking_manager_permission Implements hook_permission().
rooms_booking_manager_present_individual_rooms Prepares rooms on a per room basis for presentation.
rooms_booking_manager_present_types Prepares Units on a per type basis.
rooms_booking_manager_price_apply Calculates the price for rooms_booking line item types.
rooms_booking_manager_price_change_callback
rooms_booking_manager_quantity_change_callback AJAX callback on booking search results page when quantity change.
rooms_booking_manager_results_page Constructs the booking results page following an availability search.
rooms_booking_manager_retrieve_booking_parameters Checks that the booking parameters given are valid. This is mainly used to clean up values that came through the URL and are set in $_GET.
rooms_booking_manager_rooms_booking_edit_form_submit Submit handler for the 'rooms_booking_edit' form.
rooms_booking_manager_theme Implements hook_theme().
rooms_booking_manager_views_api Implements hook_views_api().
rooms_booking_manager_views_form_booking_cart_form_ Alters for the 'views_form_booking_cart_form_*' form.
start_date_load Loads a DateTime object from a string.