/** * Sub-function to collect events within a period * @param Date the starting date of the period * @param Date the ending date of the period * @param array by-ref an array of links to append new items to * @param int the length to truncate entries by * @author Andrew Eddie <*****@*****.**> */ function getEventLinks($startPeriod, $endPeriod, &$links, $notUsed = null, $minical = false) { global $event_filter; $events = CEvent::getEventsForPeriod($startPeriod, $endPeriod, $event_filter); $cwd = explode(',', w2PgetConfig('cal_working_days')); // assemble the links for the events foreach ($events as $row) { $start = new w2p_Utilities_Date($row['event_start_date']); $end = new w2p_Utilities_Date($row['event_end_date']); $date = $start; for ($i = 0, $i_cmp = $start->dateDiff($end); $i <= $i_cmp; $i++) { // the link // optionally do not show events on non-working days if ($row['event_cwd'] && in_array($date->getDayOfWeek(), $cwd) || !$row['event_cwd']) { if ($minical) { $link = array(); } else { $url = '?m=calendar&a=view&event_id=' . $row['event_id']; $link['href'] = ''; $link['alt'] = ''; $link['text'] = w2PtoolTip($row['event_name'], getEventTooltip($row['event_id']), true) . w2PshowImage('event' . $row['event_type'] . '.png', 16, 16, '', '', 'calendar') . '</a> ' . '<a href="' . $url . '"><span class="event">' . $row['event_name'] . '</span></a>' . w2PendTip(); } $links[$date->format(FMT_TIMESTAMP_DATE)][] = $link; } $date = $date->getNextDay(); } } }
public function setDateRange($start_date, $end_date) { $min_d_start = new w2p_Utilities_Date($start_date); $max_d_end = new w2p_Utilities_Date($end_date); // check day_diff and modify Headers $day_diff = $min_d_start->dateDiff($max_d_end); //----------------------------------------- // nice Gantt image // if diff(end_date,start_date) > 90 days it shows only //week number // if diff(end_date,start_date) > 240 days it shows only //month number //----------------------------------------- if ($day_diff > 1096) { //more than 3 years, show only the year scale $this->graph->ShowHeaders(GANTT_HYEAR); $this->graph->scale->year->grid->Show(); $this->graph->scale->year->grid->SetStyle('longdashed'); $this->graph->scale->year->grid->SetColor('lightgray'); $this->graph->scale->year->SetFont(FF_CUSTOM, FS_NORMAL, 12); } else { if ($day_diff > 480) { //more than 480 days show only the firstletter of the month $this->graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH); $this->graph->scale->month->SetStyle(MONTHSTYLE_SHORTNAME); $this->graph->scale->month->grid->Show(); $this->graph->scale->month->grid->SetStyle('longdashed'); $this->graph->scale->month->grid->SetColor('lightgray'); $this->graph->scale->month->SetFont(FF_CUSTOM, FS_NORMAL, 10); } else { if ($day_diff > 240) { //more than 240 days and less than 481 show the month short name eg: Jan $this->graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH); $this->graph->scale->month->SetStyle(MONTHSTYLE_SHORTNAME); $this->graph->scale->month->grid->Show(); $this->graph->scale->month->grid->SetStyle('longdashed'); $this->graph->scale->month->grid->SetColor('lightgray'); $this->graph->scale->month->SetFont(FF_CUSTOM, FS_NORMAL, 10); } else { if ($day_diff > 90) { //more than 90 days and less of 241 $this->graph->ShowHeaders(GANTT_HMONTH | GANTT_HWEEK); $this->graph->scale->week->SetStyle(WEEKSTYLE_WNBR); $this->graph->scale->week->SetFont(FF_CUSTOM, FS_NORMAL, 7); } else { //more than 90 days and less of 241 $this->graph->ShowHeaders(GANTT_HMONTH | GANTT_HDAY); $this->graph->scale->day->SetStyle(DAYSTYLE_SHORTDATE4); $this->graph->scale->day->SetFont(FF_CUSTOM, FS_NORMAL, 7); } } } } $start_date = is_object($start_date) ? $start_date->format(FMT_DATETIME_MYSQL) : $start_date; $end_date = is_object($end_date) ? $end_date->format(FMT_DATETIME_MYSQL) : $end_date; $this->graph->SetDateRange($start_date, $end_date); }
/** * 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; }
/** Import tasks from another project * * @param int Project ID of the tasks come from. * @return bool **/ public function importTasks($from_project_id) { global $AppUI; $errors = array(); // Load the original $origProject = new CProject(); $origProject->load($from_project_id); $q = $this->_query; $q->addTable('tasks'); $q->addQuery('task_id'); $q->addWhere('task_project =' . (int) $from_project_id); $tasks = array_flip($q->loadColumn()); $q->clear(); $origDate = new w2p_Utilities_Date($origProject->project_start_date); $destDate = new w2p_Utilities_Date($this->project_start_date); $timeOffset = $origDate->dateDiff($destDate); if ($origDate->compare($origDate, $destDate) > 0) { $timeOffset = -1 * $timeOffset; } // Dependencies array $deps = array(); // Copy each task into this project and get their deps foreach ($tasks as $orig => $void) { $objTask = new CTask(); $objTask->load($orig); $destTask = $objTask->copy($this->project_id); $tasks[$orig] = $destTask; $deps[$orig] = $objTask->getDependencies(); } // Fix record integrity foreach ($tasks as $old_id => $newTask) { // Fix parent Task // This task had a parent task, adjust it to new parent task_id if ($newTask->task_id != $newTask->task_parent) { $newTask->task_parent = $tasks[$newTask->task_parent]->task_id; } // Fix task start date from project start date offset $origDate->setDate($newTask->task_start_date); $origDate->addDays($timeOffset); $destDate = $origDate; $newTask->task_start_date = $destDate->format(FMT_DATETIME_MYSQL); // Fix task end date from start date + work duration if (!empty($newTask->task_end_date) && $newTask->task_end_date != '0000-00-00 00:00:00') { $origDate->setDate($newTask->task_end_date); $origDate->addDays($timeOffset); $destDate = $origDate; $newTask->task_end_date = $destDate->format(FMT_DATETIME_MYSQL); } // Dependencies if (!empty($deps[$old_id])) { $oldDeps = explode(',', $deps[$old_id]); // New dependencies array $newDeps = array(); foreach ($oldDeps as $dep) { $newDeps[] = $tasks[$dep]->task_id; } // Update the new task dependencies $csList = implode(',', $newDeps); $newTask->updateDependencies($csList); } // end of update dependencies $result = $newTask->store($AppUI); $newTask->addReminder(); $importedTasks[] = $newTask->task_id; if (is_array($result) && count($result)) { foreach ($result as $key => $error_msg) { $errors[] = $newTask->task_name . ': ' . $error_msg; } } } // end Fix record integrity // We have errors, so rollback everything we've done so far if (count($errors)) { foreach ($importedTasks as $badTask) { $delTask = new CTask(); $delTask->task_id = $badTask; $delTask->delete($AppUI); } } return $errors; }
/** * Post Request Handler * * This method is called when a request is a POST * * @return array */ public function executePost() { /** * @todo Remove this once we figure out how to reference vars in file * that is autoloaded */ global $tracking_dynamics; $valid = $this->hasRequiredParameters($this->requiredParams); if ($valid instanceof Frapi_Error) { return $valid; } $username = $this->getParam('username'); $password = $this->getParam('password'); $project_id = $this->getParam('project_id', self::TYPE_INT); $hassign = $this->getParam('hassign'); $hdependencies = $this->getParam('hdependencies'); $notify = $this->getParam('task_notify'); $comment = $this->getParam('email_comment'); $task_id = $this->getParam('task_id'); $adjustStartDate = $this->getParam('set_task_start_date'); $task = new CTask(); // Attempt to login as user, a little bit of a hack as we currently // require the $_POST['login'] var to be set as well as a global AppUI $AppUI = new CAppUI(); $GLOBALS['AppUI'] = $AppUI; $_POST['login'] = '******'; if (!$AppUI->login($username, $password)) { throw new Frapi_Error('INVALID_LOGIN'); } $post_data = array('task_id' => $this->getParam('task_id'), 'task_name' => $this->getParam('task_name'), 'task_status' => $this->getParam('task_status'), 'task_percent_complete' => $this->getParam('task_percent_complete'), 'task_milestone' => $this->getParam('task_milestone'), 'task_owner' => $this->getParam('task_owner'), 'task_access' => $this->getParam('task_access'), 'task_related_url' => $this->getParam('task_related_url'), 'task_parent' => $this->getParam('task_parent'), 'task_type' => $this->getParam('task_type'), 'task_target_budget' => $this->getParam('task_target_budget'), 'task_description' => $this->getParam('task_description'), 'task_start_date' => $this->getParam('task_start_date'), 'task_end_date' => $this->getParam('task_end_date'), 'task_duration' => $this->getParam('task_duration'), 'task_duration_type' => $this->getParam('task_duration_type'), 'task_dynamic' => $this->getParam('task_dynamic'), 'task_allow_other_user_tasklogs' => $this->getParam('task_allow_other_user_tasklogs'), 'task_project' => $this->getParam('task_project'), 'task_priority' => $this->getParam('task_priority')); // Include any files for handling module-specific requirements foreach (findTabModules('tasks', 'addedit') as $mod) { $fname = W2P_BASE_DIR . '/modules/' . $mod . '/tasks_dosql.addedit.php'; if (file_exists($fname)) { require_once $fname; } } // Find the task if we are set $task_end_date = null; if ($task_id) { $task->load($task_id); $task_end_date = new w2p_Utilities_Date($task->task_end_date); } $task = new CTask(); if (!$task->bind($post_data)) { throw new Frapi_Error('SAVE_ERROR', $task->getError()); } if ($task->task_dynamic != 1) { $task_dynamic_delay = $this->getParam('task_dynamic_nodelay') ? $this->getParam('task_dynamic_nodelay') : '0'; if (in_array($task->task_dynamic, $tracking_dynamics)) { $task->task_dynamic = $task_dynamic_delay ? 21 : 31; } else { $task->task_dynamic = $task_dynamic_delay ? 11 : 0; } } // Let's check if task_dynamic is unchecked if (!$this->getParam('task_dynamic')) { $task->task_dynamic = false; } // Make sure task milestone is set or reset as appropriate if ($this->getParam('task_milestone')) { $task->task_milestone = false; } //format hperc_assign user_id=percentage_assignment;user_id=percentage_assignment;user_id=percentage_assignment; $tmp_ar = explode(';', $this->getParam('hperc_assign')); $i_cmp = sizeof($tmp_ar); $hperc_assign_ar = array(); for ($i = 0; $i < $i_cmp; $i++) { $tmp = explode('=', $tmp_ar[$i]); if (count($tmp) > 1) { $hperc_assign_ar[$tmp[0]] = $tmp[1]; } elseif ($tmp[0] != '') { $hperc_assign_ar[$tmp[0]] = 100; } } // let's check if there are some assigned departments to task $task->task_departments = implode(',', $this->getParam('dept_ids', self::TYPE_ARRAY)); // convert dates to SQL format first if ($task->task_start_date) { $date = new w2p_Utilities_Date($task->task_start_date); $task->task_start_date = $date->format(FMT_DATETIME_MYSQL); } $end_date = null; if ($task->task_end_date) { if (strpos($task->task_end_date, '2400') !== false) { $task->task_end_date = str_replace('2400', '2359', $task->task_end_date); } $end_date = new w2p_Utilities_Date($task->task_end_date); $task->task_end_date = $end_date->format(FMT_DATETIME_MYSQL); } $error_array = $task->store($AppUI); // Return all the validation messages if ($error_array !== true) { $error_message = ''; foreach ($error_array as $error) { $error_message .= $error . '. '; } throw new Frapi_Error('SAVE_ERROR', $error_message); } $task_parent = $this->getParam('task_parent') ? $this->getParam('task_parent', SELF::TYPE_INT) : 0; $old_task_parent = $this->getParam('old_task_parent') ? $this->getParam('old_task_parent', SELF::TYPE_INT) : 0; if ($task_parent != $old_task_parent) { $oldTask = new CTask(); $oldTask->load($old_task_parent); $oldTask->updateDynamics(false); } // How to handle custom fields? Do we support it in api? // Now add any task reminders // If there wasn't a task, but there is one now, and // that task date is set, we need to set a reminder. if (empty($task_end_date) || !empty($end_date) && $task_end_date->dateDiff($end_date)) { $task->addReminder(); } if (isset($hassign)) { $task->updateAssigned($hassign, $hperc_assign_ar); } if (isset($hdependencies)) { // && !empty($hdependencies)) { // there are dependencies set! // backup initial start and end dates $tsd = new w2p_Utilities_Date($task->task_start_date); $ted = new w2p_Utilities_Date($task->task_end_date); // updating the table recording the // dependency relations with this task $task->updateDependencies($hdependencies, $task_parent); // we will reset the task's start date based upon dependencies // and shift the end date appropriately if ($adjustStartDate && !is_null($hdependencies)) { // load already stored task data for this task $tempTask = new CTask(); $tempTask->load($task->task_id); // shift new start date to the last dependency end date $nsd = new w2p_Utilities_Date($tempTask->get_deps_max_end_date($tempTask)); // prefer Wed 8:00 over Tue 16:00 as start date $nsd = $nsd->next_working_day(); // prepare the creation of the end date $ned = new w2p_Utilities_Date(); $ned->copy($nsd); if (empty($task->task_start_date)) { // appropriately calculated end date via start+duration $ned->addDuration($task->task_duration, $task->task_duration_type); } else { // calc task time span start - end $d = $tsd->calcDuration($ted); // Re-add (keep) task time span for end date. // This is independent from $obj->task_duration. // The value returned by Date::Duration() is always in hours ('1') $ned->addDuration($d, '1'); } // prefer tue 16:00 over wed 8:00 as an end date $ned = $ned->prev_working_day(); $task->task_start_date = $nsd->format(FMT_DATETIME_MYSQL); $task->task_end_date = $ned->format(FMT_DATETIME_MYSQL); $q = new w2p_Database_Query(); $q->addTable('tasks', 't'); $q->addUpdate('task_start_date', $task->task_start_date); $q->addUpdate('task_end_date', $task->task_end_date); $q->addWhere('task_id = ' . (int) $task->task_id); $q->addWhere('task_dynamic <> 1'); $q->exec(); $q->clear(); } $task->pushDependencies($task->task_id, $task->task_end_date); } //$task = (array)$task; $task->load($task_id); unset($task->_query, $task->_error, $task->_tbl_prefix, $task->_tbl, $task->_tbl_key, $task->_tbl_module); $this->data['task'] = $task; $this->data['success'] = true; return $this->toArray(); }
function displayWeeks($list, $task, $level, $fromPeriod, $toPeriod) { if ($fromPeriod == -1) { return ''; } $s = new w2p_Utilities_Date($fromPeriod); $e = new w2p_Utilities_Date($toPeriod); $sw = getBeginWeek($s); $dw = ceil($e->dateDiff($s) / 7); $ew = $sw + $dw; $st = new w2p_Utilities_Date($task->task_start_date); $et = new w2p_Utilities_Date($task->task_end_date); $stw = getBeginWeek($st); $dtw = ceil($et->dateDiff($st) / 7); $etw = $stw + $dtw; $row = ''; for ($i = $sw; $i <= $ew; $i++) { if ($i >= $stw and $i < $etw) { $color = 'blue'; if ($level == 0 and hasChildren($list, $task)) { $color = '#C0C0FF'; } elseif ($level == 1 and hasChildren($list, $task)) { $color = '#9090FF'; } $row .= '<td nowrap="nowrap" bgcolor="' . $color . '">'; } else { $row .= '<td nowrap="nowrap">'; } $row .= '  </td>'; } return $row; }
$fetched_projects[$task->task_project] = $task_data['project_name']; } $user_usage = array(); $task_dates = array(); $actual_date = $start_date; $days_header = ''; // we will save days title here $user_tasks_counted_in = array(); $user_names = array(); if (count($task_list) == 0) { echo '<p>' . $AppUI->_('No data available') . '</p>'; } else { foreach ($task_list as $task) { $task_start_date = new w2p_Utilities_Date($task->task_start_date); $task_end_date = new w2p_Utilities_Date($task->task_end_date); $day_difference = $task_end_date->dateDiff($task_start_date); $actual_date = $task_start_date; $users = $task->getAssignedUsers($task->task_id); if ($coarseness == 1) { userUsageDays(); } elseif ($coarseness == 7) { userUsageWeeks(); } } if ($coarseness == 1) { showDays(); } elseif ($coarseness == 7) { showWeeks(); } ?> <center><table class="std">
/** * Sub-function to collect tasks within a period * * @param Date the starting date of the period * @param Date the ending date of the period * @param array by-ref an array of links to append new items to * @param int the length to truncate entries by * @param int the company id to filter by * @author Andrew Eddie <*****@*****.**> */ function getTaskLinks($startPeriod, $endPeriod, &$links, $strMaxLen, $company_id = 0, $minical = false) { global $a, $AppUI, $w2Pconfig; $tasks = CTask::getTasksForPeriod($startPeriod, $endPeriod, $company_id, 0); $df = $AppUI->getPref('SHDATEFORMAT'); $tf = $AppUI->getPref('TIMEFORMAT'); //subtract one second so we don't have to compare the start dates for exact matches with the startPeriod which is 00:00 of a given day. $startPeriod->subtractSeconds(1); $link = array(); $sid = 3600 * 24; // assemble the links for the tasks foreach ($tasks as $row) { // the link $link['task'] = true; if (!$minical) { $link['href'] = '?m=tasks&a=view&task_id=' . $row['task_id']; // the link text if (mb_strlen($row['task_name']) > $strMaxLen) { $row['short_name'] = mb_substr($row['task_name'], 0, $strMaxLen) . '...'; } else { $row['short_name'] = $row['task_name']; } $link['text'] = '<span style="color:' . bestColor($row['color']) . ';background-color:#' . $row['color'] . '">' . $row['short_name'] . ($row['task_milestone'] ? ' ' . w2PshowImage('icons/milestone.gif') : '') . '</span>'; } // determine which day(s) to display the task $start = new w2p_Utilities_Date($AppUI->formatTZAwareTime($row['task_start_date'], '%Y-%m-%d %T')); $end = $row['task_end_date'] ? new w2p_Utilities_Date($AppUI->formatTZAwareTime($row['task_end_date'], '%Y-%m-%d %T')) : null; // First we test if the Tasks Starts and Ends are on the same day, if so we don't need to go any further. if ($start->after($startPeriod) && ($end && $end->after($startPeriod) && $end->before($endPeriod) && !$start->dateDiff($end))) { if ($minical) { $temp = array('task' => true); } else { $temp = $link; if ($a != 'day_view') { $temp['text'] = w2PtoolTip($row['task_name'], getTaskTooltip($row['task_id'], true, true, $tasks), true) . w2PshowImage('block-start-16.png') . $start->format($tf) . ' ' . $temp['text'] . ' ' . $end->format($tf) . w2PshowImage('block-end-16.png') . w2PendTip(); $temp['text'] .= '<a href="?m=tasks&a=view&task_id=' . $row['task_id'] . '&tab=1&date=' . $AppUI->formatTZAwareTime($row['task_end_date'], '%Y%m%d') . '">' . w2PtoolTip('Add Log', 'create a new log record against this task') . w2PshowImage('edit_add.png') . w2PendTip() . '</a>'; } } $links[$end->format(FMT_TIMESTAMP_DATE)][] = $temp; } else { // If they aren't, we will now need to see if the Tasks Start date is between the requested period if ($start->after($startPeriod) && $start->before($endPeriod)) { if ($minical) { $temp = array('task' => true); } else { $temp = $link; if ($a != 'day_view') { $temp['text'] = w2PtoolTip($row['task_name'], getTaskTooltip($row['task_id'], true, false, $tasks), true) . w2PshowImage('block-start-16.png') . $start->format($tf) . ' ' . $temp['text'] . w2PendTip(); $temp['text'] .= '<a href="?m=tasks&a=view&task_id=' . $row['task_id'] . '&tab=1&date=' . $AppUI->formatTZAwareTime($row['task_start_date'], '%Y%m%d') . '">' . w2PtoolTip('Add Log', 'create a new log record against this task') . w2PshowImage('edit_add.png') . w2PendTip() . '</a>'; } } $links[$start->format(FMT_TIMESTAMP_DATE)][] = $temp; } // And now the Tasks End date is checked if it is between the requested period too. if ($end && $end->after($startPeriod) && $end->before($endPeriod) && $start->before($end)) { if ($minical) { $temp = array('task' => true); } else { $temp = $link; if ($a != 'day_view') { $temp['text'] = w2PtoolTip($row['task_name'], getTaskTooltip($row['task_id'], false, true, $tasks), true) . ' ' . $temp['text'] . ' ' . $end->format($tf) . w2PshowImage('block-end-16.png') . w2PendTip(); $temp['text'] .= '<a href="?m=tasks&a=view&task_id=' . $row['task_id'] . '&tab=1&date=' . $AppUI->formatTZAwareTime($row['task_end_date'], '%Y%m%d') . '">' . w2PtoolTip('Add Log', 'create a new log record against this task') . w2PshowImage('edit_add.png') . w2PendTip() . '</a>'; } } $links[$end->format(FMT_TIMESTAMP_DATE)][] = $temp; } } } }
$obj->task_start_date = $AppUI->formatTZAwareTime($new_start_date, '%Y-%m-%d %T'); $new_end_date = $ned->format(FMT_DATETIME_MYSQL); $obj->task_end_date = $AppUI->formatTZAwareTime($new_end_date, '%Y-%m-%d %T'); $obj->store(); } } } $obj->updateDynamics(); $billingCategory = w2PgetSysVal('BudgetCategory'); $budgets = array(); foreach ($billingCategory as $id => $category) { $budgets[$id] = w2PgetParam($_POST, 'budget_' . $id, 0); } $obj->storeBudget($budgets); // Now add any task reminders // If there wasn't a task, but there is one now, and // that task date is set, we need to set a reminder. if (empty($task_end_date) || !empty($end_date) && $task_end_date->dateDiff($end_date)) { $obj->addReminder(); } $AppUI->setMsg($task_id ? 'Task updated' : 'Task added', UI_MSG_OK); if ($notify) { $obj->notify($comment); } $redirect = 'm=projects&a=view&project_id=' . $obj->task_project; } else { $AppUI->setMsg($obj->getError(), UI_MSG_ERROR, true); $AppUI->holdObject($obj); $redirect = 'm=tasks&a=addedit&task_id=' . $obj->task_id; } $AppUI->redirect($redirect);
</a> </span> </td> <td bgcolor="#dddddd" width="10%"><?php echo $row['contact_first_name'] . ' ' . $row['contact_last_name']; ?> </td> <td align="center" width="10%"><?php echo $row['replies']; ?> </td> <td bgcolor="#dddddd" width="150" nowrap="nowrap"> <?php if ($row['latest_reply']) { echo $AppUI->formatTZAwareTime($row['latest_reply'], $df . ' ' . $tf) . '<br /><font color="#999966">('; $diff = $now->dateDiff($last); echo (int) $diff . ' ' . $AppUI->_('days ago'); echo ')</font>'; } else { echo $AppUI->_('No replies'); } ?> </td> </tr> <?php } } ?> </table> <table width="100%" border="0" cellpadding="0" cellspacing="1" class="std">
/** * 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; }
/** * Import tasks from another project * * @param int Project ID of the tasks come from. * @return bool * * @todo - this entire thing has nothing to do with projects.. it should move to the CTask class - dkc 25 Nov 2012 * @todo - why are we returning either an array or a boolean? You make my head hurt. - dkc 25 Nov 2012 * * @todo - we should decide if we want to include the contacts associated with each task * @todo - we should decide if we want to include the files associated with each task * @todo - we should decide if we want to include the links associated with each task * * Of the three - contacts, files, and links - I can see a case made for * all three. Imagine you have a task which requires a particular form to * be filled out (Files) but there's also documentation you need about it * (Links) and once the task is underway, you need to let some people * know (Contacts). - dkc 25 Nov 2012 * */ public function importTasks($from_project_id, $to_project_id, $project_start_date) { $errors = array(); $old_new_task_mapping = array(); $old_dependencies = array(); $old_parents = array(); $project_start_date = new w2p_Utilities_Date($project_start_date); $newTask = new w2p_Actions_BulkTasks(); $task_list = $newTask->loadAll('task_start_date', "task_represents_project = 0 AND task_project = " . $from_project_id); $first_task = array_shift($task_list); /** * This gets the first (earliest) task start date and figures out * how much we have to shift all the tasks by. */ $original_start_date = new w2p_Utilities_Date($first_task['task_start_date']); $timeOffset = $original_start_date->dateDiff($project_start_date); array_unshift($task_list, $first_task); foreach ($task_list as $orig_task) { $orig_id = $orig_task['task_id']; $new_start_date = new w2p_Utilities_Date($orig_task['task_start_date']); $new_start_date->addDays($timeOffset); $new_end_date = new w2p_Utilities_Date($orig_task['task_end_date']); $new_end_date->addDays($timeOffset); $old_parents[$orig_id] = $orig_task['task_parent']; $orig_task['task_id'] = 0; $orig_task['task_parent'] = 0; $orig_task['task_project'] = $to_project_id; $orig_task['task_sequence'] = 0; $orig_task['task_path_enumeration'] = ''; $orig_task['task_hours_worked'] = 0; // This is necessary because we're using bind() and it shifts by timezone $orig_task['task_start_date'] = $this->_AppUI->formatTZAwareTime($new_start_date->format(FMT_DATETIME_MYSQL), '%Y-%m-%d %T'); $orig_task['task_end_date'] = $this->_AppUI->formatTZAwareTime($new_end_date->format(FMT_DATETIME_MYSQL), '%Y-%m-%d %T'); $_newTask = new w2p_Actions_BulkTasks(); $_newTask->bind($orig_task); $_newTask->store(); $task_map[$orig_id] = $_newTask->task_id; $old_dependencies[$orig_id] = array_keys($_newTask->getDependentTaskList($orig_id)); $old_new_task_mapping[$orig_id] = $_newTask->task_id; } if (count($errors)) { $this->_error = $errors; foreach ($old_new_task_mapping as $new_id) { $newTask->task_id = $new_id; $newTask->delete(); } } else { $q = $this->_getQuery(); /* This makes sure we have all the dependencies mapped out. */ foreach ($old_dependencies as $from => $to_array) { foreach ($to_array as $to) { $q->addTable('task_dependencies'); $q->addInsert('dependencies_req_task_id', $old_new_task_mapping[$from]); $q->addInsert('dependencies_task_id', $old_new_task_mapping[$to]); $q->exec(); $q->clear(); } } /* This makes sure all the parents are connected properly. */ foreach ($old_parents as $old_child => $old_parent) { if ($old_child == $old_parent) { /** Remember, this means skip the rest of the loop. */ continue; } $q->addTable('tasks'); $q->addUpdate('task_parent', $old_new_task_mapping[$old_parent]); $q->addWhere('task_id = ' . $old_new_task_mapping[$old_child]); $q->exec(); $q->clear(); } /* This copies the task assigness to the new tasks. */ foreach ($old_new_task_mapping as $old_id => $new_id) { $newTask->task_id = $old_id; $newTask->copyAssignedUsers($new_id); } } $_task = new CTask(); $task_list = $_task->loadAll('task_parent, task_id', "task_project = " . $to_project_id); foreach ($task_list as $key => $data) { $_task->load($key); $_task->_updatePathEnumeration(); if (!$_task->task_parent) { $q->addTable('tasks'); $q->addUpdate('task_parent', $_task->task_id); $q->addUpdate('task_updated', "'" . $q->dbfnNowWithTZ() . "'", false, true); $q->addWhere('task_id = ' . (int) $_task->task_id); $q->exec(); $q->clear(); } } $_task->updateDynamics(); $last_task_data = $this->getLastTaskData($to_project_id); CProject::updateTaskCache($to_project_id, $last_task_data['task_id'], $last_task_data['last_date'], $this->getTaskCount($to_project_id)); return $errors; }
/** * Tests dateDiff when the date being compared against is in the past and is * a partial day */ public function testDateDiffPastPartialDay() { $date = new w2p_Utilities_Date('2010-08-11 00:00:00'); $date_diff = $date->dateDiff(new w2p_Utilities_Date('2010-08-07 06:00:00')); $this->assertEquals(4, $date_diff); }
function showtask_pr(&$a, $level = 0, $today_view = false) { global $AppUI, $w2Pconfig, $done, $query_string, $durnTypes, $userAlloc, $showEditCheckbox; global $task_access, $task_priority; $types = w2Pgetsysval('TaskType'); $now = new w2p_Utilities_Date(); $tf = $AppUI->getPref('TIMEFORMAT'); $df = $AppUI->getPref('SHDATEFORMAT'); $fdf = $df . ' ' . $tf; $perms =& $AppUI->acl(); $show_all_assignees = $w2Pconfig['show_all_task_assignees'] ? true : false; $done[] = $a['task_id']; $start_date = intval($a['task_start_date']) ? new w2p_Utilities_Date($a['task_start_date']) : null; $end_date = intval($a['task_end_date']) ? new w2p_Utilities_Date($a['task_end_date']) : null; $last_update = isset($a['last_update']) && intval($a['last_update']) ? new w2p_Utilities_Date($a['last_update']) : null; // prepare coloured highlight of task time information $sign = 1; $style = ''; if ($start_date) { if (!$end_date) { $end_date = new w2p_Utilities_Date('0000-00-00 00:00:00'); } $days = $now->dateDiff($end_date) * $sign; } $s = '<tr>'; // dots $s .= '<td nowrap width="20%">'; for ($y = 0; $y < $level; $y++) { if ($y + 1 == $level) { $s .= '<img src="' . w2PfindImage('corner-dots.gif', $m) . '" width="16" height="12" border="0" alt="" />'; } else { $s .= '<img src="' . w2PfindImage('shim.gif', $m) . '" width="16" height="12" border="0" alt="" />'; } } // name link $alt = mb_strlen($a['task_description']) > 80 ? mb_substr($a['task_description'], 0, 80) . '...' : $a['task_description']; // instead of the statement below $alt = mb_str_replace('"', """, $alt); $alt = mb_str_replace("\r", ' ', $alt); $alt = mb_str_replace("\n", ' ', $alt); $open_link = w2PshowImage('collapse.gif'); if ($a['task_milestone'] > 0) { $s .= ' <b>' . $a["task_name"] . '</b><!--</a>--> <img src="' . w2PfindImage('icons/milestone.gif', $m) . '" border="0" alt="" /></td>'; } elseif ($a['task_dynamic'] == '1') { $s .= $open_link; $s .= '<strong>' . $a['task_name'] . '</strong>'; } else { $s .= $a['task_name']; } // percent complete $s .= '<td align="right">' . (int) $a['task_percent_complete'] . '%</td>'; $s .= '<td nowrap="nowrap" align="center" style="' . $style . '">' . ($start_date ? $start_date->format($df . ' ' . $tf) : '-') . '</td>'; $s .= '</td>'; $s .= '<td nowrap="nowrap" align="center" style="' . $style . '">' . ($end_date ? $end_date->format($df . ' ' . $tf) : '-') . '</td>'; $s .= '</td>'; $s .= '<td nowrap="nowrap" align="center" style="' . $style . '">' . ($last_update ? $last_update->format($df . ' ' . $tf) : '-') . '</td>'; echo $s; }
$task_end_date = new w2p_Utilities_Date($task->task_end_date); $task->task_percent_complete = w2PgetParam($_POST, 'task_percent_complete', null); if (w2PgetParam($_POST, 'task_end_date', '') != '') { $new_date = new w2p_Utilities_Date($_POST['task_end_date']); $new_date->setTime($task_end_date->hour, $task_end_date->minute, $task_end_date->second); $task->task_end_date = $new_date->format(FMT_DATETIME_MYSQL); } if ($task->task_percent_complete >= 100 && (!$task->task_end_date || $task->task_end_date == '0000-00-00 00:00:00')) { $task->task_end_date = $obj->task_log_date; } $msg = $task->store($AppUI); if (is_array($msg)) { $AppUI->setMsg($msg, UI_MSG_ERROR, true); } $new_task_end = new w2p_Utilities_Date($task->task_end_date); if ($new_task_end->dateDiff($task_end_date)) { $task->addReminder(); } $task->pushDependencies($task->task_id, $task->task_end_date); } if ('on' == $notify_owner) { if ($msg = $task->notifyOwner()) { $AppUI->setMsg($msg, UI_MSG_ERROR); } } // Check if we need to email the task log to anyone. $email_assignees = w2PgetParam($_POST, 'email_assignees', null); $email_task_contacts = w2PgetParam($_POST, 'email_task_contacts', null); $email_project_contacts = w2PgetParam($_POST, 'email_project_contacts', null); $email_others = w2PgetParam($_POST, 'email_others', ''); $email_log_user = w2PgetParam($_POST, 'email_log_user', '');