You are here

public function UnitCalendar::getRawDayData in Rooms - Drupal Booking for Hotels, B&Bs and Vacation Rentals 7

Given a date range it returns all data within that range including the start and end dates of states. The MySQL queries are kept simple and then the data is cleared up.

Parameters

DateTime $start_date: The starting date

DateTime $end_date: The end date of our range

Return value

array An array of the structure data[unitid][year][month][days][d1]..[d31] as week as data[unitid][year][month][unique_states]

Overrides RoomsCalendar::getRawDayData

2 calls to UnitCalendar::getRawDayData()
UnitCalendar::getEvents in modules/rooms_availability/includes/rooms_availability.unit_calendar.inc
Given a date range returns an array of RoomEvents. The heavy lifting really takes place in the getRawDayData function - here we are simply acting as a factory for event objects
UnitCalendar::getStates in modules/rooms_availability/includes/rooms_availability.unit_calendar.inc
Given a date range returns all states in that range - useful when we are not interested in starting and ending dates but simply in states.

File

modules/rooms_availability/includes/rooms_availability.unit_calendar.inc, line 122
Class UnitCalendar Handles querying and updating the availability information relative to a single bookable unit.

Class

UnitCalendar
@file Class UnitCalendar Handles querying and updating the availability information relative to a single bookable unit.

Code

public function getRawDayData(DateTime $start_date, DateTime $end_date) {

  // To handle single-day bookings (Tours) we pretend that they are overnight
  // bookings.
  if ($end_date < $start_date) {
    $end_date
      ->add(new DateInterval('P1D'));
  }

  // Create a dummy BookingEvent to represent the range we are searching over.
  // This gives us access to handy functions that BookingEvents have.
  $s = new BookingEvent($this->unit_id, 0, $start_date, $end_date);
  $results = array();

  // Start by doing a query to the db to get any info stored there.
  // If search across the same year do a single query.
  if ($s
    ->sameYear()) {
    $query = db_select('rooms_availability', 'a');
    $query
      ->fields('a');
    $query
      ->condition('a.unit_id', $this->unit_id);
    $query
      ->condition('a.year', $s
      ->startYear());
    $query
      ->condition('a.month', $s
      ->startMonth(), '>=');
    $query
      ->condition('a.month', $s
      ->endMonth(), '<=');
    $months = $query
      ->execute()
      ->fetchAll(PDO::FETCH_ASSOC);
    if (count($months) > 0) {
      foreach ($months as $month) {
        $m = $month['month'];
        $y = $month['year'];
        $id = $month['unit_id'];

        // Remove the three first rows and just keep the days.
        unset($month['month']);
        unset($month['year']);
        unset($month['unit_id']);
        $results[$id][$y][$m]['days'] = $month;
      }
    }
  }
  else {
    for ($j = $s
      ->startYear(); $j <= $s
      ->endYear(); $j++) {
      $query = db_select('rooms_availability', 'a');
      $query
        ->fields('a');
      $query
        ->condition('a.unit_id', $this->unit_id);
      $query
        ->condition('a.year', $j);
      if ($j == $s
        ->startYear()) {
        $query
          ->condition('a.month', $s
          ->startMonth(), '>=');
      }
      elseif ($j == $s
        ->endYear()) {
        $query
          ->condition('a.month', $s
          ->endMonth(), '<=');
      }
      $months = $query
        ->execute()
        ->fetchAll(PDO::FETCH_ASSOC);
      if (count($months) > 0) {
        foreach ($months as $month) {
          $m = $month['month'];
          $y = $month['year'];
          $id = $month['unit_id'];
          unset($month['month']);
          unset($month['year']);
          unset($month['unit_id']);
          $results[$id][$y][$m]['days'] = $month;
        }
      }
    }
  }

  // With the results from the db in place fill in any missing months
  // with the default state for the unit.
  for ($j = $s
    ->startYear(); $j <= $s
    ->endYear(); $j++) {
    $eod = rooms_end_of_month_dates($j);

    // We start by setting the expected start and end months for each year.
    if ($s
      ->sameYear()) {
      $expected_months = $s
        ->endMonth() - $s
        ->startMonth() + 1;
      $sm = $s
        ->startMonth();
      $em = $s
        ->endMonth();
    }
    elseif ($j == $s
      ->endYear()) {
      $expected_months = $s
        ->endMonth();
      $sm = 1;
      $em = $s
        ->endMonth();
    }
    elseif ($j == $s
      ->startYear()) {
      $expected_months = 12 - $s
        ->startMonth() + 1;
      $em = 12;
      $sm = $s
        ->startMonth();
    }
    else {
      $expected_months = 12;
      $sm = 1;
      $em = 12;
    }

    // We check to see if the months we have already fit our expectations.
    $actual_months = isset($result[$this->unit_id][$j]) ? count($results[$id][$j]) : 0;
    if ($expected_months > $actual_months) {

      // We have missing months so lets go fill them.
      for ($i = $sm; $i <= $em; $i++) {
        if (!isset($results[$this->unit_id][$j][$i])) {
          $last_day = $eod[$i];
          $month = $this
            ->prepareFullMonthArray(new BookingEvent($this->unit_id, $this->default_state, new DateTime("{$j}-{$i}-1"), new DateTime("{$j}-{$i}-{$last_day}")));

          // Add the month in its rightful position.
          $results[$this->unit_id][$j][$i]['days'] = $month;

          // And sort months.
          ksort($results[$this->unit_id][$j]);
        }
      }
    }
  }

  // With all the months in place we now need to clean results to set the
  // right start and end date for each month - this will save code downstream
  // from having to worry about it.
  foreach ($results[$this->unit_id] as $year => $months) {
    foreach ($months as $mid => $days) {

      // Get the end of month values again to make sure we have the right year
      // because it might change for queries spanning years.
      $eod = rooms_end_of_month_dates($year);

      // There is undoubtetly a smarter way to do the clean up below - but
      // will live with this for now.
      if (count($days['days']) != $eod[$mid]) {
        switch ($eod[$mid]) {
          case 30:
            unset($results[$this->unit_id][$year][$mid]['days']['d31']);
            break;
          case 29:
            unset($results[$this->unit_id][$year][$mid]['days']['d31']);
            unset($results[$this->unit_id][$year][$mid]['days']['d30']);
            break;
          case 28:
            unset($results[$this->unit_id][$year][$mid]['days']['d31']);
            unset($results[$this->unit_id][$year][$mid]['days']['d30']);
            unset($results[$this->unit_id][$year][$mid]['days']['d29']);
            break;
        }
      }
      if ($year == $s
        ->startYear() && $mid == $s
        ->startMonth()) {

        // We know we have the entire months over the range so we just unset
        // all the dates from the start of the month to the actual start day.
        for ($i = 1; $i < $s
          ->startDay(); $i++) {
          unset($results[$this->unit_id][$year][$mid]['days']['d' . $i]);
        }
      }
      if ($year == $s
        ->endYear() && $mid == $s
        ->endMonth()) {

        // And from the end of the month back to the actual end day.
        for ($i = $s
          ->endDay() + 1; $i <= $eod[$mid]; $i++) {
          unset($results[$this->unit_id][$year][$mid]['days']['d' . $i]);
        }
      }
    }
  }

  // With the results in place we do a states array with the start and
  // end dates of each event.
  foreach ($results[$this->unit_id] as $year => $months) {
    foreach ($months as $mid => $days) {

      // The number of days in the month we are interested in eventing.
      $j = count($days);

      // The start date.
      $i = substr(key($days['days']), 1);
      $start_day = $i;
      $end_day = NULL;
      $unique_states = array();
      $old_state = $days['days']['d' . $i];
      $state = $days['days']['d' . $i];
      while ($j <= count($days['days'])) {
        $state = $days['days']['d' . $i];
        if ($state != $old_state) {
          $unique_states[] = array(
            'state' => $old_state,
            'start_day' => $start_day,
            'end_day' => $i - 1,
          );
          $end_day = $i - 1;
          $start_day = $i;
          $old_state = $state;
        }
        $i++;
        $j++;
      }

      // Get the last event in.
      $unique_states[] = array(
        'state' => $state,
        'start_day' => isset($end_day) ? $end_day + 1 : $start_day,
        'end_day' => $i - 1,
      );
      $results[$this->unit_id][$year][$mid]['states'] = $unique_states;
    }
  }
  return $results;
}