You are here

public function UnitPricingCalendar::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

1 call to UnitPricingCalendar::getRawDayData()
UnitPricingCalendar::getEvents in modules/rooms_pricing/includes/rooms_pricing.unit_pricing_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

File

modules/rooms_pricing/includes/rooms_pricing.unit_pricing_calendar.inc, line 242
Contains UnitPricingCalendar.

Class

UnitPricingCalendar
Handles querying and updating the pricing 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 PricingEvent to represent the range we are searching over.
  // This gives us access to handy functions that PricingEvents have.
  $s = new PricingEvent($this->unit_id, 0, $start_date, $end_date);
  $results = array();

  // If search across the same year do a single query.
  if ($s
    ->sameYear()) {
    $query = db_select($this->base_table, '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($this->base_table, '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 PricingEvent($this->unit_id, $this->default_price, 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 this.
      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]);
        }
      }
    }
  }

  // We store -1 instead of the default price in the DB so this is our chance to get the default price back
  // cycling through the data and replace -1 with the current default price of the unit.
  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);
      while ($j <= count($days['days'])) {
        if ($days['days']['d' . $i] == -1) {
          $results[$this->unit_id][$year][$mid]['days']['d' . $i] = commerce_currency_decimal_to_amount($this->default_price, commerce_default_currency());
        }
        $i++;
        $j++;
      }
    }
  }

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