load->model('appointments_model'); $this->load->model('providers_model'); // Get the provider's working plan and reserved appointments. $working_plan = json_decode($this->providers_model ->get_setting('working_plan', $provider_id), true); $where_clause = array( 'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)), 'id_users_provider' => $provider_id ); $reserved_appointments = $this->appointments_model->get_batch($where_clause); // Sometimes it might be necessary to not take into account some // appointment records in order to display what the providers' // available time periods would be without them. foreach ($exclude_appointments as $excluded_id) { foreach ($reserved_appointments as $index => $reserved) { if ($reserved['id'] == $excluded_id) { unset($reserved_appointments[$index]); } } } // Find the empty spaces on the plan. The first split between // the plan is due to a break (if exist). After that every // reserved appointment is considered to be a taken space in the // plan. $selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))]; $available_periods_with_breaks = array(); if (isset($selected_date_working_plan['breaks'])) { foreach($selected_date_working_plan['breaks'] as $index=>$break){ // Split the working plan to available time periods that do not // contain the breaks in them. $last_break_index = $index - 1; if (count($available_periods_with_breaks) === 0) { $start_hour = $selected_date_working_plan['start']; $end_hour = $break['start']; } else { $start_hour = $selected_date_working_plan ['breaks'][$last_break_index]['end']; $end_hour = $break['start']; } $available_periods_with_breaks[] = array( 'start' => $start_hour, 'end' => $end_hour ); } // Add the period from the last break to the end of the day. $available_periods_with_breaks[] = array( 'start' =>$selected_date_working_plan['breaks'][$index]['end'], 'end' => $selected_date_working_plan['end'] ); } // Break the empty periods with the reserved appointments. $available_periods_with_appointments = array(); if (count($reserved_appointments) > 0) { foreach($available_periods_with_breaks as $period) { foreach($reserved_appointments as $index=>$reserved) { $appointment_start = date('H:i', strtotime($reserved['start_datetime'])); $appointment_end = date('H:i', strtotime($reserved['end_datetime'])); $period_start = date('H:i', strtotime($period['start'])); $period_end = date('H:i', strtotime($period['end'])); if ($period_start <= $appointment_start && $period_end >= $appointment_end) { // We need to check whether another appointment fits // in the current time period. If this happens, then // we need to consider the whole appointment time as // one, because the provider will not be available. foreach ($reserved_appointments as $tmp_appointment) { $appt_start = date('H:i', strtotime($tmp_appointment['start_datetime'])); $appt_end = date('H:i', strtotime($tmp_appointment['end_datetime'])); if ($period_start < $appt_start && $period_end > $appt_end) { if ($appointment_start > $appt_start) { $appointment_start = $appt_start; } if ($appointment_end < $appt_end) { $appointment_end = $appt_end; } } } // Current appointment is within the current // empty space. So we need to break the empty // space into two other spaces that don't include // the appointment. $new_period = array( 'start' => $period_start, 'end' => $appointment_start ); if (!in_array($new_period, $available_periods_with_appointments)) { $available_periods_with_appointments[] = $new_period; } $new_period = array( 'start' => $appointment_end, 'end' => $period_end ); if (!in_array($new_period, $available_periods_with_appointments)) { $available_periods_with_appointments[] = $new_period; } } else { // Check if there are any other appointments // between this time space. If not, it is going // to be added as it is. $found = FALSE; foreach ($reserved_appointments as $tmp_appointment) { $appt_start = date('H:i', strtotime($tmp_appointment['start_datetime'])); $appt_end = date('H:i', strtotime($tmp_appointment['end_datetime'])); if ($period_start < $appt_start && $period_end > $appt_end) { $found = TRUE; } } // It is also necessary to check that this time // period doesn't already exist in the // "$empty_spaces_with_appointments" array. $empty_period = array( 'start' => $period_start, 'end' => $period_end ); $already_exist = in_array($empty_period, $available_periods_with_appointments); if ($found === FALSE && $already_exist === FALSE) { $available_periods_with_appointments[] = $empty_period; } } } } } else { $available_periods_with_appointments = $available_periods_with_breaks; } return $available_periods_with_appointments; }