/** * Called by the Event Queue processor to process a reminder * on a task. * @access public * @param string $module Module name (not used) * @param string $type Type of event (not used) * @param integer $id ID of task being reminded * @param integer $owner Originator of event * @param mixed $args event-specific arguments. * @return mixed true, dequeue event, false, event stays in queue. * -1, event is destroyed. */ public function remind($module, $type, $id, $owner, &$args) { global $locale_char_set, $AppUI; $q = new w2p_Database_Query(); // At this stage we won't have an object yet if (!$this->load($id)) { return -1; // No point it trying again later. } $this->htmlDecode(); // Only remind on working days. $today = new w2p_Utilities_Date(); if (!$today->isWorkingDay()) { return true; } // Check if the task is completed if ($this->task_percent_complete == 100) { return -1; } $contacts = $this->getAssigned(); // Now we also check the owner of the task, as we will need // to notify them as well. $owner_is_not_assignee = false; $q->addTable('users', 'u'); $q->addJoin('contacts', 'c', 'c.contact_id = u.user_contact', 'inner'); $q->addQuery('c.contact_id, contact_first_name, contact_last_name, contact_email'); $q->addWhere('u.user_id = ' . (int) $this->task_owner); if ($q->exec(ADODB_FETCH_NUM)) { list($owner_contact, $owner_first_name, $owner_last_name, $owner_email) = $q->fetchRow(); if (!isset($contacts[$owner_contact])) { $owner_is_not_assignee = true; $contacts[$owner_contact] = array('contact_id' => $owner_contact, 'contact_first_name' => $owner_first_name, 'contact_last_name' => $owner_last_name, 'contact_email' => $owner_email); } } $q->clear(); // build the subject line, based on how soon the // task will be overdue. $starts = new w2p_Utilities_Date($this->task_start_date); $expires = new w2p_Utilities_Date($this->task_end_date); $now = new w2p_Utilities_Date(); $diff = $expires->dateDiff($now); $diff *= w2p_Utilities_Date::compare($expires, $now); $prefix = $AppUI->_('Task Due', UI_OUTPUT_RAW); if ($diff == 0) { $msg = $AppUI->_('TODAY', UI_OUTPUT_RAW); } elseif ($diff == 1) { $msg = $AppUI->_('TOMORROW', UI_OUTPUT_RAW); } elseif ($diff < 0) { $msg = $AppUI->_(array('OVERDUE', abs($diff), 'DAYS')); $prefix = $AppUI->_('Task', UI_OUTPUT_RAW); } else { $msg = $AppUI->_(array($diff, 'DAYS')); } $project = new CProject(); $project_name = $project->load($this->task_project)->project_name; // Check to see that the project is both active and not a template if (!$project->project_active || $project->project_status == w2PgetConfig('template_projects_status_id', 0)) { return -1; } $subject = $prefix . ' ' . $msg . ' ' . $this->task_name . '::' . $project_name; $body = $AppUI->_('Task Due', UI_OUTPUT_RAW) . ': ' . $msg . "\n" . $AppUI->_('Project', UI_OUTPUT_RAW) . ': ' . $project_name . "\n" . $AppUI->_('Task', UI_OUTPUT_RAW) . ': ' . $this->task_name . "\n" . $AppUI->_('Start Date', UI_OUTPUT_RAW) . ': START-TIME' . "\n" . $AppUI->_('Finish Date', UI_OUTPUT_RAW) . ': END-TIME' . "\n" . $AppUI->_('URL', UI_OUTPUT_RAW) . ': ' . W2P_BASE_URL . '/index.php?m=tasks&a=view&task_id=' . $this->task_id . '&reminded=1' . "\n\n" . $AppUI->_('Resources', UI_OUTPUT_RAW) . ":\n"; foreach ($contacts as $contact) { if (!$owner_is_not_assignee || $owner_is_not_assignee && $contact['contact_id'] != $owner_contact) { $body .= $contact['contact_first_name'] . ' ' . $contact['contact_last_name'] . ' <' . $contact['contact_email'] . ">\n"; } } $body .= "\n" . $AppUI->_('Description', UI_OUTPUT_RAW) . ":\n" . $this->task_description . "\n"; $mail = new w2p_Utilities_Mail(); $mail->Subject($subject, $locale_char_set); foreach ($contacts as $contact) { $user_id = CUser::getUserIdByContactID($contact['contact_id']); $AppUI->loadPrefs($user_id); $df = $AppUI->getPref('DISPLAYFORMAT'); $tz = $AppUI->getPref('TIMEZONE'); $body = str_replace('START-TIME', $starts->convertTZ($tz)->format($df), $body); $body = str_replace('END-TIME', $expires->convertTZ($tz)->format($df), $body); $mail->Body($body, $locale_char_set); if ($mail->ValidEmail($contact['contact_email'])) { $mail->To($contact['contact_email'], true); $mail->Send(); } } return true; }
function clash_process(CAppUI $AppUI) { global $do_include; $obj = new CEvent(); $obj->bind($_SESSION['add_event_post']); $attendees = $_SESSION['add_event_attendees']; $users = array(); if (isset($attendees) && $attendees) { $users = explode(',', $attendees); } array_push($users, $obj->event_owner); // First remove any duplicates $users = array_unique($users); // Now remove any null entries, so implode doesn't create a dud SQL // Foreach is safer as it works on a copy of the array. foreach ($users as $key => $user) { if (!$user) { unset($users[$key]); } } $start_date = new w2p_Utilities_Date($_POST['event_start_date'] . "000000"); $end_date = new w2p_Utilities_Date($_POST['event_end_date'] . "235959"); // First find any events in the range requested. $event_list = $obj->getEventsInWindow($start_date->format(FMT_DATETIME_MYSQL), $end_date->format(FMT_DATETIME_MYSQL), (int) ($_POST['start_time'] / 100), (int) ($_POST['end_time'] / 100), $users); $event_start_date = new w2p_Utilities_Date($_POST['event_start_date'] . $_POST['start_time']); $event_end_date = new w2p_Utilities_Date($_POST['event_end_date'] . $_POST['end_time']); if (!$event_list || !count($event_list)) { // First available date/time is OK, seed addEdit with the details. $obj->event_start_date = $event_start_date->format(FMT_DATETIME_MYSQL); $obj->event_end_date = $event_end_date->format(FMT_DATETIME_MYSQL); $_SESSION['add_event_post'] = get_object_vars($obj); $AppUI->setMsg('No clashes in suggested timespan', UI_MSG_OK); $_SESSION['event_is_clash'] = true; $_GET['event_id'] = $obj->event_id; $do_include = W2P_BASE_DIR . "/modules/calendar/addedit.php"; return; } // Now we grab the events, in date order, and compare against the // required start and end times. // Working in 30 minute increments from the start time, and remembering // the end time stipulation, find the first hole in the times. // Determine the duration in hours/minutes. $start_hour = (int) ($_POST['start_time'] / 10000); $start_minutes = (int) ($_POST['start_time'] % 10000 / 100); $start_time = $start_hour * 60 + $start_minutes; $end_hour = (int) ($_POST['end_time'] / 10000); $end_minutes = (int) ($_POST['end_time'] % 10000 / 100); $end_time = $end_hour * 60 + $end_minutes - $_POST['duration']; // First, build a set of "slots" that give us the duration // and start/end times we need $first_day = $start_date->format('%E'); $end_day = $end_date->format('%E'); $days_between = $end_day + 1 - $first_day; $oneday = new Date_Span(array(1, 0, 0, 0)); $slots = array(); $slot_count = 0; $first_date = new w2p_Utilities_Date($start_date); for ($i = 0; $i < $days_between; $i++) { if ($first_date->isWorkingDay()) { $slots[$i] = array(); for ($j = $start_time; $j <= $end_time; $j += 30) { $slot_count++; $slots[$i][] = array('date' => $first_date->format('%Y-%m-%d'), 'start_time' => $j, 'end_time' => $j + $_POST['duration'], 'committed' => false); } } $first_date->addSpan($oneday); } // Now process the events list foreach ($event_list as $event) { $sdate = new w2p_Utilities_Date($event['event_start_date']); $edate = new w2p_Utilities_Date($event['event_end_date']); $sday = $sdate->format('%E'); $day_offset = $sday - $first_day; // Now find the slots on that day that match list($syear, $smonth, $sday, $shour, $sminute, $ssecond) = sscanf($event['event_start_date'], "%4d-%2d-%2d %2d:%2d:%2d"); list($eyear, $emonth, $eday, $ehour, $eminute, $esecond) = sscanf($event['event_start_date'], "%4d-%2d-%2d %2d:%2d:%2d"); $start_mins = $shour * 60 + $sminute; $end_mins = $ehour * 60 + $eminute; if (isset($slots[$day_offset])) { foreach ($slots[$day_offset] as $key => $slot) { if ($start_mins <= $slot['end_time'] && $end_mins >= $slot['start_time']) { $slots[$day_offset][$key]['committed'] = true; } } } } // Third pass through, find the first uncommitted slot; foreach ($slots as $day_offset => $day_slot) { foreach ($day_slot as $slot) { if (!$slot['committed']) { $hour = (int) ($slot['start_time'] / 60); $min = $slot['start_time'] % 60; $ehour = (int) ($slot['end_time'] / 60); $emin = $slot['end_time'] % 60; $obj->event_start_date = $slot['date'] . ' ' . sprintf("%02d:%02d:00", $hour, $min); $obj->event_end_date = $slot['date'] . ' ' . sprintf("%02d:%02d:00", $ehour, $emin); $_SESSION['add_event_post'] = get_object_vars($obj); $AppUI->setMsg('First available time slot', UI_MSG_OK); $_SESSION['event_is_clash'] = true; $_GET['event_id'] = $obj->event_id; $do_include = W2P_BASE_DIR . '/modules/calendar/addedit.php'; return; } } } // If we get here we have found no available slots clear_clash(); $AppUI->setMsg('No times match your parameters', UI_MSG_ALERT); $AppUI->redirect(); }
/** * Called by the Event Queue processor to process a reminder * on a task. * @access public * @param string $notUsed Module name (not used) * @param string $notUsed2 Type of event (not used) * @param integer $id ID of task being reminded * @param integer $owner Originator of event * @param mixed $notUsed event-specific arguments. * * @return mixed true, dequeue event, false, event stays in queue. * -1, event is destroyed. */ public function remind($notUsed = null, $notUsed2 = null, $id, $owner, $notUsed3 = null) { // At this stage we won't have an object yet if (!$this->load($id)) { return -1; // No point it trying again later. } $this->htmlDecode(); // Only remind on working days. $today = new w2p_Utilities_Date(); if (!$today->isWorkingDay()) { return true; } // Check if the task is completed if ($this->task_percent_complete == 100) { return -1; } $contacts = $this->assignees($this->task_id); $contact = new CContact(); $owner = $contact->findContactByUserId($this->task_owner); $contacts[$owner->contact_id] = array('user_id' => $this->task_owner, 'contact_id' => $owner->contact_id, 'contact_name' => $owner->contact_display_name, 'contact_email' => $owner->contact_email); // build the subject line, based on how soon the // task will be overdue. $starts = new w2p_Utilities_Date($this->task_start_date); $expires = new w2p_Utilities_Date($this->task_end_date); $now = new w2p_Utilities_Date(); $diff = $expires->dateDiff($now); $diff *= $expires->compare($expires, $now); $prefix = $this->_AppUI->_('Task Due', UI_OUTPUT_RAW); if ($diff == 0) { $msg = $this->_AppUI->_('TODAY', UI_OUTPUT_RAW); } elseif ($diff == 1) { $msg = $this->_AppUI->_('TOMORROW', UI_OUTPUT_RAW); } elseif ($diff < 0) { $msg = $this->_AppUI->_(array('OVERDUE', abs($diff), 'DAYS')); $prefix = $this->_AppUI->_('Task', UI_OUTPUT_RAW); } else { $msg = $this->_AppUI->_(array($diff, 'DAYS')); } $project = new CProject(); $project->overrideDatabase($this->_query); $project_name = $project->load($this->task_project)->project_name; // Check to see that the project is both active and not a template if (!$project->project_active || $project->project_status == w2PgetConfig('template_projects_status_id', 0)) { return -1; } $subject = $prefix . ' ' . $msg . ' ' . $this->task_name . '::' . $project_name; $emailManager = new w2p_Output_EmailManager($this->_AppUI); $body = $emailManager->getTaskRemind($this, $msg, $project_name, $contacts); $mail = new w2p_Utilities_Mail(); $mail->Subject($subject); foreach ($contacts as $contact) { $user_id = $contact['user_id']; $this->_AppUI->loadPrefs($user_id); $df = $this->_AppUI->getPref('SHDATEFORMAT'); $tz = $this->_AppUI->getPref('TIMEZONE'); $body = str_replace('START-TIME', $starts->convertTZ($tz)->format($df), $body); $body = str_replace('END-TIME', $expires->convertTZ($tz)->format($df), $body); $mail->Body($body, $this->_locale_char_set); $mail->To($contact['contact_email'], true); $mail->Send(); } return true; }
public function calcFinish($duration, $durationType) { // since one will alter the date ($this) one better copies it to a new instance $finishDate = new w2p_Utilities_Date(); $finishDate->copy($this); // get w2P time constants $day_start_hour = intval(w2PgetConfig('cal_day_start')); $day_end_hour = intval(w2PgetConfig('cal_day_end')); $work_hours = intval(w2PgetConfig('daily_working_hours')); $duration_in_minutes = $durationType == 24 ? $duration * $work_hours * 60 : $duration * 60; // Jump to the first working day while (!$finishDate->isWorkingDay()) { $finishDate->addDays(1); } $first_day_minutes = min($day_end_hour * 60 - $finishDate->getHour() * 60 - $finishDate->getMinute(), $work_hours * 60, $duration_in_minutes); $finishDate->addSeconds($first_day_minutes * 60); $duration_in_minutes -= $first_day_minutes; while ($duration_in_minutes != 0) { // Jump to the next day $finishDate->addDays(1); // Reset date's time to the first hour in the morning $finishDate->setTime($day_start_hour); // Jump all non-working days while (!$finishDate->isWorkingDay()) { $finishDate->addDays(1); } $day_work_minutes = min($work_hours * 60, $duration_in_minutes); $finishDate->addSeconds($day_work_minutes * 60); $duration_in_minutes -= $day_work_minutes; } return $finishDate; }
/** * Tests isWorkingDay with a non working day, and call_working_days * is null */ public function testIsWorkingDayNullWorkingDaysNo() { global $w2Pconfig; $w2Pconfig['cal_working_days'] = null; $date = new w2p_Utilities_Date('2010-08-07 00:00:00'); $this->assertFalse($date->isWorkingDay()); }