. * * For more information, contact Colosa Inc, 2566 Le Jeune Rd., * Coral Gables, FL, 33134, USA, or email info@colosa.com. * * * * @name calendar * created 2010-03-22 * * @author Hugo Loza 2010-03-22 * */ require_once ("classes/model/CalendarDefinition.php"); /** * A Calendar object where it is defined Working Days, Business Hours and Holidays * A Calendar is applied to a User, Process or Task * Extends CalendarDefinition. * * @author Hugo Loza 2010-03-22 * @uses CalendarDefinition * @package workflow.engine.classes * */ class calendar extends CalendarDefinition { public $pmCalendarUid = ''; public $pmCalendarData = array(); public function getCalendar ($userUid, $proUid = null, $tasUid = null) { require_once 'classes/model/CalendarAssignments.php'; $criteria = new Criteria ( 'workflow' ); $criteria->clearSelectColumns ( ); $calendarData = array(); //Default Calendar $calendarData['UID'] = '00000000000000000000000000000001'; $calendarData['TYPE'] = 'DEFAULT'; //Load User,Task and Process calendars (if exist) $criteria->addSelectColumn ( CalendarAssignmentsPeer::CALENDAR_UID ); $criteria->addSelectColumn ( CalendarAssignmentsPeer::OBJECT_UID ); $criteria->addSelectColumn ( CalendarAssignmentsPeer::OBJECT_TYPE ); $criteria->add ( CalendarAssignmentsPeer::OBJECT_UID, array($userUid, $proUid, $tasUid), CRITERIA::IN ); $oDataset = CalendarAssignmentsPeer::doSelectRS ( $criteria ); $oDataset->setFetchmode ( ResultSet::FETCHMODE_ASSOC ); $oDataset->next (); $calendarArray = array(); while (is_array($aRow = $oDataset->getRow ())) { if ($aRow['OBJECT_UID']==$userUid) { $calendarArray['USER'] = $aRow ['CALENDAR_UID']; } if ($aRow['OBJECT_UID']==$proUid) { $calendarArray['PROCESS'] = $aRow ['CALENDAR_UID']; } if ($aRow['OBJECT_UID']==$tasUid) { $calendarArray['TASK'] = $aRow ['CALENDAR_UID']; } $oDataset->next (); } if (isset($calendarArray['USER'])) { $calendarData['UID'] = $calendarArray['USER']; $calendarData['TYPE'] = 'USER'; } elseif (isset($calendarArray['PROCESS'])) { $calendarData['UID'] = $calendarArray['PROCESS']; $calendarData['TYPE'] = 'PROCESS'; } elseif (isset($calendarArray['TASK'])) { $calendarData['UID'] = $calendarArray['TASK']; $calendarData['TYPE'] = 'TASK'; } $this->pmCalendarUid = $calendarData['UID']; return $this->pmCalendarUid; } public function getCalendarData ($calendarUid = null) { require_once ( 'classes/model/CalendarDefinition.php' ); $calendarUid = (is_null($calendarUid)) ? $this->pmCalendarUid : $calendarUid; $this->pmCalendarUid = $calendarUid; //if exists the row in the database propel will update it, otherwise will insert. $tr = CalendarDefinitionPeer::retrieveByPK ( $calendarUid ); $defaultCalendar ['CALENDAR_UID'] = '00000000000000000000000000000001'; $defaultCalendar ['CALENDAR_NAME'] = 'Default'; $defaultCalendar ['CALENDAR_CREATE_DATE'] = date ( 'Y-m-d' ); $defaultCalendar ['CALENDAR_UPDATE_DATE'] = date ( 'Y-m-d' ); $defaultCalendar ['CALENDAR_DESCRIPTION'] = 'Default'; $defaultCalendar ['CALENDAR_STATUS'] = 'ACTIVE'; $defaultCalendar ['CALENDAR_WORK_DAYS'] = '1|2|3|4|5'; $defaultCalendar ['CALENDAR_WORK_DAYS'] = explode ( '|', '1|2|3|4|5' ); $defaultCalendar ['BUSINESS_DAY'] [1] ['CALENDAR_BUSINESS_DAY'] = 7; $defaultCalendar ['BUSINESS_DAY'] [1] ['CALENDAR_BUSINESS_START'] = '09:00'; $defaultCalendar ['BUSINESS_DAY'] [1] ['CALENDAR_BUSINESS_END'] = '17:00'; $defaultCalendar ['BUSINESS_DAY'] [1] ['DIFF_HOURS'] = '8'; $defaultCalendar ['HOURS_FOR_DAY'] = '8'; $defaultCalendar ['HOLIDAY'] = array (); if ((is_object ( $tr ) && get_class ( $tr ) == 'CalendarDefinition')) { $fields ['CALENDAR_UID'] = $tr->getCalendarUid (); $fields ['CALENDAR_NAME'] = $tr->getCalendarName (); $fields ['CALENDAR_CREATE_DATE'] = $tr->getCalendarCreateDate (); $fields ['CALENDAR_UPDATE_DATE'] = $tr->getCalendarUpdateDate (); $fields ['CALENDAR_DESCRIPTION'] = $tr->getCalendarDescription (); $fields ['CALENDAR_STATUS'] = $tr->getCalendarStatus (); $fields ['CALENDAR_WORK_DAYS'] = $tr->getCalendarWorkDays (); $fields ['CALENDAR_WORK_DAYS_A'] = explode ( '|', $tr->getCalendarWorkDays () ); } else { $fields=$defaultCalendar; //$this->saveCalendarInfo ( $fields ); $fields ['CALENDAR_WORK_DAYS'] = '1|2|3|4|5'; $fields ['CALENDAR_WORK_DAYS_A'] = explode ( '|', '1|2|3|4|5' ); //$tr = CalendarDefinitionPeer::retrieveByPK ( $calendarUid ); } $CalendarBusinessHoursObj = new CalendarBusinessHours ( ); $CalendarBusinessHours = $this->getCalendarBusinessHours ( $calendarUid ); $numDay = 8; $daysHours = array(); $hoursCant = array(); $modaHours = 0; $keyModa = 0; foreach ($CalendarBusinessHours as $value) { if ($value['CALENDAR_BUSINESS_DAY'] != $numDay) { $numDay = $value['CALENDAR_BUSINESS_DAY']; $daysHours[$numDay] = 0; } $daysHours[$numDay] += $value['DIFF_HOURS']; } foreach ($daysHours as $value) { if (isset($hoursCant[$value])) { $hoursCant[$value]++; } else { $hoursCant[$value] = 1; } } foreach ($hoursCant as $key => $value) { if ($value > $modaHours ) { $modaHours = $value; $keyModa = $key; } } $fields ['HOURS_FOR_DAY'] = $keyModa; $fields ['BUSINESS_DAY'] = $CalendarBusinessHours; $CalendarHolidaysObj = new CalendarHolidays ( ); $CalendarHolidays = $this->getCalendarHolidays ( $calendarUid ); $fields ['HOLIDAY'] = $CalendarHolidays; $fields=$this->validateCalendarInfo($fields, $defaultCalendar); $this->pmCalendarData = $fields; return $this->pmCalendarData; } public function getCalendarBusinessHours ($calendarUid = null) { require_once ( 'classes/model/CalendarBusinessHours.php' ); $calendarUid = (is_null($calendarUid)) ? $this->pmCalendarUid : $calendarUid; $this->pmCalendarUid = $calendarUid; $criteria = new Criteria('workflow'); $criteria->clearSelectColumns ( ); $criteria->addSelectColumn ( CalendarBusinessHoursPeer::CALENDAR_UID ); $criteria->addSelectColumn ( CalendarBusinessHoursPeer::CALENDAR_BUSINESS_DAY ); $criteria->addSelectColumn ( CalendarBusinessHoursPeer::CALENDAR_BUSINESS_START ); $criteria->addSelectColumn ( CalendarBusinessHoursPeer::CALENDAR_BUSINESS_END ); $criteria->add ( CalendarBusinessHoursPeer::CALENDAR_UID, $calendarUid , CRITERIA::EQUAL ); $criteria->addDescendingOrderByColumn ( CalendarBusinessHoursPeer::CALENDAR_BUSINESS_DAY ); $criteria->addAscendingOrderByColumn ( CalendarBusinessHoursPeer::CALENDAR_BUSINESS_START ); $rs = CalendarBusinessHoursPeer::doSelectRS($criteria); $rs->setFetchmode(ResultSet::FETCHMODE_ASSOC); $rs->next(); $row = $rs->getRow(); $fields = array(); $count = 0; while (is_array($row)) { $count++; $iniTime = (float)str_replace(':', '', $row['CALENDAR_BUSINESS_START']); $finTime = (float)str_replace(':', '', $row['CALENDAR_BUSINESS_END']); $row['DIFF_HOURS'] = (($finTime-$iniTime)/100); $fields[$count] = $row; $rs->next(); $row = $rs->getRow(); } return $fields; } public function getCalendarHolidays ($calendarUid = null) { require_once ( 'classes/model/CalendarHolidays.php' ); $calendarUid = (is_null($calendarUid)) ? $this->pmCalendarUid : $calendarUid; $this->pmCalendarUid = $calendarUid; $criteria = new Criteria('workflow'); $criteria->clearSelectColumns ( ); $criteria->addSelectColumn ( CalendarHolidaysPeer::CALENDAR_UID ); $criteria->addSelectColumn ( CalendarHolidaysPeer::CALENDAR_HOLIDAY_NAME ); $criteria->addSelectColumn ( CalendarHolidaysPeer::CALENDAR_HOLIDAY_START ); $criteria->addSelectColumn ( CalendarHolidaysPeer::CALENDAR_HOLIDAY_END ); $criteria->add ( CalendarHolidaysPeer::CALENDAR_UID, $calendarUid , CRITERIA::EQUAL ); $rs = CalendarHolidaysPeer::doSelectRS($criteria); $rs->setFetchmode(ResultSet::FETCHMODE_ASSOC); $rs->next(); $row = $rs->getRow(); $fields=array(); $count=0; while (is_array($row)) { $count++; $a=explode(' ',$row['CALENDAR_HOLIDAY_START']); $row['CALENDAR_HOLIDAY_START']=$a[0]; $a=explode(' ',$row['CALENDAR_HOLIDAY_END']); $row['CALENDAR_HOLIDAY_END']=$a[0]; $fields[$count] = $row; $rs->next(); $row = $rs->getRow(); } return $fields; } public function validateCalendarInfo ($fields, $defaultCalendar) { try { //Validate if Working days are Correct //Minimun 3 ? $workingDays=explode ( '|', $fields['CALENDAR_WORK_DAYS'] ); if (count($workingDays)<3) { throw (new Exception ( 'You must define at least 3 Working Days!' )); } //Validate that all Working Days have Bussines Hours if (count($fields ['BUSINESS_DAY'])<1) { throw (new Exception ( 'You must define at least one Business Day for all days' )); } $workingDaysOK=array(); foreach ($workingDays as $key => $day) { $workingDaysOK[$day]=false; } $sw_all = false; foreach ($fields ['BUSINESS_DAY'] as $keyB => $businessHours) { if (($businessHours['CALENDAR_BUSINESS_DAY']==7)) { $sw_all=true; } elseif((in_array($businessHours['CALENDAR_BUSINESS_DAY'],$workingDays))) { $workingDaysOK[$businessHours['CALENDAR_BUSINESS_DAY']]=true; } } $sw_days = true; foreach ($workingDaysOK as $day => $sw_day) { $sw_days = $sw_days && $sw_day; } if (!($sw_all || $sw_days)) { throw (new Exception ( 'Not all working days have their correspondent business day' )); } //Validate Holidays return $fields; } catch (Exception $e) { //print $e->getMessage(); //$this->addCalendarLog('!!!!!!! BAD CALENDAR DEFINITION. '.$e->getMessage()); $defaultCalendar ['CALENDAR_WORK_DAYS'] = '1|2|3|4|5'; $defaultCalendar ['CALENDAR_WORK_DAYS_A'] = explode ( '|', '1|2|3|4|5' ); return $defaultCalendar; } } /** * * @param string(32) $userUid * @param string(32) $proUid * @param string(32) $tasUid */ function calendar ($userUid = NULL, $proUid = NULL, $tasUid = NULL) { $this->userUid = $userUid; $this->proUid = $proUid; $this->tasUid = $tasUid; $this->calendarLog = ""; $this->setupCalendar( $userUid, $proUid, $tasUid ); } /** * Small function used to add important information about the calcs and actions * to the log (that log will be saved) * * @name addCalendarLog * @param text $msg * @access public * */ function addCalendarLog ($msg) { $this->calendarLog .= "\n" . date( "D M j G:i:s T Y" ) . ": " . $msg; } /** * setupCalendar is used to generate a valid instance of calendar using $userUid, $proUid and $tasUid * to find a valid calendar. * If there is no valid calendar then use the Default * * @name setupCalendar * @param string(32) $userUid * @param string(32) $proUid * @param string(32) $tasUid * @return void */ function setupCalendar ($userUid, $proUid, $tasUid) { $calendarDefinition = $this->getCalendarFor( $userUid, $proUid, $tasUid ); $this->calendarUid = $calendarDefinition['CALENDAR_UID']; $this->calendarDefinition = $calendarDefinition; } //// FUNTION CALCULATE DATE public function calculateDate ($iniDate, $duration, $formatDuration, $calendarData = array()) { $calendarData = (count($calendarData)) ? $calendarData : $this->pmCalendarData; $this->pmCalendarData = $calendarData; if ( G::toUpper($formatDuration) == 'DAYS' ) { $duration = $duration*$this->pmCalendarData['HOURS_FOR_DAY']; } /* $log = array(); $titles = array(); $titles[] = 'HOURS'; $titles[] = 'DATE'; $titles[] = '**DAY'; $titles[] = '**RANGE'; $titles[] = '**HOURS RANGE'; $titles[] = '**SUM HOURS'; $titles[] = '**NEXT DATE'; $log[] = $titles; $dataLog = array(); $dataLog[] = $duration; $dataLog[] = $iniDate; $dataLog[] = '-----'; $dataLog[] = '-----'; $dataLog[] = '-----'; $dataLog[] = '-----'; $dataLog[] = '-----'; $log[] = $dataLog; */ $hoursDuration = (float)$duration; $newDate = $iniDate; while ($hoursDuration > 0) { //$dataLog = array(); $newDate = $this->getIniDate($newDate); //$dataLog[] = $hoursDuration; //$dataLog[] = $newDate; $rangeWorkHour = $this->getRangeWorkHours($newDate, $calendarData['BUSINESS_DAY']); $onlyDate = (date('Y-m-d',strtotime($newDate))) . ' ' . $rangeWorkHour['END']; //$dataLog[] = date('l',strtotime($newDate)); //$dataLog[] = $rangeWorkHour['START'] . ' / ' . $rangeWorkHour['END']; //$dataLog[] = $rangeWorkHour['TOTAL']; if ( (((float)$hoursDuration) >= ((float)$rangeWorkHour['TOTAL'])) || ((strtotime($onlyDate) - strtotime($newDate)) < (((float)$hoursDuration)*3600)) ) { $secondRes = (float)(strtotime($onlyDate) - strtotime($newDate)); $newDate = $onlyDate; $hoursDuration -= (float)($secondRes/3600); //$dataLog[] = (float)($secondRes/3600); } else { $newDate = date('Y-m-d H:i:s', strtotime('+' . (((float)$hoursDuration)*3600) . ' seconds', strtotime($newDate))); //$dataLog[] = (float)($hoursDuration); $hoursDuration = 0; } //$dataLog[] = $newDate; //$log[] = $dataLog; } //$this->showLog($log); $result['DUE_DATE'] = $newDate; $result['DUE_DATE_SECONDS'] = strtotime($newDate); return $result; } public function calculateDuration ($iniDate, $finDate = null, $calendarData = array()) { if ((is_null($finDate)) || ($finDate == '')) { $finDate = date('Y-m-d H:i:s'); } $calendarData = (count($calendarData)) ? $calendarData : $this->pmCalendarData; $this->pmCalendarData = $calendarData; $secondDuration = 0.00; if ( (strtotime($iniDate)) < (strtotime($finDate)) ) { $timeIniDate = strtotime($iniDate); $timeFinDate = strtotime($finDate); } elseif ( (strtotime($finDate)) < (strtotime($iniDate)) ) { $timeIniDate = strtotime($finDate); $timeFinDate = strtotime($iniDate); $auxDate = $iniDate; $iniDate = $finDate; $finDate = $auxDate; } else { return $secondDuration; } $finDate = $this->getIniDate($finDate); $newDate = $iniDate; while ($timeIniDate < $timeFinDate) { //$dataLog = array(); $newDate = $this->getIniDate($newDate); //$dataLog[] = $hoursDuration; //$dataLog[] = $newDate; $rangeWorkHour = $this->getRangeWorkHours($newDate, $calendarData['BUSINESS_DAY']); $onlyDate = (date('Y-m-d',strtotime($newDate))) . ' ' . $rangeWorkHour['END']; //$dataLog[] = date('l',strtotime($newDate)); //$dataLog[] = $rangeWorkHour['START'] . ' / ' . $rangeWorkHour['END']; //$dataLog[] = $rangeWorkHour['TOTAL']; if ( (strtotime($finDate)) < (strtotime($onlyDate)) ) { $secondRes = ( ((float)strtotime($finDate)) - ((float)strtotime($newDate)) ); $timeIniDate = strtotime($finDate); $secondDuration += (float)$secondRes; } else { $secondRes = ( ((float)strtotime($onlyDate)) - ((float)strtotime($newDate)) ); $newDate = $onlyDate; $timeIniDate = strtotime($onlyDate); $secondDuration += (float)$secondRes; } //$dataLog[] = $newDate; //$log[] = $dataLog; } return $secondDuration; } public function getRangeWorkHours ($date, $workHours) { $auxIniDate = explode(' ', $date); $timeDate = $auxIniDate['1']; $timeDate = (float)str_replace(':', '', ((strlen($timeDate) == 8) ? $timeDate : $timeDate.':00') ); $weekDay = date('w',strtotime($date)); $workHoursDay = array(); $tempWorkHoursDay = array(); foreach ($workHours as $value) { if ($value['CALENDAR_BUSINESS_DAY'] == $weekDay) { $rangeWorkHour = array(); $timeStart = $value['CALENDAR_BUSINESS_START']; $timeEnd = $value['CALENDAR_BUSINESS_END']; $rangeWorkHour['START'] = ((strlen($timeStart) == 8) ? $timeStart : $timeStart.':00'); $rangeWorkHour['END'] = ((strlen($timeEnd) == 8) ? $timeEnd : $timeEnd.':00'); $workHoursDay[] = $rangeWorkHour; } if ($value['CALENDAR_BUSINESS_DAY'] == '7') { $rangeWorkHour = array(); $timeStart = $value['CALENDAR_BUSINESS_START']; $timeEnd = $value['CALENDAR_BUSINESS_END']; $rangeWorkHour['START'] = ((strlen($timeStart) == 8) ? $timeStart : $timeStart.':00'); $rangeWorkHour['END'] = ((strlen($timeEnd) == 8) ? $timeEnd : $timeEnd.':00'); $tempWorkHoursDay[] = $rangeWorkHour; } } if ( !(count($workHoursDay)) ) { $workHoursDay = $tempWorkHoursDay; } foreach ($workHoursDay as $value) { $iniTime = (float)str_replace(':', '', $value['START']); $finTime = (float)str_replace(':', '', $value['END']); if ( ($iniTime <= $timeDate) && ($timeDate <= $finTime) ) { //pr($finTime .' menos '.$iniTime .' = '.($finTime-$iniTime)); $value['TOTAL'] = (($finTime-$iniTime)/10000); return $value; } } return false; } public function getIniDate ($iniDate, $calendarData = array()) { $calendarData = (count($calendarData)) ? $calendarData : $this->pmCalendarData; $this->pmCalendarData = $calendarData; $flagIniDate = true; while ($flagIniDate) { // 1 if it's a work day $weekDay = date('w',strtotime($iniDate)); if ( !(in_array($weekDay, $calendarData['CALENDAR_WORK_DAYS_A'])) ) { $iniDate = date('Y-m-d'.' 00:00:00' , strtotime('+1 day', strtotime($iniDate))); continue; } // 2 if it's a holiday $iniDateHolidayDay = $this->is_holiday($iniDate); if ($iniDateHolidayDay) { $iniDate = date('Y-m-d'.' 00:00:00' , strtotime('+1 day', strtotime($iniDate))); continue; } // 3 if it's work time $workHours = $this->nextWorkHours($iniDate, $weekDay); if ( !($workHours['STATUS']) ) { $iniDate = date('Y-m-d'.' 00:00:00' , strtotime('+1 day', strtotime($iniDate))); continue; } else { $iniDate = $workHours['DATE']; } $flagIniDate = false; } return $iniDate; } public function nextWorkHours ($date, $weekDay, $workHours = array()) { $workHours = (count($workHours)) ? $workHours : $this->pmCalendarData['BUSINESS_DAY']; $auxIniDate = explode(' ', $date); $timeDate = $auxIniDate['1']; $timeDate = (float)str_replace(':', '', ((strlen($timeDate) == 8) ? $timeDate : $timeDate.':00') ); $nextWorkHours = array(); $workHoursDay = array(); $tempWorkHoursDay = array(); foreach ($workHours as $value) { if ($value['CALENDAR_BUSINESS_DAY'] == $weekDay) { $rangeWorkHour = array(); $timeStart = $value['CALENDAR_BUSINESS_START']; $timeEnd = $value['CALENDAR_BUSINESS_END']; $rangeWorkHour['START'] = ((strlen($timeStart) == 8) ? $timeStart : $timeStart.':00'); $rangeWorkHour['END'] = ((strlen($timeEnd) == 8) ? $timeEnd : $timeEnd.':00'); $workHoursDay[] = $rangeWorkHour; } if ($value['CALENDAR_BUSINESS_DAY'] == '7') { $rangeWorkHour = array(); $timeStart = $value['CALENDAR_BUSINESS_START']; $timeEnd = $value['CALENDAR_BUSINESS_END']; $rangeWorkHour['START'] = ((strlen($timeStart) == 8) ? $timeStart : $timeStart.':00'); $rangeWorkHour['END'] = ((strlen($timeEnd) == 8) ? $timeEnd : $timeEnd.':00'); $tempWorkHoursDay[] = $rangeWorkHour; } } if ( !(count($workHoursDay)) ) { $workHoursDay = $tempWorkHoursDay; } $countHours = count($workHoursDay); if ($countHours) { for ($i = 1; $i < $countHours; $i++) { for ($j = 0; $j < $countHours-$i; $j++) { $dataft = (float)str_replace(':', '', $workHoursDay[$j]['START']); $datasc = (float)str_replace(':', '', $workHoursDay[$j+1]['END']); if ($dataft > $datasc) { $aux = $workHoursDay[$j+1]; $workHoursDay[$j+1] = $workHoursDay[$j]; $workHoursDay[$j] = $aux; } } } foreach ($workHoursDay as $value) { $iniTime = (float)str_replace(':', '', ((strlen($value['START']) == 8) ? $value['START'] : $value['START'].':00')); $finTime = (float)str_replace(':', '', ((strlen($value['END']) == 8) ? $value['END'] : $value['END'].':00')); if ( $timeDate <= $iniTime ) { $nextWorkHours['STATUS'] = true; $nextWorkHours['DATE'] = $auxIniDate['0'] . ' ' . ((strlen($value['START']) == 8) ? $value['START'] : $value['START'].':00'); return $nextWorkHours; } elseif ( ($iniTime <= $timeDate) && ($timeDate < $finTime) ) { $nextWorkHours['STATUS'] = true; $nextWorkHours['DATE'] = $date; return $nextWorkHours; } } } $nextWorkHours['STATUS'] = false; return $nextWorkHours; } public function is_holiday ($date, $holidays = array()) { $holidays = (count($holidays)) ? $holidays : $this->pmCalendarData['HOLIDAY']; $auxIniDate = explode(' ', $date); $iniDate = $auxIniDate['0']; $iniDate = strtotime($iniDate); foreach ($holidays as $value) { $holidayStartDate = strtotime(date('Y-m-d',strtotime($value['CALENDAR_HOLIDAY_START']))); $holidayEndDate = strtotime(date('Y-m-d',strtotime($value['CALENDAR_HOLIDAY_END']))); if ( ($holidayStartDate <= $iniDate) && ($iniDate <= $holidayEndDate) ) { return true; } } return false; } /** * getnextValidBusinessHoursrange is used recursivily to find a valid BusinessHour * for the given $date and $time. * This function use all the exeptions defined for * Working days, Business Hours and Holidays. * * @author Hugo Loza * @name getNextValidBusinessHoursRange * @param date $date * @param time $time * * @var array $businessHoursA Object with all the infromation about the valid Business Hours found * $return array('DATE'=>$date,'TIME'=>$time,'BUSINESS_HOURS'=>$businessHoursA) */ function getNextValidBusinessHoursRange ($date, $time) { $this->addCalendarLog( "================= Start : $date,$time ================" ); //First Validate if is a valid date $sw_valid_date = false; $sw_date_changed = false; while (! $sw_valid_date) { $dateArray = explode( "-", $date ); $hour = 0; $minute = 0; $second = 0; $month = $dateArray[1]; $day = $dateArray[2]; $year = $dateArray[0]; $weekDay = date( "w", mktime( $hour, $minute, $second, $month, $day, $year ) ); $weekDayLabel = date( "l", mktime( $hour, $minute, $second, $month, $day, $year ) ); $dateInt = mktime( $hour, $minute, $second, $month, $day, $year ); $this->addCalendarLog( "**** $weekDayLabel ($weekDay) * $date" ); $sw_week_day = false; $sw_not_holiday = true; if (in_array( $weekDay, $this->calendarDefinition['CALENDAR_WORK_DAYS_A'] )) { $sw_week_day = true; } if (! $sw_week_day) { $this->addCalendarLog( "Valid working Dates: " . $this->calendarDefinition['CALENDAR_WORK_DAYS_A'] ); $this->addCalendarLog( "- Non working Day" ); } foreach ($this->calendarDefinition['HOLIDAY'] as $key => $holiday) { //Normalize Holiday date to SAME year of date $holidayStartA = explode( " ", $holiday['CALENDAR_HOLIDAY_START'] ); $holidayStartA = explode( "-", $holidayStartA[0] ); $normalizedHolidayStart = date( "Y-m-d", mktime( $hour, $minute, $second, $holidayStartA[1], $holidayStartA[2], $year ) ); $normalizedHolidayStartInt = mktime( $hour, $minute, $second, $holidayStartA[1], $holidayStartA[2], $year ); $holidayEndA = explode( " ", $holiday['CALENDAR_HOLIDAY_END'] ); $holidayEndA = explode( "-", $holidayEndA[0] ); $normalizedHolidayEnd = date( "Y-m-d", mktime( $hour, $minute, $second, $holidayEndA[1], $holidayEndA[2], $year ) ); $normalizedHolidayEndInt = mktime( $hour, $minute, $second, $holidayEndA[1], $holidayEndA[2], $year ); $sw_not_holiday_aux = true; if ($dateInt >= $normalizedHolidayStartInt && $dateInt <= $normalizedHolidayEndInt) { $sw_not_holiday = false; $sw_not_holiday_aux = false; } if (! $sw_not_holiday_aux) { $this->addCalendarLog( "It is a holiday -> " . $holiday['CALENDAR_HOLIDAY_NAME'] . " ($normalizedHolidayStart - $normalizedHolidayEnd)" ); } } $sw_valid_date = $sw_week_day && $sw_not_holiday; if (! $sw_valid_date) { //Go to next day $date = date( "Y-m-d", mktime( $hour, $minute + 1, $second, $month, $day + 1, $year ) ); $sw_date_changed = true; } else { $this->addCalendarLog( "FOUND VALID DATE -> $date" ); //We got a valid day, now get the valid Business Hours //Here Need to find a rule to get the most nea $businessHoursA = array (); $prevHour = "00:00"; if ($sw_date_changed) { // If date has changed then Use the first available period $time = "00:01"; } foreach ($this->calendarDefinition['BUSINESS_DAY'] as $keyBH => $businessHours) { // First the period may correspond to ALL or to the current week day if (($businessHours['CALENDAR_BUSINESS_DAY'] == 7) || ($businessHours['CALENDAR_BUSINESS_DAY'] == $weekDay)) { $this->addCalendarLog( "Validating ($time/$prevHour) From: " . $businessHours['CALENDAR_BUSINESS_START'] . " to " . $businessHours['CALENDAR_BUSINESS_END'] ); //Prev Hour $prevHourA = explode( ":", $prevHour ); $prevHourSeconds = ($prevHourA[0] * 60 * 60) + ($prevHour[1] * 60); $calendarBusinessStartA = explode( ":", $businessHours['CALENDAR_BUSINESS_START'] ); $calendarBusinessStartSeconds = ($calendarBusinessStartA[0] * 60 * 60) + ($calendarBusinessStartA[1] * 60); $calendarBusinessEndA = explode( ":", $businessHours['CALENDAR_BUSINESS_END'] ); $calendarBusinessEndSeconds = ($calendarBusinessEndA[0] * 60 * 60) + ($calendarBusinessEndA[1] * 60); $timeAuxA = explode( ":", $time ); $timeAuxSeconds = ($timeAuxA[0] * 60 * 60) + ($timeAuxA[1] * 60); if (($timeAuxSeconds >= $prevHourSeconds) && ($timeAuxSeconds < $calendarBusinessEndSeconds)) { $this->addCalendarLog( "*** FOUND VALID BUSINESS HOUR " . $businessHours['CALENDAR_BUSINESS_START'] . " - " . $businessHours['CALENDAR_BUSINESS_END'] ); if ($timeAuxSeconds < $calendarBusinessStartSeconds) { //Out of range then assign first hour $this->addCalendarLog( "Set to default start hour to: " . $businessHours['CALENDAR_BUSINESS_START'] ); $time = $businessHours['CALENDAR_BUSINESS_START']; } $prevHour = $businessHours['CALENDAR_BUSINESS_END']; $businessHoursA = $businessHours; } } } } if (empty( $businessHoursA )) { $this->addCalendarLog( "> No Valid Business Hour found for current date, go to next" ); $date = date( "Y-m-d", mktime( $hour, $minute + 1, $second, $month, $day + 1, $year ) ); $sw_date_changed = true; $sw_valid_date = false; } } $return['DATE'] = $date; $return['TIME'] = $time; $return['BUSINESS_HOURS'] = $businessHoursA; return $return; } } ?>