/**
  * Output the calendar view
  */
 public function output()
 {
     wp_enqueue_script('chosen');
     $product_filter = isset($_REQUEST['filter_bookings']) ? absint($_REQUEST['filter_bookings']) : '';
     $view = isset($_REQUEST['view']) && $_REQUEST['view'] == 'day' ? 'day' : 'month';
     if ($view == 'day') {
         $day = isset($_REQUEST['calendar_day']) ? wc_clean($_REQUEST['calendar_day']) : date('Y-m-d');
         $this->bookings = WC_Bookings_Controller::get_bookings_in_date_range(strtotime('midnight', strtotime($day)), strtotime('midnight +1 day', strtotime($day)), $product_filter);
     } else {
         $month = isset($_REQUEST['calendar_month']) ? absint($_REQUEST['calendar_month']) : date('n');
         $year = isset($_REQUEST['calendar_year']) ? absint($_REQUEST['calendar_year']) : date('Y');
         if ($year < date('Y') - 10 || $year > 2100) {
             $year = date('Y');
         }
         if ($month > 12) {
             $month = 1;
             $year++;
         }
         if ($month < 1) {
             $month = 1;
             $year--;
         }
         $start_week = (int) date('W', strtotime("first day of {$year}-{$month}"));
         $end_week = (int) date('W', strtotime("last day of {$year}-{$month}"));
         if ($end_week == 1) {
             $end_week = 53;
         }
         $this->bookings = WC_Bookings_Controller::get_bookings_in_date_range(strtotime($year . 'W' . str_pad($start_week, 2, '0', STR_PAD_LEFT)), strtotime($year . 'W' . str_pad($end_week + 1, 2, '0', STR_PAD_LEFT)), $product_filter);
     }
     include 'views/html-calendar-' . $view . '.php';
     wc_enqueue_js('$( "select#calendar-bookings-filter" ).chosen();');
 }
 /**
  * Output the calendar view
  */
 public function output()
 {
     if (version_compare(WOOCOMMERCE_VERSION, '2.3', '<')) {
         wp_enqueue_script('chosen');
         wc_enqueue_js('$( "select#calendar-bookings-filter" ).chosen();');
     } else {
         wp_enqueue_script('wc-enhanced-select');
     }
     $product_filter = isset($_REQUEST['filter_bookings']) ? absint($_REQUEST['filter_bookings']) : '';
     $view = isset($_REQUEST['view']) && $_REQUEST['view'] == 'day' ? 'day' : 'month';
     if ($view == 'day') {
         $day = isset($_REQUEST['calendar_day']) ? wc_clean($_REQUEST['calendar_day']) : date('Y-m-d');
         $this->bookings = WC_Bookings_Controller::get_bookings_in_date_range(strtotime('midnight', strtotime($day)), strtotime('midnight +1 day', strtotime($day)), $product_filter);
     } else {
         $month = isset($_REQUEST['calendar_month']) ? absint($_REQUEST['calendar_month']) : date('n');
         $year = isset($_REQUEST['calendar_year']) ? absint($_REQUEST['calendar_year']) : date('Y');
         if ($year < date('Y') - 10 || $year > 2100) {
             $year = date('Y');
         }
         if ($month > 12) {
             $month = 1;
             $year++;
         }
         if ($month < 1) {
             $month = 1;
             $year--;
         }
         $start_of_week = absint(get_option('start_of_week', 1));
         $last_day = date('t', strtotime("{$year}-{$month}-01"));
         $start_date_w = absint(date('w', strtotime("{$year}-{$month}-01")));
         $end_date_w = absint(date('w', strtotime("{$year}-{$month}-{$last_day}")));
         // Calc day offset
         $day_offset = $start_date_w - $start_of_week;
         $day_offset = $day_offset >= 0 ? $day_offset : 7 - abs($day_offset);
         // Cald end day offset
         $end_day_offset = 7 - $last_day % 7 - $day_offset;
         $end_day_offset = $end_day_offset >= 0 && $end_day_offset < 7 ? $end_day_offset : 7 - abs($end_day_offset);
         $start_timestamp = strtotime("-{$day_offset} day", strtotime("{$year}-{$month}-01"));
         $end_timestamp = strtotime("+{$end_day_offset} day", strtotime("{$year}-{$month}-{$last_day}"));
         $this->bookings = WC_Bookings_Controller::get_bookings_in_date_range($start_timestamp, $end_timestamp, $product_filter);
     }
     include 'views/html-calendar-' . $view . '.php';
 }
 /**
  * Get existing bookings in a given date range
  *
  * @param string $start-date
  * @param string $end_date
  * @param int    $resource_id
  * @return array
  */
 public function get_bookings_in_date_range($start_date, $end_date, $resource_id = null)
 {
     if ($this->has_resources() && $resource_id) {
         return WC_Bookings_Controller::get_bookings_in_date_range($start_date, $end_date, $resource_id);
     } else {
         return WC_Bookings_Controller::get_bookings_in_date_range($start_date, $end_date, $this->id);
     }
 }
 /**
  * Return an array of resources which can be booked for a defined start/end date
  * @param  string $start_date
  * @param  string $end_date
  * @param  int $resource_id
  * @param  integer $qty being booked
  * @return bool|WP_ERROR if no blocks available, or int count of bookings that can be made, or array of available resources
  */
 public function get_available_bookings($start_date, $end_date, $resource_id = '', $qty = 1)
 {
     // Check the date is not in the past
     if (date('Ymd', $start_date) < date('Ymd', current_time('timestamp'))) {
         return false;
     }
     // Check we have a resource if needed
     $booking_resource = $resource_id ? $this->get_resource($resource_id) : null;
     if ($this->has_resources() && !is_numeric($resource_id)) {
         return false;
     }
     $min_date = $this->get_min_date();
     $max_date = $this->get_max_date();
     $check_from = strtotime("midnight +{$min_date['value']} {$min_date['unit']}", current_time('timestamp'));
     $check_to = strtotime("midnight +{$max_date['value']} {$max_date['unit']}", current_time('timestamp'));
     // Min max checks
     if ('month' === $this->get_duration_unit()) {
         $check_to = strtotime('midnight', strtotime(date('Y-m-t', $check_to)));
     }
     if ($end_date < $check_from || $start_date > $check_to) {
         return false;
     }
     // Get availability of each resource - no resource has been chosen yet
     if ($this->has_resources() && !$resource_id) {
         $resources = $this->get_resources();
         $available_resources = array();
         foreach ($resources as $resource) {
             $availability = $this->get_available_bookings($start_date, $end_date, $resource->ID, $qty);
             if ($availability && !is_wp_error($availability)) {
                 $available_resources[$resource->ID] = $availability;
             }
         }
         if (empty($available_resources)) {
             return new WP_Error('Error', __('This block cannot be booked.', 'woocommerce-bookings'));
         }
         return $available_resources;
         // If we are checking for bookings for a specific resource, or have none...
     } else {
         $available_qtys = array();
         $check_date = $start_date;
         while ($check_date < $end_date) {
             if (!$this->check_availability_rules_against_date($check_date, $resource_id)) {
                 return false;
             }
             if ('start' === $this->wc_booking_check_availability_against) {
                 break;
                 // Only need to check first day
             }
             $check_date = strtotime("+1 day", $check_date);
         }
         if (in_array($this->get_duration_unit(), array('minute', 'hour')) && !$this->check_availability_rules_against_time($start_date, $end_date, $resource_id)) {
             return false;
         }
         $blocks = $this->get_blocks_in_range($start_date, $end_date, '', $resource_id);
         if (!$blocks) {
             return false;
         }
         /**
          * Grab all existing bookings for the date range
          * @var array
          */
         if ($this->has_resources() && $resource_id) {
             $existing_bookings = WC_Bookings_Controller::get_bookings_in_date_range($start_date, $end_date, $resource_id);
         } else {
             $existing_bookings = WC_Bookings_Controller::get_bookings_in_date_range($start_date, $end_date, $this->id);
         }
         foreach ($blocks as $block) {
             $available_qty = $this->has_resources() && $booking_resource->has_qty() ? $booking_resource->get_qty() : $this->get_qty();
             $qty_booked_in_block = 0;
             foreach ($existing_bookings as $existing_booking) {
                 if ($existing_booking->is_booked_on_day($block)) {
                     $qty_to_add = $this->has_person_qty_multiplier() ? max(1, array_sum($existing_booking->get_persons())) : 1;
                     if ($this->has_resources()) {
                         if ($existing_booking->get_resource_id() === absint($resource_id) || !$booking_resource->has_qty() && $existing_booking->get_resource() && !$existing_booking->get_resource()->has_qty()) {
                             $qty_booked_in_block += $qty_to_add;
                         }
                     } else {
                         $qty_booked_in_block += $qty_to_add;
                     }
                 }
             }
             $available_qty = $available_qty - $qty_booked_in_block;
             if ($available_qty < $qty) {
                 if (in_array($this->get_duration_unit(), array('hour', 'minute'))) {
                     return new WP_Error('Error', sprintf(_n('There is %d place remaining', 'There are %d places remaining', $available_qty, 'woocommerce-bookings'), $available_qty));
                 } elseif (!$available_qtys) {
                     return new WP_Error('Error', sprintf(_n('There is %d place remaining on %s', 'There are %d places remaining on %s', $available_qty, 'woocommerce-bookings'), $available_qty, date_i18n(get_option('date_format'), $block)));
                 } else {
                     return new WP_Error('Error', sprintf(_n('There is %d place remaining on %s', 'There are %d places remaining on %s', $available_qty, 'woocommerce-bookings'), max($available_qtys), date_i18n(get_option('date_format'), $block)));
                 }
             }
             $available_qtys[] = $available_qty;
         }
         return min($available_qtys);
     }
 }