. * --------------------------------------------------------------------- */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * CalendarSegment Class */ class CalendarSegment extends CommonDBChild { // From CommonDBTM public $dohistory = true; // From CommonDBChild static public $itemtype = 'Calendar'; static public $items_id = 'calendars_id'; /** * @since 0.84 **/ function getForbiddenStandardMassiveAction() { $forbidden = parent::getForbiddenStandardMassiveAction(); $forbidden[] = 'update'; return $forbidden; } static function getTypeName($nb = 0) { return _n('Time range', 'Time ranges', $nb); } function prepareInputForAdd($input) { // Check override of segment : do not add if (count(self::getSegmentsBetween($input['calendars_id'], $input['day'], $input['begin'], $input['day'], $input['end'])) > 0) { Session::addMessageAfterRedirect(__('Can not add a range riding an existing period'), false, ERROR); return false; } return parent::prepareInputForAdd($input); } /** * Duplicate all segments from a calendar to his clone * * @deprecated 9.5 * * @param $oldid * @param $newid **/ static function cloneCalendar($oldid, $newid) { global $DB; Toolbox::deprecated('Use clone'); $result = $DB->request( [ 'FROM' => self::getTable(), 'WHERE' => [ 'calendars_id' => $oldid, ] ] ); foreach ($result as $data) { $c = new self(); unset($data['id']); $data['calendars_id'] = $newid; $data['_no_history'] = true; $c->add($data); } } function post_addItem() { // Update calendar cache $cal = new Calendar(); $cal->updateDurationCache($this->fields['calendars_id']); parent::post_addItem(); } function post_deleteFromDB() { // Update calendar cache $cal = new Calendar(); $cal->updateDurationCache($this->fields['calendars_id']); parent::post_deleteFromDB(); } /** * Get segments of a calendar between 2 date * * @param integer $calendars_id id of the calendar * @param integer $begin_day begin day number * @param string $begin_time begin time to check * @param integer $end_day end day number * @param string $end_time end time to check **/ static function getSegmentsBetween($calendars_id, $begin_day, $begin_time, $end_day, $end_time) { // Do not check hour if day before the end day of after the begin day return getAllDataFromTable( 'glpi_calendarsegments', [ 'calendars_id' => $calendars_id, ['day' => ['>=', $begin_day]], ['day' => ['<=', $end_day]], ['OR' => [ 'begin' => ['<', $end_time], 'day' => ['<', $end_day] ]], ['OR' => [ 'end' => ['>=', $begin_time], 'day' => ['>', $begin_day] ]] ] ); } /** * Get active time between begin and end time in a day * * @param integer $calendars_id id of the calendar * @param integer $day day number * @param string $begin_time begin time to check * @param string $end_time end time to check * * @return integer Time in seconds **/ static function getActiveTimeBetween($calendars_id, $day, $begin_time, $end_time) { global $DB; $sum = 0; // Do not check hour if day before the end day of after the begin day $iterator = $DB->request([ 'SELECT' => [ new \QueryExpression(" TIMEDIFF( LEAST(" . $DB->quoteValue($end_time) .", " . $DB->quoteName('end') . "), GREATEST(" . $DB->quoteName('begin') . ", " . $DB->quoteValue($begin_time) . ") ) AS " . $DB->quoteName('TDIFF') ) ], 'FROM' => 'glpi_calendarsegments', 'WHERE' => [ 'calendars_id' => $calendars_id, 'day' => $day, 'begin' => ['<', $end_time], 'end' => ['>', $begin_time] ] ]); while ($data = $iterator->next()) { list($hour, $minute ,$second) = explode(':', $data['TDIFF']); $sum += $hour*HOUR_TIMESTAMP+$minute*MINUTE_TIMESTAMP+$second; } return $sum; } /** * Add a delay of a starting hour in a specific day * * @param integer $calendars_id id of the calendar * @param integer $day day number * @param string $begin_time begin time * @param integer $delay timestamp delay to add * * @return string|false Ending timestamp (HH:mm:dd) of delay or false if not applicable. **/ static function addDelayInDay($calendars_id, $day, $begin_time, $delay) { global $DB; // Do not check hour if day before the end day of after the begin day $iterator = $DB->request([ 'SELECT' => [ new \QueryExpression( "GREATEST(" . $DB->quoteName('begin') . ", " . $DB->quoteValue($begin_time) . ") AS " . $DB->quoteName('BEGIN') ), new \QueryExpression( "TIMEDIFF(" . $DB->quoteName('end') . ", GREATEST(" . $DB->quoteName('begin') . ", " . $DB->quoteValue($begin_time) . ")) AS " . $DB->quoteName('TDIFF') ) ], 'FROM' => 'glpi_calendarsegments', 'WHERE' => [ 'calendars_id' => $calendars_id, 'day' => $day, 'end' => ['>', $begin_time] ], 'ORDER' => 'begin' ]); while ($data = $iterator->next()) { list($hour, $minute, $second) = explode(':', $data['TDIFF']); $tstamp = $hour*HOUR_TIMESTAMP+$minute*MINUTE_TIMESTAMP+$second; // Delay is completed if ($delay <= $tstamp) { list($begin_hour, $begin_minute, $begin_second) = explode(':', $data['BEGIN']); $beginstamp = $begin_hour*HOUR_TIMESTAMP+$begin_minute*MINUTE_TIMESTAMP+$begin_second; $endstamp = $beginstamp+$delay; $units = Toolbox::getTimestampTimeUnits($endstamp); return str_pad($units['hour'], 2, '0', STR_PAD_LEFT).':'. str_pad($units['minute'], 2, '0', STR_PAD_LEFT).':'. str_pad($units['second'], 2, '0', STR_PAD_LEFT); } else { $delay -= $tstamp; } } return false; } /** * Get first working hour of a day * * @param integer $calendars_id id of the calendar * @param integer $day day number * * @return string Timestamp (HH:mm:dd) of first working hour **/ static function getFirstWorkingHour($calendars_id, $day) { global $DB; // Do not check hour if day before the end day of after the begin day $result = $DB->request([ 'SELECT' => ['MIN' => 'begin AS minb'], 'FROM' => 'glpi_calendarsegments', 'WHERE' => [ 'calendars_id' => $calendars_id, 'day' => $day ] ])->next(); return $result['minb']; } /** * Get last working hour of a day * * @param integer $calendars_id id of the calendar * @param integer $day day number * * @return string Timestamp (HH:mm:dd) of last working hour **/ static function getLastWorkingHour($calendars_id, $day) { global $DB; // Do not check hour if day before the end day of after the begin day $result = $DB->request([ 'SELECT' => ['MAX' => 'end AS mend'], 'FROM' => 'glpi_calendarsegments', 'WHERE' => [ 'calendars_id' => $calendars_id, 'day' => $day ] ])->next(); return $result['mend']; } /** * Is the hour passed is a working hour ? * * @param integer $calendars_id id of the calendar * @param integer $day day number * @param string $hour hour (Format HH:MM::SS) * * @return boolean **/ static function isAWorkingHour($calendars_id, $day, $hour) { global $DB; // Do not check hour if day before the end day of after the begin day $result = $DB->request([ 'COUNT' => 'cpt', 'FROM' => 'glpi_calendarsegments', 'WHERE' => [ 'calendars_id' => $calendars_id, 'day' => $day, 'begin' => ['<=', $hour], 'end' => ['>=', $hour] ] ])->next(); return $result['cpt'] > 0; } /** * Show segments of a calendar * * @param $calendar Calendar object **/ static function showForCalendar(Calendar $calendar) { global $DB; $ID = $calendar->getField('id'); if (!$calendar->can($ID, READ)) { return false; } $canedit = $calendar->can($ID, UPDATE); $rand = mt_rand(); $iterator = $DB->request([ 'FROM' => 'glpi_calendarsegments', 'WHERE' => [ 'calendars_id' => $ID ], 'ORDER' => [ 'day', 'begin', 'end' ] ]); $numrows = count($iterator); if ($canedit) { echo "
"; echo "
"; echo ""; echo ""; echo ""; echo "
".__('Add a schedule')."
"._n('Day', 'Days', 1).""; echo ""; Dropdown::showFromArray('day', Toolbox::getDaysOfWeekArray()); echo "".__('Start').''; Dropdown::showHours("begin", ['value' => date('H').":00"]); echo "".__('End').''; Dropdown::showHours("end", ['value' => (date('H')+1).":00"]); echo ""; echo ""; echo "
"; Html::closeForm(); echo "
"; } echo "
"; if ($canedit && $numrows) { Html::openMassiveActionsForm('mass'.__CLASS__.$rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $numrows), 'container' => 'mass'.__CLASS__.$rand]; Html::showMassiveActions($massiveactionparams); } echo ""; echo ""; if ($canedit && $numrows) { echo ""; } echo ""; echo ""; echo ""; echo ""; $daysofweek = Toolbox::getDaysOfWeekArray(); if ($numrows) { while ($data = $iterator->next()) { echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; } echo ""; } echo "
"; echo Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); echo ""._n('Day', 'Days', 1)."".__('Start')."".__('End')."
"; Html::showMassiveActionCheckBox(__CLASS__, $data["id"]); echo ""; echo $daysofweek[$data['day']]; echo "".$data["begin"]."".$data["end"]."
"; if ($canedit && $numrows) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } echo "
"; } function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { $nb = 0; switch ($item->getType()) { case 'Calendar' : if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable($this->getTable(), ['calendars_id' => $item->getID()]); } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb); } } return ''; } static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { if ($item->getType()=='Calendar') { self::showForCalendar($item); } return true; } }