/** */ protected function _content() { global $conf, $prefs, $registry; $html = ''; if (!empty($this->_params['show_alarms'])) { $messages = array(); try { $alarmList = Nag::listAlarms($_SERVER['REQUEST_TIME']); } catch (Nag_Exception $e) { return '<em>' . htmlspecialchars($e->getMessage()) . '</em>'; } foreach ($alarmList as $task) { $differential = $task->getNextDue()->timestamp() - $_SERVER['REQUEST_TIME']; $key = $differential; while (isset($messages[$key])) { $key++; } $viewurl = Horde::url('view.php', true)->add(array('task' => $task->id, 'tasklist' => $task->tasklist)); $link = $viewurl->link() . (!empty($task->name) ? htmlspecialchars($task->name) : _("[none]")) . '</a>'; if ($differential >= -60 && $differential < 60) { $messages[$key] = sprintf(_("%s is due now."), $link); } elseif ($differential >= 60) { $messages[$key] = sprintf(_("%s is due in %s"), $link, Nag::secondsToString($differential)); } } ksort($messages); foreach ($messages as $message) { $html .= '<tr><td class="control">' . Horde::img('alarm_small.png') . ' <strong>' . $message . '</strong></td></tr>'; } if (!empty($messages)) { $html .= '</table><br /><table cellspacing="0" width="100%" class="linedRow">'; } } $i = 0; try { $tasks = Nag::listTasks(array('tasklists' => isset($this->_params['show_tasklists']) ? $this->_params['show_tasklists'] : array_keys(Nag::listTasklists(false, Horde_Perms::READ)), 'completed' => empty($this->_params['show_completed']) ? Nag::VIEW_INCOMPLETE : Nag::VIEW_ALL, 'include_history' => false)); } catch (Nag_Exception $e) { return '<em>' . htmlspecialchars($e->getMessage()) . '</em>'; } $tasks->reset(); while ($task = $tasks->each()) { $due = $task->due ? $task->getNextDue() : null; // Only print tasks due in the past if the show_overdue flag is on. if ($due && $due->before($_SERVER['REQUEST_TIME']) && empty($this->_params['show_overdue'])) { continue; } if ($task->completed) { $class = 'closed'; } elseif ($due && $due->before($_SERVER['REQUEST_TIME'])) { $class = 'overdue'; } else { $class = ''; } $style = ' style="background-color:' . $task->backgroundColor() . ';color:' . $task->foregroundColor() . '"'; $html .= '<tr class="' . $class . '">'; if (!empty($this->_params['show_actions'])) { $taskurl = Horde::url('task.php', true)->add(array('task' => $task->id, 'tasklist' => $task->tasklist, 'url' => Horde::selfUrl(true))); $label = sprintf(_("Edit \"%s\""), $task->name); $html .= '<td width="1%"' . $style . '>' . $taskurl->copy()->add('actionID', 'modify_task')->link() . Horde::img('edit-sidebar-' . substr($task->foregroundColor(), 1) . '.png', $label) . '</a></td>'; if ($task->completed) { $html .= '<td width="1%">' . $style . '' . Horde::img('checked.png', _("Completed")) . '</td>'; } else { $label = sprintf(_("Complete \"%s\""), $task->name); $html .= '<td width="1%"' . $style . '>' . Horde::url($conf['urls']['pretty'] == 'rewrite' ? 't/complete' : 'task/complete.php')->add(array('task' => $task->id, 'tasklist' => $task->tasklist, 'url' => Horde::selfUrl(true)))->link() . Horde::img('unchecked.png', $label) . '</a></td>'; } } if (!empty($this->_params['show_pri'])) { $html .= '<td align="center"' . $style . '> ' . Nag::formatPriority($task->priority) . ' </td>'; } if (!empty($this->_params['show_tasklist'])) { $html .= '<td width="1%" class="nowrap"' . $style . '>' . htmlspecialchars(Nag::getLabel($GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create()->getShare($task->tasklist))) . ' </td>'; } $html .= '<td' . $style . '>'; $viewurl = Horde::url('view.php', true)->add(array('task' => $task->id, 'tasklist' => $task->tasklist)); $html .= $task->treeIcons() . $viewurl->link(array('title' => $task->desc, 'style' => 'color:' . $task->foregroundColor())) . (!empty($task->name) ? htmlspecialchars($task->name) : _("[none]")) . '</a>'; if ($due && empty($task->completed) && !empty($this->_params['show_due'])) { $html .= ' (' . $due->strftime($prefs->getValue('date_format')) . ')'; } $html .= '</td>'; $html .= "</tr>\n"; } if (empty($html)) { return '<em>' . _("No tasks to display") . '</em>'; } return '<table cellspacing="0" width="100%" class="linedRow">' . $html . '</table>'; }
/** * Const'r * * @param Horde_Form_Variables $vars The form variables. * @param string $title The form title. * * @return Nag_Form_Task */ public function __construct($vars, $title = '') { global $injector, $nag_shares, $prefs, $registry; parent::__construct($vars, $title); $user = $registry->getAuth(); $tasklist_enums = array(); foreach (Nag::listTasklists(false, Horde_Perms::SHOW, false) as $tl_id => $tl) { if (!$tl->hasPermission($user, Horde_Perms::EDIT)) { continue; } $tasklist_enums[$tl_id] = Nag::getLabel($tl); } $tasklist = $vars->get('tasklist_id'); if (empty($tasklist)) { reset($tasklist_enums); $tasklist = key($tasklist_enums); } $priorities = array(1 => '1 ' . _("(highest)"), 2 => 2, 3 => 3, 4 => 4, 5 => '5 ' . _("(lowest)")); $this->addHidden('', 'mobile', 'boolean', false); $this->addHidden('', 'task_id', 'text', false); $this->addHidden('', 'old_tasklist', 'text', false); $this->addHidden('', 'url', 'text', false); $this->addHidden('', 'uid', 'text', false); $this->addHidden('', 'owner', 'text', false); $this->addHidden('', 'list', 'text', false); $this->addHidden('', 'tab_name', 'text', false); $this->setSection(self::SECTION_GENERAL, _("General")); $this->addVariable(_("Name"), 'name', 'text', true); if (!$prefs->isLocked('default_tasklist') && count($tasklist_enums) > 1) { $v = $this->addVariable(_("Task List"), 'tasklist_id', 'enum', true, false, false, array($tasklist_enums)); if (!$vars->get('mobile')) { $v->setAction(Horde_Form_Action::factory('reload')); } } if (!$vars->get('mobile')) { $tasks = Nag::listTasks(array('tasklists' => array($tasklist), 'complete' => Nag::VIEW_FUTURE_INCOMPLETE, 'include_history' => false)); $task_enums = array('' => _("No parent task")); $tasks->reset(); while ($task = $tasks->each()) { if ($vars->get('task_id') == $task->id) { continue; } $task_enums[htmlspecialchars($task->id)] = str_repeat(' ', $task->indent * 4) . htmlspecialchars($task->name); } $v = $this->addVariable(_("Parent task"), 'parent', 'enum', false, false, false, array($task_enums)); $v->setOption('htmlchars', true); } $this->addVariable(_("Tags"), 'tags', 'Nag:NagTags', false); // Only display the delete button if this is an existing task and the // user has HORDE_PERMS::DELETE $share = $nag_shares->getShare($tasklist); $delete = $share->hasPermission($registry->getAuth(), Horde_Perms::DELETE) && $vars->get('task_id'); if (!$vars->get('mobile')) { $users = $share->listUsers(Horde_Perms::READ); $groups = $share->listGroups(Horde_Perms::READ); if (count($groups)) { $horde_group = $injector->getInstance('Horde_Group'); foreach ($groups as $group) { $users = array_merge($users, $horde_group->listUsers($group)); } } if (empty($GLOBALS['conf']['assignees']['allow_external'])) { $users = array_flip($users); if (count($users)) { foreach (array_keys($users) as $user) { $identity = $injector->getInstance('Horde_Core_Factory_Identity')->create($user); $fullname = $identity->getValue('fullname'); $users[$user] = strlen($fullname) ? $fullname : $user; } } $this->addVariable(_("Assignee"), 'assignee', 'enum', false, false, null, array($users, _("None"))); } else { $this->addVariable(_("Assignee"), 'assignee', 'Nag:NagContact', false); } } $this->addVariable(_("Private?"), 'private', 'boolean', false); $this->addVariable(_("Due By"), 'due', 'Nag:NagDue', false); if (!$vars->get('mobile')) { $this->addVariable(_("Delay Start Until"), 'start', 'Nag:NagStart', false); } $this->addVariable(_("Alarm"), 'alarm', 'Nag:NagAlarm', false); if (!$vars->get('mobile')) { $v = $this->addVariable(_("Notification"), 'methods', 'Nag:NagMethod', false); $v->setAction(Horde_Form_Action::factory('reload')); $v = $this->addVariable(_("Priority"), 'priority', 'enum', false, false, false, array($priorities)); $v->setDefault(3); $this->addVariable(_("Estimated Time"), 'estimate', 'number', false); $this->addVariable(_("Actual Time"), 'actual', 'number', false); $this->_completedVar = $this->addVariable(_("Completed?"), 'completed', 'boolean', false); $this->setSection(self::SECTION_RECUR, _("Recurrence")); $this->addVariable(_("Recurrence"), 'recurrence', 'Nag:NagRecurrence', false); } $this->setSection(self::SECTION_DESC, _("Description")); try { $description = Horde::callHook('description_help', array(), 'nag'); } catch (Horde_Exception_HookNotSet $e) { $description = ''; } $this->addVariable(_("Description"), 'desc', 'longtext', false, false, $description); $buttons = array(array('value' => _("Save"))); if ($delete) { $buttons[] = array('value' => _("Delete"), 'name' => 'deletebutton', 'class' => 'horde-delete'); } if (!$vars->get('task_id')) { $buttons[] = array('value' => _("Save and New"), 'name' => 'savenewbutton', 'class' => 'horde-create'); } if (Horde_Util::getFormData('have_search')) { $buttons[] = array('value' => _("Return to Search Results"), 'name' => 'search_return', 'class' => 'horde-button'); } $this->setButtons($buttons); }
$sync[] = $default; $GLOBALS['prefs']->setValue('sync_lists', serialize($sync)); } }); // store the task lists to diplay $_prefs['display_tasklists'] = array('value' => 'a:0:{}'); // Tasklists use for synchronization $_prefs['sync_lists'] = array('value' => 'a:0:{}', 'type' => 'multienum', 'enum' => array(), 'desc' => _("Select the task lists that, in addition to the default, should be used for synchronization with external devices:"), 'on_init' => function ($ui) { $enum = array(); $sync = @unserialize($GLOBALS['prefs']->getValue('sync_lists')); if (empty($sync)) { $GLOBALS['prefs']->setValue('sync_lists', serialize(array(Nag::getDefaultTasklist(Horde_Perms::DELETE)))); } foreach (Nag::listTasklists(false, Horde_Perms::DELETE, false) as $key => $list) { if ($list->getName() != Nag::getDefaultTasklist(Horde_Perms::DELETE)) { $enum[$key] = Nag::getLabel($list); } } $ui->prefs['sync_lists']['enum'] = $enum; }, 'on_change' => function () { $sync = @unserialize($GLOBALS['prefs']->getValue('sync_lists')); $haveDefault = false; $default = Nag::getDefaultTasklist(Horde_Perms::DELETE); foreach ($sync as $cid) { if ($cid == $default) { $haveDefault = true; break; } } if (!$haveDefault) { $sync[] = $default;
/** * Sends email notifications that a task has been added, edited, or * deleted to users that want such notifications. * * @param string $action The event action. One of "add", "edit", or * "delete". * @param Nag_Task $task The changed task. * @param Nag_Task $old_task The original task if $action is "edit". * * @throws Nag_Exception */ public static function sendNotification($action, $task, $old_task = null) { if (!in_array($action, array('add', 'edit', 'delete'))) { throw new Nag_Exception('Unknown event action: ' . $action); } try { $share = $GLOBALS['nag_shares']->getShare($task->tasklist); } catch (Horde_Share_Exception $e) { Horde::log($e->getMessage(), 'ERR'); throw new Nag_Exception($e); } $groups = $GLOBALS['injector']->getInstance('Horde_Group'); $recipients = array(); $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create(); $from = $identity->getDefaultFromAddress(true); $owner = $share->get('owner'); if (strlen($owner)) { $recipients[$owner] = self::_notificationPref($owner, 'owner'); } foreach ($share->listUsers(Horde_Perms::READ) as $user) { if (empty($recipients[$user])) { $recipients[$user] = self::_notificationPref($user, 'read', $task->tasklist); } } foreach ($share->listGroups(Horde_Perms::READ) as $group) { try { $group_users = $groups->listUsers($group); } catch (Horde_Group_Exception $e) { Horde::log($e, 'ERR'); continue; } foreach ($group_users as $user) { if (empty($recipients[$user])) { $recipients[$user] = self::_notificationPref($user, 'read', $task->tasklist); } } } $addresses = array(); foreach ($recipients as $user => $vals) { if (!$vals) { continue; } $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($user); $email = $identity->getValue('from_addr'); if (strpos($email, '@') === false) { continue; } if (!isset($addresses[$vals['lang']][$vals['tf']][$vals['df']])) { $addresses[$vals['lang']][$vals['tf']][$vals['df']] = array(); } $tmp = new Horde_Mail_Rfc822_Address($email); $tmp->personal = $identity->getValue('fullname'); $addresses[$vals['lang']][$vals['tf']][$vals['df']][] = strval($tmp); } if (!$addresses) { return; } $mail = new Horde_Mime_Mail(array('User-Agent' => 'Nag ' . $GLOBALS['registry']->getVersion(), 'Precedence' => 'bulk', 'Auto-Submitted' => 'auto-generated', 'From' => $from)); foreach ($addresses as $lang => $twentyFour) { $GLOBALS['registry']->setLanguageEnvironment($lang); $view_link = Horde::url('view.php', true)->add(array('tasklist' => $task->tasklist, 'task' => $task->id))->setRaw(true); switch ($action) { case 'add': $subject = _("Task added:"); $notification_message = _("You requested to be notified when tasks are added to your task lists.") . "\n\n" . ($task->due ? _("The task \"%s\" has been added to task list \"%s\", with a due date of: %s.") : _("The task \"%s\" has been added to task list \"%s\".")) . "\n" . str_replace('%', '%%', $view_link); break; case 'edit': $subject = _("Task modified:"); $notification_message = _("You requested to be notified when tasks are edited on your task lists.") . "\n\n" . _("The task \"%s\" has been edited on task list \"%s\".") . "\n" . str_replace('%', '%%', $view_link) . "\n\n" . _("Changes made for this task:"); if ($old_task->name != $task->name) { $notification_message .= "\n - " . sprintf(_("Changed name from \"%s\" to \"%s\""), $old_task->name, $task->name); } if ($old_task->tasklist != $task->tasklist) { $old_share = $GLOBALS['nag_shares']->getShare($old_task->tasklist); $notification_message .= "\n - " . sprintf(_("Changed task list from \"%s\" to \"%s\""), Nag::getLabel($old_share), Nag::getLabel($share)); } if ($old_task->parent_id != $task->parent_id) { $old_parent = $old_task->getParent(); try { $parent = $task->getParent(); $notification_message .= "\n - " . sprintf(_("Changed parent task from \"%s\" to \"%s\""), $old_parent ? $old_parent->name : _("no parent"), $parent ? $parent->name : _("no parent")); } catch (Nag_Exception $e) { } } if ($old_task->assignee != $task->assignee) { $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($old_task->assignee); $old_name = $identity->getValue('fullname'); if (!strlen($old_name)) { $old_name = $old_task->assignee; } $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($task->assignee); $new_name = $identity->getValue('fullname'); if (!strlen($new_name)) { $new_name = $new_task->assignee; } $notification_message .= "\n - " . sprintf(_("Changed assignee from \"%s\" to \"%s\""), $old_name, $new_name); } if ($old_task->private != $task->private) { $notification_message .= "\n - " . ($task->private ? _("Turned privacy on") : _("Turned privacy off")); } if ($old_task->due != $task->due) { $notification_message .= "\n - " . sprintf(_("Changed due date from %s to %s"), $old_task->due ? self::formatDate($old_task->due) : _("no due date"), $task->due ? self::formatDate($task->due) : _("no due date")); } if ($old_task->start != $task->start) { $notification_message .= "\n - " . sprintf(_("Changed start date from %s to %s"), $old_task->start ? self::formatDate($old_task->start) : _("no start date"), $task->start ? self::formatDate($task->start) : _("no start date")); } if ($old_task->alarm != $task->alarm) { $notification_message .= "\n - " . sprintf(_("Changed alarm from %s to %s"), self::formatAlarm($old_task->alarm), self::formatAlarm($task->alarm)); } if ($old_task->priority != $task->priority) { $notification_message .= "\n - " . sprintf(_("Changed priority from %s to %s"), $old_task->priority, $task->priority); } if ($old_task->estimate != $task->estimate) { $notification_message .= "\n - " . sprintf(_("Changed estimate from %s to %s"), $old_task->estimate, $task->estimate); } if ($old_task->completed != $task->completed) { $notification_message .= "\n - " . sprintf(_("Changed completion from %s to %s"), $old_task->completed ? _("completed") : _("not completed"), $task->completed ? _("completed") : _("not completed")); } if ($old_task->desc != $task->desc) { $notification_message .= "\n - " . _("Changed description"); } break; case 'delete': $subject = _("Task deleted:"); $notification_message = _("You requested to be notified when tasks are deleted from your task lists.") . "\n\n" . _("The task \"%s\" has been deleted from task list \"%s\"."); break; } $mail->addHeader('Subject', $subject . ' ' . $task->name); foreach ($twentyFour as $tf => $dateFormat) { foreach ($dateFormat as $df => $df_recipients) { $message = sprintf($notification_message, $task->name, Nag::getLabel($share), $task->due ? strftime($df, $task->due) . ' ' . date($tf ? 'H:i' : 'h:ia', $task->due) : ''); if (strlen(trim($task->desc))) { $message .= "\n\n" . _("Task description:") . "\n\n" . $task->desc; } $mail->setBody($message); $mail->clearRecipients(); $mail->addRecipients($df_recipients); Horde::log(sprintf('Sending event notifications for %s to %s', $task->name, implode(', ', $df_recipients)), 'INFO'); $mail->send($GLOBALS['injector']->getInstance('Horde_Mail')); } } } }
/** */ public function davGetCollections($user) { global $injector, $nag_shares, $registry; $hordeUser = $registry->convertUsername($user, true); $shares = $nag_shares->listShares($hordeUser); $dav = $injector->getInstance('Horde_Dav_Storage'); $tasklists = array(); foreach ($shares as $id => $share) { if ($user == '-system-' && $share->get('owner')) { continue; } try { $id = $dav->getExternalCollectionId($id, 'tasks') ?: $id; } catch (Horde_Dav_Exception $e) { } $tasklists[] = array('id' => $id, 'uri' => $id, '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}shared-url' => Nag::getUrl(Nag::DAV_CALDAV, $share), 'principaluri' => 'principals/' . $user, '{http://sabredav.org/ns}owner-principal' => 'principals/' . ($share->get('owner') ? $registry->convertUsername($share->get('owner'), false) : '-system-'), '{DAV:}displayname' => Nag::getLabel($share), '{urn:ietf:params:xml:ns:caldav}calendar-description' => $share->get('desc'), '{http://apple.com/ns/ical/}calendar-color' => $share->get('color'), '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Sabre\CalDAV\Property\SupportedCalendarComponentSet(array('VTODO')), '{http://sabredav.org/ns}read-only' => !$share->hasPermission($hordeUser, Horde_Perms::EDIT)); } return $tasklists; }
public function listTimeObjectCategories() { $categories = array(); $tasklists = Nag::listTasklists(false, Horde_Perms::SHOW | Horde_Perms::READ); foreach ($tasklists as $tasklistId => $tasklist) { $categories[$tasklistId] = array('title' => Nag::getLabel($tasklist), 'type' => 'share'); } return $categories; }
/** * Convert this tasklist to a hash. * * @return array A hash of tasklist properties. */ public function toHash() { $tasks = Nag::listTasks(array('tasklists' => $this->_share->getName(), 'include_history' => false)); $hash = array('name' => Nag::getLabel($this->_share), 'desc' => $this->_share->get('desc'), 'color' => $this->_share->get('color'), 'owner' => $this->_share->get('owner'), 'id' => $this->_share->getName(), 'count' => $tasks->count(), 'smart' => $this->_share->get('issmart') ? true : false, 'overdue' => $tasks->childrenOverdue()); return $hash; }
while ($task = $this->tasks->each()) { $due = $task->due ? $task->getNextDue() : null; if (!empty($task->completed)) { $style = 'linedRow closed'; } elseif ($due && $due->before($_SERVER['REQUEST_TIME'])) { $style = 'linedRow overdue'; } else { $style = ''; } if ($task->tasklist == '**EXTERNAL**') { $share = $GLOBALS['nag_shares']->newShare($GLOBALS['registry']->getAuth(), '**EXTERNAL**', $task->tasklist_name); $owner = $task->tasklist_name; } else { try { $share = $GLOBALS['nag_shares']->getShare($task->tasklist); $owner = Nag::getLabel($share); } catch (Horde_Share_Exception $e) { $owner = $task->tasklist; } } $locals = array('style' => $style, 'have_read' => $share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::READ), 'have_edit' => $share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT), 'owner' => $owner, 'task' => $task, 'due' => $due, 'columns' => $this->columns, 'dynamic_sort' => $this->dynamic_sort &= !$task->hasSubTasks(), 'dateFormat' => $GLOBALS['prefs']->getValue('date_format')); ?> <?php echo $this->renderPartial('list/task', array('locals' => $locals)); ?> <?php } ?> </tbody> </table> <?php
/** * Return tasklists the current user has PERMS_EDIT on. * See Bug: 13837. * * @return array A hash of tasklist objects. */ protected function _getTasklists() { $tasklist_enums = array(); $user = $GLOBALS['registry']->getAuth(); foreach (Nag::listTasklists(false, Horde_Perms::SHOW, false) as $tl_id => $tl) { if (!$tl->hasPermission($user, Horde_Perms::EDIT)) { continue; } $tasklist_enums[$tl_id] = Nag::getLabel($tl); } return $tasklist_enums; }