Support new security model in the formSubmit function - bug fix
[openemr.git] / library / appointments.inc.php
blob718c9bf99dabc97ab854c9369c816c9e9e60c171
1 <?php
3 // Copyright (C) 2011 Ken Chapple
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // Holds library functions (and hashes) used by the appointment reporting module
12 $COMPARE_FUNCTION_HASH = array(
13 'doctor' => 'compareAppointmentsByDoctorName',
14 'patient' => 'compareAppointmentsByPatientName',
15 'pubpid' => 'compareAppointmentsByPatientId',
16 'date' => 'compareAppointmentsByDate',
17 'time' => 'compareAppointmentsByTime',
18 'type' => 'compareAppointmentsByType',
19 'comment' => 'compareAppointmentsByComment'
22 $ORDERHASH = array(
23 'doctor' => array( 'doctor', 'date', 'time' ),
24 'patient' => array( 'patient', 'date', 'time' ),
25 'pubpid' => array( 'pubpid', 'date', 'time' ),
26 'date' => array( 'date', 'time', 'type', 'patient' ),
27 'time' => array( 'time', 'date', 'patient' ),
28 'type' => array( 'type', 'date', 'time', 'patient' ),
29 'comment' => array( 'comment', 'date', 'time', 'patient' )
32 function fetchEvents( $from_date, $to_date, $where_param = null, $orderby_param = null )
34 $where =
35 "( (e.pc_endDate >= '$from_date' AND e.pc_eventDate <= '$to_date' AND e.pc_recurrtype = '1') OR " .
36 "(e.pc_eventDate >= '$from_date' AND e.pc_eventDate <= '$to_date') )";
37 if ( $where_param ) $where .= $where_param;
39 $order_by = "e.pc_eventDate, e.pc_startTime";
40 if ( $orderby_param ) {
41 $order_by = $orderby_param;
44 $query = "SELECT " .
45 "e.pc_eventDate, e.pc_endDate, e.pc_startTime, e.pc_endTime, e.pc_duration, e.pc_recurrtype, e.pc_recurrspec, e.pc_recurrfreq, e.pc_catid, e.pc_eid, " .
46 "e.pc_title, e.pc_hometext, " .
47 "p.fname, p.mname, p.lname, p.pid, p.pubpid, p.phone_home, p.phone_cell, " .
48 "u.fname AS ufname, u.mname AS umname, u.lname AS ulname, u.id AS uprovider_id, " .
49 "c.pc_catname, c.pc_catid " .
50 "FROM openemr_postcalendar_events AS e " .
51 "LEFT OUTER JOIN patient_data AS p ON p.pid = e.pc_pid " .
52 "LEFT OUTER JOIN users AS u ON u.id = e.pc_aid " .
53 "LEFT OUTER JOIN openemr_postcalendar_categories AS c ON c.pc_catid = e.pc_catid " .
54 "WHERE $where " .
55 "ORDER BY $order_by";
57 $res = sqlStatement( $query );
58 $events = array();
59 if ( $res )
61 while ( $row = sqlFetchArray($res) )
63 // if it's a repeating appointment, fetch all occurances in date range
64 if ( $row['pc_recurrtype'] ) {
65 $reccuringEvents = getRecurringEvents( $row, $from_date, $to_date );
66 $events = array_merge( $events, $reccuringEvents );
67 } else {
68 $events []= $row;
73 return $events;
76 function fetchAllEvents( $from_date, $to_date, $provider_id = null, $facility_id = null )
78 $where = "";
79 if ( $provider_id ) $where .= " AND e.pc_aid = '$provider_id'";
81 $facility_filter = '';
82 if ( $facility_id ) {
83 $event_facility_filter = " AND e.pc_facility = '$facility_id'";
84 $provider_facility_filter = " AND u.facility_id = '$facility_id'";
85 $facility_filter = $event_facility_filter . $provider_facility_filter;
88 $where .= $facility_filter;
89 $appointments = fetchEvents( $from_date, $to_date, $where );
90 return $appointments;
93 function fetchAppointments( $from_date, $to_date, $patient_id = null, $provider_id = null, $facility_id = null )
95 $where = "";
96 if ( $provider_id ) $where .= " AND e.pc_aid = '$provider_id'";
97 if ( $patient_id ) {
98 $where .= " AND e.pc_pid = '$patient_id'";
99 } else {
100 $where .= " AND e.pc_pid != ''";
103 $facility_filter = '';
104 if ( $facility_id ) {
105 $event_facility_filter = " AND e.pc_facility = '$facility_id'";
106 $provider_facility_filter = " AND u.facility_id = '$facility_id'";
107 $facility_filter = $event_facility_filter . $provider_facility_filter;
110 $where .= $facility_filter;
111 $appointments = fetchEvents( $from_date, $to_date, $where );
112 return $appointments;
115 function getRecurringEvents( $event, $from_date, $to_date )
117 $repeatEvents = array();
118 $from_date_time = strtotime( $from_date . " 00:00:00" );
119 $thistime = strtotime( $event['pc_eventDate'] . " 00:00:00" );
120 //$thistime = max( $thistime, $from_date_time );
121 if ( $event['pc_recurrtype'] )
123 preg_match( '/"event_repeat_freq_type";s:1:"(\d)"/', $event['pc_recurrspec'], $matches );
124 $repeattype = $matches[1];
126 preg_match( '/"event_repeat_freq";s:1:"(\d)"/', $event['pc_recurrspec'], $matches );
127 $repeatfreq = $matches[1];
128 if ( !$repeatfreq ) $repeatfreq = 1;
130 $upToDate = strtotime( $to_date." 23:59:59" ); // set the up-to-date to the last second of the "to_date"
131 $endtime = strtotime( $event['pc_endDate'] . " 23:59:59" );
132 if ( $endtime > $upToDate ) $endtime = $upToDate;
134 $repeatix = 0;
135 while ( $thistime < $endtime )
137 // Skip the event if a repeat frequency > 1 was specified and this is
138 // not the desired occurrence.
139 if ( !$repeatix ) {
140 $inRange = ( $thistime >= $from_date_time && $thistime < $upToDate );
141 if ( $inRange ) {
142 $newEvent = $event;
143 $eventDate = date( "Y-m-d", $thistime );
144 $newEvent['pc_eventDate'] = $eventDate;
145 $newEvent['pc_endDate'] = $eventDate;
146 $repeatEvents []= $newEvent;
150 if ( ++$repeatix >= $repeatfreq ) $repeatix = 0;
152 $adate = getdate($thistime);
153 if ($repeattype == 0) { // daily
154 $adate['mday'] += 1;
155 } else if ($repeattype == 1) { // weekly
156 $adate['mday'] += 7;
157 } else if ($repeattype == 2) { // monthly
158 $adate['mon'] += 1;
159 } else if ($repeattype == 3) { // yearly
160 $adate['year'] += 1;
161 } else if ($repeattype == 4) { // work days
162 if ($adate['wday'] == 5) // if friday, skip to monday
163 $adate['mday'] += 3;
164 else if ($adate['wday'] == 6) // saturday should not happen
165 $adate['mday'] += 2;
166 else
167 $adate['mday'] += 1;
168 } else {
169 die("Invalid repeat type '$repeattype'");
171 $thistime = mktime(0, 0, 0, $adate['mon'], $adate['mday'], $adate['year']);
175 return $repeatEvents;
178 // get the event slot size in seconds
179 function getSlotSize()
181 if ( isset( $GLOBALS['calendar_interval'] ) ) {
182 return $GLOBALS['calendar_interval'] * 60;
184 return 15 * 60;
187 function getAvailableSlots( $from_date, $to_date, $provider_id = null, $facility_id = null )
189 $appointments = fetchAllEvents( $from_date, $to_date, $provider_id, $facility_id );
190 $appointments = sortAppointments( $appointments, "date" );
191 $from_datetime = strtotime( $from_date." 00:00:00" );
192 $to_datetime = strtotime( $to_date." 23:59:59" );
193 $availableSlots = array();
194 $start_time = 0;
195 $date = 0;
196 for ( $i = 0; $i < count( $appointments ); ++$i )
198 if ( $appointments[$i]['pc_catid'] == 2 ) { // 2 == In Office
199 $start_time = $appointments[$i]['pc_startTime'];
200 $date = $appointments[$i]['pc_eventDate'];
201 $provider_id = $appointments[$i]['uprovider_id'];
202 } else if ( $appointments[$i]['pc_catid'] == 3 ) { // 3 == Out Of Office
203 continue;
204 } else {
205 $start_time = $appointments[$i]['pc_endTime'];
206 $date = $appointments[$i]['pc_eventDate'];
207 $provider_id = $appointments[$i]['uprovider_id'];
210 // find next appointment with the same provider
211 $next_appointment_date = 0;
212 $next_appointment_time = 0;
213 for ( $j = $i+1; $j < count( $appointments ); ++$j ) {
214 if ( $appointments[$j]['uprovider_id'] == $provider_id ) {
215 $next_appointment_date = $appointments[$j]['pc_eventDate'];
216 $next_appointment_time = $appointments[$j]['pc_startTime'];
217 break;
221 $same_day = ( strtotime( $next_appointment_date ) == strtotime( $date ) ) ? true : false;
223 if ( $next_appointment_time && $same_day ) {
224 // check the start time of the next appointment
226 $start_datetime = strtotime( $date." ".$start_time );
227 $next_appointment_datetime = strtotime( $next_appointment_date." ".$next_appointment_time );
228 $curr_time = $start_datetime;
229 while ( $curr_time < $next_appointment_datetime - (getSlotSize() / 2) ) {
230 //create a new appointment ever 15 minutes
231 $time = date( "H:i:s", $curr_time );
232 $available_slot = createAvailableSlot(
233 $appointments[$i]['pc_eventDate'],
234 $time,
235 $appointments[$i]['ufname'],
236 $appointments[$i]['ulname'],
237 $appointments[$i]['umname'] );
238 $availableSlots []= $available_slot;
239 $curr_time += getSlotSize(); // add a 15-minute slot
244 return $availableSlots;
247 function createAvailableSlot( $event_date, $start_time, $provider_fname, $provider_lname, $provider_mname = "", $cat_name = "Available" )
249 $newSlot = array();
250 $newSlot['ulname'] = $provider_lname;
251 $newSlot['ufname'] = $provider_fname;
252 $newSlot['umname'] = $provider_mname;
253 $newSlot['pc_eventDate'] = $event_date;
254 $newSlot['pc_startTime'] = $start_time;
255 $newSlot['pc_endTime'] = $start_time;
256 $newSlot['pc_catname'] = $cat_name;
257 return $newSlot;
260 function getCompareFunction( $code ) {
261 global $COMPARE_FUNCTION_HASH;
262 return $COMPARE_FUNCTION_HASH[$code];
265 function getComparisonOrder( $code ) {
266 global $ORDERHASH;
267 return $ORDERHASH[$code];
270 function sortAppointments( array $appointments, $orderBy = 'date' )
272 global $appointment_sort_order;
273 $appointment_sort_order = $orderBy;
274 usort( $appointments, "compareAppointments" );
275 return $appointments;
278 // cmp_function for usort
279 // The comparison function must return an integer less than, equal to,
280 // or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
281 function compareAppointments( $appointment1, $appointment2 )
283 global $appointment_sort_order;
284 $comparisonOrder = getComparisonOrder( $appointment_sort_order );
285 foreach ( $comparisonOrder as $comparison )
287 $cmp_function = getCompareFunction( $comparison );
288 $result = $cmp_function( $appointment1, $appointment2 );
289 if ( 0 != $result ) {
290 return $result;
294 return 0;
297 function compareBasic( $e1, $e2 )
299 if ( $e1 < $e2 ) {
300 return -1;
301 } else if ( $e1 > $e2 ) {
302 return 1;
305 return 0;
308 function compareAppointmentsByDate( $appointment1, $appointment2 )
310 $date1 = strtotime( $appointment1['pc_eventDate'] );
311 $date2 = strtotime( $appointment2['pc_eventDate'] );
313 return compareBasic( $date1, $date2 );
316 function compareAppointmentsByTime( $appointment1, $appointment2 )
318 $time1 = strtotime( $appointment1['pc_startTime'] );
319 $time2 = strtotime( $appointment2['pc_startTime'] );
321 return compareBasic( $time1, $time2 );
324 function compareAppointmentsByDoctorName( $appointment1, $appointment2 )
326 $name1 = $appointment1['ulname'];
327 $name2 = $appointment2['ulname'];
328 $cmp = compareBasic( $name1, $name2 );
329 if ( $cmp == 0 ) {
330 $name1 = $appointment1['ufname'];
331 $name2 = $appointment2['ufname'];
332 return compareBasic( $name1, $name2 );
335 return $cmp;
338 function compareAppointmentsByPatientName( $appointment1, $appointment2 )
340 $name1 = $appointment1['lname'];
341 $name2 = $appointment2['lname'];
342 $cmp = compareBasic( $name1, $name2 );
343 if ( $cmp == 0 ) {
344 $name1 = $appointment1['fname'];
345 $name2 = $appointment2['fname'];
346 return compareBasic( $name1, $name2 );
349 return $cmp;
352 function compareAppointmentsByType( $appointment1, $appointment2 )
354 $type1 = $appointment1['pc_catid'];
355 $type2 = $appointment2['pc_catid'];
356 return compareBasic( $type1, $type2 );
359 function compareAppointmentsByPatientId( $appointment1, $appointment2 )
361 $id1 = $appointment1['pubpid'];
362 $id2 = $appointment2['pubpid'];
363 return compareBasic( $id1, $id2 );
366 function compareAppointmentsByComment( $appointment1, $appointment2 )
368 $comment1 = $appointment1['pc_hometext'];
369 $comment2 = $appointment2['pc_hometext'];
370 return compareBasic( $comment1, $comment2 );