1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14:
15: if (!defined('NAG_BASE')) {
16: define('NAG_BASE', dirname(__FILE__) . '/..');
17: }
18:
19: if (!defined('HORDE_BASE')) {
20: 21:
22: if (file_exists(NAG_BASE . '/config/horde.local.php')) {
23: include NAG_BASE . '/config/horde.local.php';
24: } else {
25: define('HORDE_BASE', NAG_BASE . '/..');
26: }
27: }
28:
29: 30:
31: require_once HORDE_BASE . '/lib/core.php';
32:
33: class Nag_Application extends Horde_Registry_Application
34: {
35: 36:
37: public $version = 'H4 (3.0.10-git)';
38:
39: 40:
41: public $mobileView = true;
42:
43: 44: 45: 46:
47: protected function _init()
48: {
49:
50: $GLOBALS['registry']->setTimeZone();
51:
52:
53: $GLOBALS['nag_shares'] = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create();
54:
55: Nag::initialize();
56: }
57:
58: 59:
60: public function perms()
61: {
62: return array(
63: 'max_tasks' => array(
64: 'title' => _("Maximum Number of Tasks"),
65: 'type' => 'int'
66: )
67: );
68: }
69:
70: 71:
72: public function ($menu)
73: {
74: global $conf, $injector;
75:
76: $menu->add(Horde::url('list.php'), _("_List Tasks"), 'nag.png', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
77:
78: if (Nag::getDefaultTasklist(Horde_Perms::EDIT) &&
79: ($injector->getInstance('Horde_Core_Perms')->hasAppPermission('max_tasks') === true ||
80: $injector->getInstance('Horde_Core_Perms')->hasAppPermission('max_tasks') > Nag::countTasks())) {
81: $menu->add(Horde::url('task.php')->add('actionID', 'add_task'), _("_New Task"), 'add.png', null, null, null, Horde_Util::getFormData('task') ? '__noselection' : null);
82: if ($GLOBALS['browser']->hasFeature('dom')) {
83: Horde::addScriptFile('effects.js', 'horde');
84: Horde::addScriptFile('redbox.js', 'horde');
85: $menu->add(new Horde_Url(''), _("_Quick Add"), 'add.png', null, null, 'RedBox.showInline(\'quickAddInfoPanel\'); $(\'quickText\').focus(); return false;', Horde_Util::getFormData('task') ? 'quickAdd __noselection' : 'quickAdd');
86: }
87: }
88:
89:
90: $menu->add(Horde::url('search.php'), _("_Search"), 'search.png');
91:
92:
93: if ($conf['menu']['import_export']) {
94: $menu->add(Horde::url('data.php'), _("_Import/Export"), 'data.png');
95: }
96: }
97:
98: 99:
100: public function hasPermission($permission, $allowed, $opts = array())
101: {
102: if (is_array($allowed)) {
103: switch ($permission) {
104: case 'max_tasks':
105: $allowed = max($allowed);
106: break;
107: }
108: }
109: return $allowed;
110: }
111:
112: public function prefsInit($ui)
113: {
114: global $registry;
115: if ($registry->hasMethod('getListTypes', 'whups')) {
116: $ui->override['show_external'] = array(
117: 'whups' => $registry->get('name', 'whups')
118: );
119: } else {
120: $ui->suppress[] = 'show_external';
121: }
122: }
123:
124: 125:
126: public function prefsGroup($ui)
127: {
128: global $conf, $prefs, $registry;
129:
130: foreach ($ui->getChangeablePrefs() as $val) {
131: switch ($val) {
132: case 'default_due_time':
133: $twentyfour = $prefs->getValue('twentyFour');
134:
135: $vals = array('now' => _("The current hour"));
136: for ($i = 0; $i < 24; ++$i) {
137: $value = sprintf('%02d:00', $i);
138: $vals[$value] = ($twentyfour)
139: ? $value
140: : sprintf('%02d:00 ' . ($i >= 12 ? _("pm") : _("am")), ($i % 12 ? $i % 12 : 12));
141: }
142: $ui->override['default_due_time'] = $vals;
143: break;
144:
145: case 'default_tasklist':
146: $vals = array();
147: foreach (Nag::listTasklists() as $id => $tasklist) {
148: $vals[htmlspecialchars($id)] = htmlspecialchars($tasklist->get('name'));
149: }
150: $ui->override['default_tasklist'] = $vals;
151: break;
152:
153: case 'sync_lists':
154: $sync = @unserialize($prefs->getValue('sync_lists'));
155: if (empty($sync)) {
156: $prefs->setValue('sync_lists', serialize(array(Nag::getDefaultTasklist())));
157: }
158: $out = array();
159: foreach (Nag::listTasklists(false, Horde_Perms::EDIT) as $key => $list) {
160: if ($list->getName() != Nag::getDefaultTasklist(Horde_Perms::EDIT)) {
161: $out[$key] = $list->get('name');
162: }
163: }
164: $ui->override['sync_lists'] = $out;
165: break;
166:
167: case 'show_external':
168: if ($registry->hasMethod('getListTypes', 'whups')) {
169: $ui->override['show_external'] = array(
170: 'whups' => $registry->get('name', 'whups')
171: );
172: } else {
173: $ui->suppress[] = 'show_external';
174: }
175: break;
176:
177: case 'task_alarms_select':
178: if (empty($conf['alarms']['driver']) ||
179: $prefs->isLocked('task_alarms_select')) {
180: $ui->suppress[] = 'task_alarms';
181: } else {
182: Horde_Core_Prefs_Ui_Widgets::alarmInit();
183: }
184: break;
185: }
186: }
187: }
188:
189: 190:
191: public function prefsSpecial($ui, $item)
192: {
193: switch ($item) {
194: case 'task_alarms_select':
195: return Horde_Core_Prefs_Ui_Widgets::alarm(array(
196: 'label' => _("Choose how you want to receive reminders for tasks with alarms:"),
197: 'pref' => 'task_alarms'
198: ));
199: }
200:
201: return '';
202: }
203:
204: 205:
206: public function prefsSpecialUpdate($ui, $item)
207: {
208: switch ($item) {
209: case 'task_alarms_select':
210: $data = Horde_Core_Prefs_Ui_Widgets::alarmUpdate($ui, array('pref' => 'task_alarms'));
211: if (!is_null($data)) {
212: $GLOBALS['prefs']->setValue('task_alarms', serialize($data));
213: return true;
214: }
215: break;
216: }
217:
218: return false;
219: }
220:
221: 222:
223: public function prefsCallback($ui)
224: {
225:
226: if ($GLOBALS['prefs']->isDirty('sync_lists') || $GLOBALS['prefs']->isDirty('default_tasklist')) {
227: $sync = @unserialize($GLOBALS['prefs']->getValue('sync_lists'));
228: $haveDefault = false;
229: $default = Nag::getDefaultTasklist(Horde_Perms::EDIT);
230: foreach ($sync as $cid) {
231: if ($cid == $default) {
232: $haveDefault = true;
233: break;
234: }
235: }
236: if (!$haveDefault) {
237: $sync[] = $default;
238: $GLOBALS['prefs']->setValue('sync_lists', serialize($sync));
239: }
240: }
241:
242: if ($GLOBALS['conf']['activesync']['enabled'] && $GLOBALS['prefs']->isDirty('sync_lists')) {
243: try {
244: $stateMachine = $GLOBALS['injector']->getInstance('Horde_ActiveSyncState');
245: $stateMachine->setLogger($GLOBALS['injector']->getInstance('Horde_Log_Logger'));
246: $devices = $stateMachine->listDevices($GLOBALS['registry']->getAuth());
247: foreach ($devices as $device) {
248: $stateMachine->removeState(null, $device['device_id'], $GLOBALS['registry']->getAuth());
249: }
250: $GLOBALS['notification']->push(_("All state removed for your ActiveSync devices. They will resynchronize next time they connect to the server."));
251: } catch (Horde_ActiveSync_Exception $e) {
252: $GLOBALS['notification']->push(_("There was an error communicating with the ActiveSync server: %s"), $e->getMessage(), 'horde.err');
253: }
254: }
255: }
256:
257: 258:
259: public function removeUserData($user)
260: {
261:
262: try {
263: $shares = $GLOBALS['nag_shares']->listShares($user, array('attributes' => $user));
264: } catch (Horde_Share_Exception $e) {
265: Horde::logMessage($e, 'ERR');
266: throw new Nag_Exception($e);
267: }
268:
269: $error = false;
270: foreach ($shares as $share) {
271: $storage = Nag_Driver::singleton($share->getName());
272: $result = $storage->deleteAll();
273: try {
274: $GLOBALS['nag_shares']->removeShare($share);
275: } catch (Horde_Share_Exception $e) {
276: Horde::logMessage($e, 'NOTICE');
277: $error = true;
278: }
279: }
280:
281:
282: try {
283: $shares = $GLOBALS['nag_shares']->listShares($user);
284: foreach ($shares as $share) {
285: $share->removeUser($user);
286: }
287: } catch (Horde_Share_Exception $e) {
288: Horde::logMessage($e, 'NOTICE');
289: $error = true;
290: }
291:
292: if ($error) {
293: throw new Nag_Exception(sprintf(_("There was an error removing tasks for %s. Details have been logged."), $user));
294: }
295: }
296:
297:
298:
299: 300:
301: public function listAlarms($time, $user = null)
302: {
303: if ((empty($user) || $user != $GLOBALS['registry']->getAuth()) &&
304: !$GLOBALS['registry']->isAdmin()) {
305:
306: throw new Horde_Exception_PermissionDenied(_("Permission Denied"));
307: }
308:
309: $storage = Nag_Driver::singleton();
310: $group = $GLOBALS['injector']->getInstance('Horde_Group');
311: $alarm_list = array();
312: $tasklists = is_null($user) ?
313: array_keys($GLOBALS['nag_shares']->listAllShares()) :
314: $GLOBALS['display_tasklists'];
315:
316: $alarms = Nag::listAlarms($time, $tasklists);
317: foreach ($alarms as $alarm) {
318: try {
319: $share = $GLOBALS['nag_shares']->getShare($alarm->tasklist);
320: } catch (Horde_Share_Exception $e) {
321: continue;
322: }
323: if (empty($user)) {
324: $users = $share->listUsers(Horde_Perms::READ);
325: $groups = $share->listGroups(Horde_Perms::READ);
326: foreach ($groups as $gid) {
327: $users = array_merge($users, $group->listUsers($gid));
328: }
329: $users = array_unique($users);
330: } else {
331: $users = array($user);
332: }
333: foreach ($users as $alarm_user) {
334: $prefs = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Prefs')->create('nag', array(
335: 'cache' => false,
336: 'user' => $alarm_user
337: ));
338: $GLOBALS['registry']->setLanguageEnvironment($prefs->getValue('language'));
339: $alarm_list[] = $alarm->toAlarm($alarm_user, $prefs);
340: }
341: }
342:
343: return $alarm_list;
344: }
345:
346:
347:
348:
349: 350:
351: public function (Horde_Tree_Base $tree, $parent = null,
352: array $params = array())
353: {
354: global $registry;
355:
356: switch ($params['id']) {
357: case 'alarms':
358:
359: $now = time();
360: $alarms = Nag::listAlarms($now);
361: $alarmCount = 0;
362: $horde_alarm = $GLOBALS['injector']->getInstance('Horde_Alarm');
363: foreach ($alarms as $taskId => $task) {
364: if ($horde_alarm->isSnoozed($task->uid, $registry->getAuth())) {
365: continue;
366: }
367: ++$alarmCount;
368:
369: $differential = $task->due - $now;
370: $title = ($differential >= 60)
371: ? sprintf(_("%s is due in %s"), $task->name, Nag::secondsToString($differential))
372: : sprintf(_("%s is due now."), $task->name);
373: $url = Horde::url('view.php')->add(array(
374: 'task' => $task->id,
375: 'tasklist' => $task->tasklist
376: ));
377:
378: $tree->addNode(
379: $parent . $taskId,
380: $parent,
381: $task->name,
382: 1,
383: false,
384: array(
385: 'icon' => Horde_Themes::img('alarm.png'),
386: 'title' => $title,
387: 'url' => $url
388: )
389: );
390: }
391:
392: if ($registry->get('url', $parent)) {
393: $purl = $registry->get('url', $parent);
394: } elseif ($registry->get('status', $parent) == 'heading' ||
395: !$registry->get('webroot')) {
396: $purl = null;
397: } else {
398: $purl = Horde::url($registry->getInitialPage($parent));
399: }
400:
401: $pnode_name = $registry->get('name', $parent);
402: if ($alarmCount) {
403: $pnode_name = '<strong>' . $pnode_name . '</strong>';
404: }
405:
406: $tree->addNode(
407: $parent,
408: $registry->get('menu_parent', $parent),
409: $pnode_name,
410: 0,
411: false,
412: array(
413: 'icon' => strval($registry->get('icon', $parent)),
414: 'url' => $purl
415: )
416: );
417: break;
418:
419: case 'menu':
420: $add = Horde::url('task.php')->add('actionID', 'add_task');
421:
422: $tree->addNode(
423: $parent . '__new',
424: $parent,
425: _("New Task"),
426: 1,
427: false,
428: array(
429: 'icon' => Horde_Themes::img('add.png'),
430: 'url' => $add
431: )
432: );
433:
434: foreach (Nag::listTasklists() as $name => $tasklist) {
435: $tree->addNode(
436: $parent . $name . '__new',
437: $parent . '__new',
438: sprintf(_("in %s"), $tasklist->get('name')),
439: 2,
440: false,
441: array(
442: 'icon' => Horde_Themes::img('add.png'),
443: 'url' => $add->copy()->add('tasklist_id', $name)
444: )
445: );
446: }
447:
448: $tree->addNode(
449: $parent . '__search',
450: $parent,
451: _("Search"),
452: 1,
453: false,
454: array(
455: 'icon' => Horde_Themes::img('search.png'),
456: 'url' => Horde::url('search.php')
457: )
458: );
459: break;
460: }
461: }
462:
463: }
464: