You are here

function book_units_per_type_form in Rooms - Drupal Booking for Hotels, B&Bs and Vacation Rentals 7

Book units per type booking form callback.

1 string reference to 'book_units_per_type_form'
rooms_booking_manager_present_types in modules/rooms_booking_manager/rooms_booking_manager.module
Prepares Units on a per type basis.

File

modules/rooms_booking_manager/rooms_booking_manager.module, line 1403
Rooms Booking Manager brings together all the pieces required to find a room and book it - including the DrupalCommerce integration

Code

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;
}