Overview

Packages

  • Mnemo
  • None

Classes

  • Mnemo
  • Mnemo_Ajax_Application
  • Mnemo_Ajax_Imple_EditNote
  • Mnemo_Api
  • Mnemo_Driver
  • Mnemo_Driver_Kolab
  • Mnemo_Driver_Sql
  • Mnemo_Exception
  • Mnemo_Factory_Driver
  • Mnemo_Factory_Notepads
  • Mnemo_Form_CreateNotepad
  • Mnemo_Form_DeleteNotepad
  • Mnemo_Form_EditNotepad
  • Mnemo_Notepads_Base
  • Mnemo_Notepads_Default
  • Mnemo_Notepads_Kolab
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Copyright 2001-2012 Horde LLC (http://www.horde.org/)
  4:  *
  5:  * See the enclosed file LICENSE for license information (ASL). If you
  6:  * did not receive this file, see http://www.horde.org/licenses/apache.
  7:  *
  8:  * @package Mnemo
  9:  */
 10: /**
 11:  * Mnemo Base Class.
 12:  *
 13:  * @author  Jon Parise <jon@horde.org>
 14:  * @package Mnemo
 15:  */
 16: class Mnemo
 17: {
 18:     /**
 19:      * Sort by memo description.
 20:      */
 21:     const SORT_DESC = 0;
 22: 
 23:     /**
 24:      * Sort by memo category.
 25:      */
 26:     const SORT_CATEGORY = 1;
 27: 
 28:     /**
 29:      * Sort by notepad.
 30:      */
 31:     const SORT_NOTEPAD = 2;
 32: 
 33:     /**
 34:      * Sort by moddate
 35:      */
 36:     const SORT_MOD_DATE = 3;
 37: 
 38:     /**
 39:      * Sort in ascending order.
 40:      */
 41:     const SORT_ASCEND = 0;
 42: 
 43:     /**
 44:      * Sort in descending order.
 45:      */
 46:     const SORT_DESCEND = 1;
 47: 
 48:     /**
 49:      * No passphrase provided.
 50:      */
 51:     const ERR_NO_PASSPHRASE = 100;
 52: 
 53:     /**
 54:      * Decrypting failed
 55:      */
 56:     const ERR_DECRYPT = 101;
 57: 
 58:     /**
 59:      * Retrieves the current user's note list from storage. This function will
 60:      * also sort the resulting list, if requested.
 61:      *
 62:      * @param constant $sortby   The field by which to sort. (self::SORT_DESC,
 63:      *                           self::SORT_CATEGORY, self::SORT_NOTEPAD,
 64:      *                           self::SORT_MOD_DATE)
 65:      * @param constant $sortdir  The direction by which to sort.
 66:      *                           (self::SORT_ASC, self::SORT_DESC)
 67:      *
 68:      * @return array  A list of the requested notes.
 69:      *
 70:      * @see Mnemo_Driver::listMemos()
 71:      */
 72:     public static function listMemos($sortby = self::SORT_DESC,
 73:                                      $sortdir = self::SORT_ASCEND)
 74:     {
 75:         global $conf, $display_notepads;
 76:         $memos = array();
 77: 
 78:         /* Sort the memo list. */
 79:         $sort_functions = array(
 80:             self::SORT_DESC => 'ByDesc',
 81:             self::SORT_CATEGORY => 'ByCategory',
 82:             self::SORT_NOTEPAD => 'ByNotepad',
 83:             self::SORT_MOD_DATE => 'ByModDate'
 84:         );
 85: 
 86:         foreach ($display_notepads as $notepad) {
 87:             $storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
 88:             try {
 89:                 $storage->retrieve();
 90:             } catch (Mnemo_Exception $e) {
 91:                 $GLOBALS['notification']->push($e, 'horde.error');
 92:             }
 93:             $newmemos = $storage->listMemos();
 94:             $memos = array_merge($memos, $newmemos);
 95:         }
 96: 
 97:         // Sort the array if we have a sort function defined
 98:         if (isset($sort_functions[$sortby])) {
 99:             $prefix = ($sortdir == self::SORT_DESCEND) ? '_rsort' : '_sort';
100:             uasort($memos, array('Mnemo', $prefix . $sort_functions[$sortby]));
101:         }
102: 
103:         return $memos;
104:     }
105: 
106:     /**
107:      * Returns the number of notes in notepads that the current user owns.
108:      *
109:      * @return integer  The number of notes that the user owns.
110:      */
111:     public static function countMemos()
112:     {
113:         static $count;
114:         if (isset($count)) {
115:             return $count;
116:         }
117: 
118:         $notepads = self::listNotepads(true, Horde_Perms::ALL);
119:         $count = 0;
120:         foreach (array_keys($notepads) as $notepad) {
121:             $storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
122:             $storage->retrieve();
123:             $count += count($storage->listMemos());
124:         }
125: 
126:         return $count;
127:     }
128: 
129:     /**
130:      * Retrieves a specific note from storage.
131:      *
132:      * @param string $notepad     The notepad to retrieve the note from.
133:      * @param string $noteId      The Id of the note to retrieve.
134:      * @param string $passphrase  A passphrase with which this note was
135:      *                            supposed to be encrypted.
136:      *
137:      * @return array  The note.
138:      */
139:     public static function getMemo($notepad, $noteId, $passphrase = null)
140:     {
141:         $storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
142:         return $storage->get($noteId, $passphrase);
143:     }
144: 
145:     /**
146:      * Get preview text for a note (the first 20 lines or so).
147:      *
148:      * @param array $note The note array
149:      *
150:      * @return string A few lines of the note for previews or tooltips.
151:      */
152:     public static function getNotePreview($note)
153:     {
154:         $body = $note['body'];
155:         if ($body instanceof Mnemo_Exception) {
156:             $body = $body->getMessage();
157:         }
158:         $lines = explode("\n", wordwrap($body));
159:         return implode("\n", array_splice($lines, 0, 20));
160:     }
161: 
162:     /**
163:      * Lists all notepads a user has access to.
164:      *
165:      * This method takes the $conf['share']['hidden'] setting into account. If
166:      * this setting is enabled, even if requesting permissions different than
167:      * SHOW, it will only return calendars that the user owns or has SHOW
168:      * permissions for. For checking individual calendar's permissions, use
169:      * hasPermission() instead.
170:      *
171:      * @param boolean $owneronly   Only return memo lists that this user owns?
172:      *                             Defaults to false.
173:      * @param integer $permission  The permission to filter notepads by.
174:      *
175:      * @return array  The memo lists.
176:      */
177:     public static function listNotepads($owneronly = false,
178:                                         $permission = Horde_Perms::SHOW)
179:     {
180:         if ($owneronly && !$GLOBALS['registry']->getAuth()) {
181:             return array();
182:         }
183:         if ($owneronly || empty($GLOBALS['conf']['share']['hidden'])) {
184:             try {
185:                 $notepads = $GLOBALS['mnemo_shares']->listShares(
186:                     $GLOBALS['registry']->getAuth(),
187:                     array('perm' => $permission,
188:                           'attributes' => $owneronly ? $GLOBALS['registry']->getAuth() : null,
189:                           'sort_by' => 'name'));
190:             } catch (Horde_Share_Exception $e) {
191:                 Horde::logMessage($e->getMessage(), 'ERR');
192:                 return array();
193:             }
194:         } else {
195:             try {
196:                 $notepads = $GLOBALS['mnemo_shares']->listShares(
197:                     $GLOBALS['registry']->getAuth(),
198:                     array('perm' => $permission,
199:                           'attributes' => $GLOBALS['registry']->getAuth(),
200:                           'sort_by' => 'name'));
201:             } catch (Horde_Share_Exception $e) {
202:                 Horde::logMessage($e);
203:                 return array();
204:             }
205:             $display_notepads = @unserialize($GLOBALS['prefs']->getValue('display_notepads'));
206:             if (is_array($display_notepads)) {
207:                 foreach ($display_notepads as $id) {
208:                     try {
209:                         $notepad = $GLOBALS['mnemo_shares']->getShare($id);
210:                         if ($notepad->hasPermission($GLOBALS['registry']->getAuth(), $permission)) {
211:                             $notepads[$id] = $notepad;
212:                         }
213:                     } catch (Horde_Exception_NotFound $e) {
214:                     } catch (Horde_Share_Exception $e) {
215:                         Horde::logMessage($e);
216:                         return array();
217:                     }
218:                 }
219:             }
220:         }
221: 
222:         return $notepads;
223:     }
224: 
225:     /**
226:      * Returns the default notepad for the current user at the specified
227:      * permissions level.
228:      *
229:      * @return mixed  The notepad identifier, or false if none found
230:      */
231:     public static function getDefaultNotepad($permission = Horde_Perms::SHOW)
232:     {
233:         global $prefs;
234: 
235:         $default_notepad = $prefs->getValue('default_notepad');
236:         $notepads = self::listNotepads(false, $permission);
237: 
238:         if (isset($notepads[$default_notepad])) {
239:             return $default_notepad;
240:         } elseif ($prefs->isLocked('default_notepad')) {
241:             return $GLOBALS['registry']->getAuth();
242:         } elseif (count($notepads)) {
243:             reset($notepads);
244:             return key($notepads);
245:         }
246: 
247:         return false;
248:     }
249: 
250:     /**
251:      * Returns the real name, if available, of a user.
252:      *
253:      * @return string  The real name
254:      */
255:     public static function getUserName($uid)
256:     {
257:         static $names = array();
258: 
259:         if (!isset($names[$uid])) {
260:             $ident = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($uid);
261:             $ident->setDefault($ident->getDefault());
262:             $names[$uid] = $ident->getValue('fullname');
263:             if (empty($names[$uid])) {
264:                 $names[$uid] = $uid;
265:             }
266:         }
267: 
268:         return $names[$uid];
269:     }
270: 
271:     /**
272:      * Comparison function for sorting notes by description.
273:      *
274:      * @param array $a  Note one.
275:      * @param array $b  Note two.
276:      *
277:      * @return integer  1 if memo one is greater, -1 if memo two is greater; 0
278:      *                  if they are equal.
279:      */
280:     protected static function _sortByDesc($a, $b)
281:     {
282:         return strcoll($a['desc'], $b['desc']);
283:     }
284: 
285:     /**
286:      * Comparison function for reverse sorting notes by description.
287:      *
288:      * @param array $a  Note one.
289:      * @param array $b  Note two.
290:      *
291:      * @return integer  -1 if note one is greater, 1 if note two is greater; 0
292:      *                  if they are equal.
293:      */
294:     protected static function _rsortByDesc($a, $b)
295:     {
296:         return strcoll($b['desc'], $a['desc']);
297:     }
298: 
299:     /**
300:      * Comparison function for sorting notes by category.
301:      *
302:      * @param array $a  Note one.
303:      * @param array $b  Note two.
304:      *
305:      * @return integer  1 if note one is greater, -1 if note two is greater; 0
306:      *                  if they are equal.
307:      */
308:     protected static function _sortByCategory($a, $b)
309:     {
310:         return strcoll($a['category'] ? $a['category'] : _("Unfiled"),
311:                        $b['category'] ? $b['category'] : _("Unfiled"));
312:     }
313: 
314:     /**
315:      * Comparison function for reverse sorting notes by category.
316:      *
317:      * @param array $a  Note one.
318:      * @param array $b  Note two.
319:      *
320:      * @return integer  -1 if note one is greater, 1 if note two is greater; 0
321:      *                  if they are equal.
322:      */
323:     protected static function _rsortByCategory($a, $b)
324:     {
325:         return strcoll($b['category'] ? $b['category'] : _("Unfiled"),
326:                        $a['category'] ? $a['category'] : _("Unfiled"));
327:     }
328: 
329:     /**
330:      * Comparison function for sorting notes by notepad name.
331:      *
332:      * @param array $a  Note one.
333:      * @param array $b  Note two.
334:      *
335:      * @return integer  1 if note one is greater, -1 if note two is greater;
336:      *                  0 if they are equal.
337:      */
338:     protected static function _sortByNotepad($a, $b)
339:     {
340:         $aowner = $a['memolist_id'];
341:         $bowner = $b['memolist_id'];
342: 
343:         $ashare = $GLOBALS['mnemo_shares']->getShare($aowner);
344:         $bshare = $GLOBALS['mnemo_shares']->getShare($bowner);
345: 
346:         if ($aowner != $ashare->get('owner')) {
347:             $aowner = $ashare->get('name');
348:         }
349:         if ($bowner != $bshare->get('owner')) {
350:             $bowner = $bshare->get('name');
351:         }
352: 
353:         return strcoll($aowner, $bowner);
354:     }
355: 
356:     /**
357:      * Comparison function for reverse sorting notes by notepad name.
358:      *
359:      * @param array $a  Note one.
360:      * @param array $b  Note two.
361:      *
362:      * @return integer  -1 if note one is greater, 1 if note two is greater;
363:      *                  0 if they are equal.
364:      */
365:     protected static function _rsortByNotepad($a, $b)
366:     {
367:         $aowner = $a['memolist_id'];
368:         $bowner = $b['memolist_id'];
369: 
370:         $ashare = $GLOBALS['mnemo_shares']->getShare($aowner);
371:         $bshare = $GLOBALS['mnemo_shares']->getShare($bowner);
372: 
373:         if ($aowner != $ashare->get('owner')) {
374:             $aowner = $ashare->get('name');
375:         }
376:         if ($bowner != $bshare->get('owner')) {
377:             $bowner = $bshare->get('name');
378:         }
379: 
380:         return strcoll($bowner, $aowner);
381:     }
382: 
383:     /**
384:      * Comparison function for sorting notes by modification date.
385:      *
386:      * @param array $a  Note one.
387:      * @param array $b  Note two.
388:      *
389:      * @return integer  1 if note one is greater, -1 if note two is greater;
390:      *                  0 if they are equal.
391:      */
392:     protected static function _sortByModDate($a, $b)
393:     {
394:         // Get notes` history
395:         $history = $GLOBALS['injector']->getInstance('Horde_History');
396: 
397:         $guidA = 'mnemo:' . $a['memolist_id'] . ':' . $a['uid'];
398:         $guidB = 'mnemo:' . $b['memolist_id'] . ':' . $b['uid'];
399: 
400:         // Gets the timestamp of the most recent modification to the note
401:         $modDateA = $history->getActionTimestamp($guidA, 'modify');
402:         $modDateB = $history->getActionTimestamp($guidB, 'modify');
403: 
404:         // If the note hasn't been modified, get the creation timestamp
405:         if ($modDateA == 0) {
406:             $modDateA = $history->getActionTimestamp($guidA, 'add');
407:         }
408:         if ($modDateB == 0) {
409:             $modDateB = $history->getActionTimestamp($guidB, 'add');
410:         }
411:         if ($modDateA == $modDateB) {
412:             return 0;
413:         }
414: 
415:         return ($modDateA > $modDateB) ? 1 : -1;
416:     }
417: 
418:      /**
419:      * Comparison function for reverse sorting notes by modification date.
420:      *
421:      * @param array $a  Note one.
422:      * @param array $b  Note two.
423:      *
424:      * @return integer  -1 if note one is greater, 1 if note two is greater,
425:      *                  0 if they are equal.
426:      */
427:     protected static function _rsortByModDate($a, $b)
428:     {
429:         // Get note's history
430:         $history = $GLOBALS['injector']->getInstance('Horde_History');
431: 
432:         $guidA = 'mnemo:' . $a['memolist_id'] . ':' . $a['uid'];
433:         $guidB = 'mnemo:' . $b['memolist_id'] . ':' . $b['uid'];
434: 
435:         // Gets the timestamp of the most recent modification to the note
436:         $modDateA = $history->getActionTimestamp($guidA, 'modify');
437:         $modDateB = $history->getActionTimestamp($guidB, 'modify');
438: 
439:         // If the note hasn't been modified, get the creation timestamp
440:         if ($modDateA == 0) {
441:             $modDateA = $history->getActionTimestamp($guidA, 'add');
442:         }
443:         if ($modDateB == 0) {
444:             $modDateB = $history->getActionTimestamp($guidB, 'add');
445:         }
446: 
447:         if ($modDateA == $modDateB) {
448:             return 0;
449:         }
450: 
451:         return ($modDateA < $modDateB) ? 1 : -1;
452:     }
453: 
454:     /**
455:      * Returns the specified permission for the current user.
456:      *
457:      * @param string $permission  A permission, currently only 'max_notes'.
458:      *
459:      * @return mixed  The value of the specified permission.
460:      */
461:     public static function hasPermission($permission)
462:     {
463:         global $perms;
464: 
465:         if (!$perms->exists('mnemo:' . $permission)) {
466:             return true;
467:         }
468: 
469:         $allowed = $perms->getPermissions('mnemo:' . $permission, $GLOBALS['registry']->getAuth());
470:         if (is_array($allowed)) {
471:             switch ($permission) {
472:             case 'max_notes':
473:                 $allowed = max($allowed);
474:                 break;
475:             }
476:         }
477: 
478:         return $allowed;
479:     }
480: 
481:     /**
482:      * Returns a note's passphrase for symmetric encryption from the session
483:      * cache.
484:      *
485:      * @param string $id  A note id.
486:      *
487:      * @return string  The passphrase, if set.
488:      */
489:     public static function getPassphrase($id)
490:     {
491:         if (!$id) {
492:             return;
493:         }
494:         if ($passphrase = $GLOBALS['session']->get('mnemo', 'passphrase/' . $id)) {
495:             $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
496:             return $secret->read($secret->getKey('mnemo'), $passphrase);
497:         }
498:     }
499: 
500:     /**
501:      * Stores a note's passphrase for symmetric encryption in the session
502:      * cache.
503:      *
504:      * @param string $id          A note id.
505:      * @param string $passphrase  The note's passphrase.
506:      *
507:      * @return boolean  True
508:      */
509:     public static function storePassphrase($id, $passphrase)
510:     {
511:         $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
512:         $GLOBALS['session']->set('mnemo', 'passphrase/' . $id, $secret->write($secret->getKey('mnemo'), $passphrase));
513:     }
514: 
515:     /**
516:      * Initial app setup code.
517:      *
518:      * Defines the following $GLOBALS (@TODO these should use the injector)
519:      *  mnemo_shares
520:      *  display_notepads
521:      */
522:     public static function initialize()
523:     {
524:         $GLOBALS['mnemo_shares'] = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create();
525: 
526:         // Update the preference for which notepads to display. If the
527:         // user doesn't have any selected notepads for view then fall
528:         // back to some available notepad.
529:         $GLOBALS['display_notepads'] = unserialize($GLOBALS['prefs']->getValue('display_notepads'));
530:         if (($notepadId = Horde_Util::getFormData('display_notepad')) !== null) {
531:             if (is_array($notepadId)) {
532:                 $GLOBALS['display_notepads'] = $notepadId;
533:             } else {
534:                 if (in_array($notepadId, $GLOBALS['display_notepads'])) {
535:                     $key = array_search($notepadId, $GLOBALS['display_notepads']);
536:                     unset($GLOBALS['display_notepads'][$key]);
537:                 } else {
538:                     $GLOBALS['display_notepads'][] = $notepadId;
539:                 }
540:             }
541:         }
542: 
543:         // Make sure all notepads exist now, to save on checking later.
544:         $_temp = ($GLOBALS['display_notepads']) ? $GLOBALS['display_notepads'] : array();
545: 
546:         $_all = self::listNotepads();
547:         $GLOBALS['display_notepads'] = array();
548:         foreach ($_temp as $id) {
549:             if (isset($_all[$id])) {
550:                 $GLOBALS['display_notepads'][] = $id;
551:             }
552:         }
553: 
554:         // All notepads for guests.
555:         if (!count($GLOBALS['display_notepads']) &&
556:             !$GLOBALS['registry']->getAuth()) {
557:             $GLOBALS['display_notepads'] = array_keys($_all);
558:         }
559: 
560:         /* If the user doesn't own a notepad, create one. */
561:         $notepads = $GLOBALS['injector']->getInstance('Mnemo_Factory_Notepads')
562:             ->create();
563:         if (($new_default = $notepads->ensureDefaultShare()) !== null) {
564:             $GLOBALS['display_notepads'][] = $new_default;
565:         }
566: 
567:         $GLOBALS['prefs']->setValue('display_notepads', serialize($GLOBALS['display_notepads']));
568:     }
569: 
570:     /**
571:      */
572:     static public function getCssStyle($category, $stickies = false)
573:     {
574:         $cManager = new Horde_Prefs_CategoryManager();
575:         $colors = $cManager->colors();
576:         if (!isset($colors[$category])) {
577:             return '';
578:         }
579:         $fgColors = $cManager->fgColors();
580: 
581:         if (!$stickies) {
582:             return 'color:' . (isset($fgColors[$category]) ? $fgColors[$category] : $fgColors['_default_']) . ';' .
583:                 'background:' . $colors[$category] . ';';
584:         }
585: 
586:         $hex = str_replace('#', '', $colors[$category]);
587:         if (strlen($hex) == 3) {
588:             $r = hexdec(substr($hex, 0, 1));
589:             $g = hexdec(substr($hex, 1, 1));
590:             $b = hexdec(substr($hex, 2, 1));
591:         } else {
592:             $r = hexdec(substr($hex, 0, 2));
593:             $g = hexdec(substr($hex, 2, 2));
594:             $b = hexdec(substr($hex, 4, 2));
595:         }
596: 
597:         return "background: rgba($r, $g, $b, 0.5)";
598:     }
599: 
600: }
601: 
API documentation generated by ApiGen