1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: class Whups_Ticket
16: {
17: 18: 19: 20: 21:
22: protected $_id;
23:
24: 25: 26: 27: 28:
29: protected $_details;
30:
31: 32: 33: 34: 35:
36: protected $_changes = array();
37:
38: 39: 40: 41: 42: 43: 44:
45: static public function makeTicket($id)
46: {
47: global $whups_driver;
48:
49: $details = $whups_driver->getTicketDetails($id);
50: $ticket = new Whups_Ticket($id, $details);
51:
52: return $ticket;
53: }
54:
55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65:
66: static public function newTicket($info, $requester)
67: {
68: global $whups_driver;
69:
70: if (!isset($info['type'])) {
71: $info['type'] = $whups_driver->getDefaultType($info['queue']);
72: if (!$info['type']) {
73: $queue = $whups_driver->getQueue($info['queue']);
74: throw new Whups_Exception(
75: sprintf(
76: _("No type for this ticket and no default type for queue \"%s\" specified."),
77: $queue['name']));
78: }
79: }
80: if (!isset($info['state'])) {
81: $info['state'] = $whups_driver->getDefaultState($info['type']);
82: if (!$info['state']) {
83: throw new Whups_Exception(
84: sprintf(
85: _("No state for this ticket and no default state for ticket type \"%s\" specified."),
86: $whups_driver->getTypeName($info['type'])));
87: }
88: }
89: if (!isset($info['priority'])) {
90: $info['priority'] = $whups_driver->getDefaultPriority($info['type']);
91: if (!$info['priority']) {
92: throw new Whups_Exception(
93: sprintf(
94: _("No priority for this ticket and no default priority for ticket type \"%s\" specified."),
95: $whups_driver->getTypeName($info['type'])));
96: }
97: }
98:
99: $id = $whups_driver->addTicket($info, $requester);
100: $details = $whups_driver->getTicketDetails($id, false);
101: $ticket = new Whups_Ticket($id, $details);
102:
103:
104: if (!empty($info['newattachment']['name'])) {
105: $ticket->change(
106: 'attachment',
107: array(
108: 'name' => $info['newattachment']['name'],
109: 'tmp_name' => $info['newattachment']['tmp_name']));
110: }
111:
112:
113: if (!empty($info['deferred_attachment']) &&
114: ($a_name = $GLOBALS['session']->get('whups', 'deferred_attachment/' . $info['deferred_attachment']))) {
115: $ticket->change(
116: 'attachment',
117: array(
118: 'name' => $info['deferred_attachment'],
119: 'tmp_name' => $a_name));
120: unlink($a_name);
121: }
122:
123:
124: if (!empty($info['attachments'])) {
125: $ticket->change('attachments', $info['attachments']);
126: }
127:
128:
129: $ticket->commit(
130: $ticket->get('user_id_requester'),
131: $info['last-transaction'],
132: false);
133:
134:
135: $ticket->notify($ticket->get('user_id_requester'), true);
136:
137: return $ticket;
138: }
139:
140: 141: 142: 143: 144: 145: 146: 147:
148: public function __construct($id, array $details)
149: {
150: $this->_id = $id;
151: $this->_details = $details;
152: }
153:
154: 155: 156: 157: 158:
159: public function getDetails()
160: {
161: return $this->_details;
162: }
163:
164: 165: 166: 167: 168:
169: public function getId()
170: {
171: return $this->_id;
172: }
173:
174: 175: 176: 177: 178: 179: 180:
181: public function get($detail)
182: {
183: return isset($this->_details[$detail])
184: ? $this->_details[$detail]
185: : null;
186: }
187:
188: 189: 190: 191: 192: 193: 194: 195: 196:
197: public function set($detail, $value)
198: {
199: $this->_details[$detail] = $value;
200: }
201:
202: 203: 204: 205: 206: 207: 208: 209: 210:
211: public function change($detail, $value)
212: {
213: $previous_value = isset($this->_details[$detail])
214: ? $this->_details[$detail]
215: : '';
216: if ($previous_value != $value) {
217: $this->_changes[$detail] = array(
218: 'from' => $this->get($detail),
219: 'from_name' => $this->get($detail . '_name'),
220: 'to' => $value);
221: }
222: }
223:
224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237:
238: public function commit($user = null, $transaction = null, $notify = true)
239: {
240: global $whups_driver;
241:
242: if (!count($this->_changes)) {
243: return;
244: }
245:
246: if (is_null($user)) {
247: $user = $GLOBALS['registry']->getAuth();
248: }
249: $author_email = isset($this->_changes['comment-email']['to'])
250: ? $this->_changes['comment-email']['to']
251: : null;
252:
253: if (is_null($transaction)) {
254:
255: $transaction = $whups_driver->newTransaction($user, $author_email);
256: }
257:
258:
259:
260: if ($user === false) {
261: $user = '-' . $transaction . '_transaction';
262: }
263:
264:
265: try {
266: $this->_changes = Horde::callHook('ticket_update', array($this, $this->_changes), 'whups');
267: } catch (Horde_Exception_HookNotSet $e) {
268: }
269:
270:
271: $timestamp = time();
272: $this->_changes['date_updated'] = array('to' => $timestamp);
273: if (isset($this->_changes['state'])) {
274: $state = $whups_driver->getState($this->_changes['state']['to']);
275: if ($state['category'] == 'assigned') {
276: $this->_changes['date_assigned'] = array('to' => $timestamp);
277: $this->_changes['date_resolved'] = array('to' => null);
278: } elseif ($state['category'] == 'resolved') {
279: $this->_changes['date_resolved'] = array('to' => $timestamp);
280: } else {
281: $this->_changes['date_resolved'] = array('to' => null);
282: }
283: }
284:
285: $updates = array();
286: foreach ($this->_changes as $detail => $values) {
287: $value = $values['to'];
288: switch ($detail) {
289: case 'owners':
290:
291:
292: $oldOwners = current($whups_driver->getOwners($this->_id));
293: $this->_changes['oldowners'] = $oldOwners;
294: foreach ($value as $owner) {
295: if (!$oldOwners ||
296: array_search($owner, $oldOwners) === false) {
297: $whups_driver->addTicketOwner($this->_id, $owner);
298: $whups_driver->updateLog(
299: $this->_id, $user,
300: array('assign' => $owner),
301: $transaction);
302: } else {
303:
304:
305: unset($oldOwners[array_search($owner, $oldOwners)]);
306: }
307: }
308:
309:
310: if (is_array($oldOwners)) {
311: foreach ($oldOwners as $owner) {
312: $whups_driver->deleteTicketOwner($this->_id, $owner);
313: $whups_driver->updateLog(
314: $this->_id, $user,
315: array('unassign' => $owner),
316: $transaction);
317: }
318: }
319: break;
320:
321: case 'comment':
322: $commentId = $whups_driver->addComment(
323: $this->_id, $value, $user, $author_email);
324:
325:
326: $updates['comment'] = $commentId;
327: if (!empty($this->_changes['comment-perms'])) {
328: $this->addCommentPerms(
329: $commentId,
330: $this->_changes['comment-perms']['to']);
331: }
332: break;
333:
334: case 'comment-email':
335: case 'comment-perms':
336:
337: break;
338:
339: case 'attachment':
340: $this->addAttachment($value['name'], $value['tmp_name']);
341:
342:
343: $updates['attachment'][] = $value['name'];
344: break;
345:
346: case 'attachments':
347: foreach ($value as $attachment) {
348: $this->addAttachment($attachment['name'], $attachment['tmp_name']);
349:
350:
351: $updates['attachment'][] = $attachment['name'];
352: }
353: break;
354:
355: case 'delete-attachment':
356: $this->deleteAttachment($value);
357:
358:
359: $updates['delete-attachment'] = $value;
360:
361: break;
362:
363: case 'queue':
364:
365: $newqueue = $whups_driver->getQueue($value);
366: if (empty($newqueue['queue_versioned'])) {
367: $updates['version'] = 0;
368: }
369: $updates['queue'] = $value;
370:
371: default:
372: if (strpos($detail, 'attribute_') === 0 &&
373: !is_string($value)) {
374: $value = Horde_Serialize::Serialize($value,
375: Horde_Serialize::JSON);
376: }
377: $updates[$detail] = $value;
378: }
379: }
380:
381: if (count($updates)) {
382: $whups_driver->updateTicket($this->_id, $updates);
383: $whups_driver->updateLog($this->_id, $user, $updates, $transaction);
384: }
385:
386:
387:
388:
389: $details = $whups_driver->getTicketDetails($this->_id);
390: $this->_details = array_merge($this->_details, $details);
391:
392:
393: if ($notify) {
394: $this->notify($user, false);
395: }
396:
397:
398: $this->_changes = array();
399: }
400:
401: 402: 403: 404: 405:
406: public function delete()
407: {
408: global $whups_driver;
409:
410:
411: $view = new Horde_View(array('templatePath' => WHUPS_BASE . '/config'));
412: $view->date = strftime($GLOBALS['prefs']->getValue('date_format'));
413: $view->auth_name = $GLOBALS['injector']
414: ->getInstance('Horde_Core_Factory_Identity')
415: ->create()
416: ->getValue('fullname');
417: if (empty($view->auth_name)) {
418: $view->auth_name = $GLOBALS['registry']->getAuth('bare');
419: }
420:
421:
422: $message_file = WHUPS_BASE . '/config/delete_email.plain';
423: if (file_exists($message_file . '.' . $this->get('queue') . '.php')) {
424: $message_file .= '.' . $this->get('queue') . '.php';
425: } elseif (file_exists($message_file . '.local.php')) {
426: $message_file .= '.local.php';
427: } else {
428: $message_file .= '.php';
429: }
430: $message_file = basename($message_file);
431:
432: if ($GLOBALS['conf']['mail']['incl_resp'] ||
433: !count(current($whups_driver->getOwners($this->_id)))) {
434:
435: $listeners = $whups_driver->getListeners(
436: $this->_id, true, false, true);
437: } else {
438:
439: $listeners = $whups_driver->getListeners(
440: $this->_id, true, false, false);
441: }
442:
443: $this->change('comment', _("The ticket was deleted."));
444: $this->commit(null, null, false);
445: $whups_driver->deleteTicket($this->_id);
446: $whups_driver->mail(array('ticket' => $this,
447: 'recipients' => $listeners,
448: 'subject' => _("Deleted:") . ' ' . $this->get('summary'),
449: 'view' => $view,
450: 'template' => $message_file,
451: 'from' => $GLOBALS['registry']->getAuth()));
452: }
453:
454: 455: 456: 457: 458: 459: 460: 461: 462:
463: public function addAttachment(&$attachment_name, $attachment_file)
464: {
465: if (!isset($GLOBALS['conf']['vfs']['type'])) {
466: throw new Whups_Exception(
467: _("The VFS backend needs to be configured to enable attachment uploads."),
468: 'horde.error');
469: }
470:
471: try {
472: $vfs = $GLOBALS['injector']
473: ->getInstance('Horde_Core_Factory_Vfs')
474: ->create();
475: } catch (Horde_Vfs_Exception $e) {
476: throw new Whups_Exception($e);
477: }
478:
479:
480: $used_names = $this->listAllAttachments();
481:
482: $dir = Whups::VFS_ATTACH_PATH . '/' . $this->_id;
483: while ((array_search($attachment_name, $used_names) !== false) ||
484: $vfs->exists($dir, $attachment_name)) {
485: if (preg_match('/(.*)\[(\d+)\](\.[^.]*)?$/', $attachment_name,
486: $match)) {
487: $attachment_name = $match[1] . '[' . ++$match[2] . ']';
488: if (isset($match[3])) {
489: $attachment_name .= $match[3];
490: }
491: } else {
492: $dot = strrpos($attachment_name, '.');
493: if ($dot === false) {
494: $attachment_name .= '[1]';
495: } else {
496: $attachment_name = substr($attachment_name, 0, $dot)
497: . '[1]' . substr($attachment_name, $dot);
498: }
499: }
500: }
501:
502: try {
503: $vfs->write($dir, $attachment_name, $attachment_file, true);
504: } catch (Horde_Vfs_Exception $e) {
505: throw new Whups_Exception($e);
506: }
507: }
508:
509: 510: 511: 512: 513: 514: 515:
516: public function deleteAttachment($attachment_name)
517: {
518: if (!isset($GLOBALS['conf']['vfs']['type'])) {
519: throw new Whups_Exception(
520: _("The VFS backend needs to be configured to enable attachment uploads."),
521: 'horde.error');
522: }
523:
524: try {
525: $vfs = $GLOBALS['injector']
526: ->getInstance('Horde_Core_Factory_Vfs')
527: ->create();
528: } catch (Horde_Vfs_Exception $e) {
529: throw Whups_Exception($e);
530: }
531:
532: $dir = Whups::VFS_ATTACH_PATH . '/' . $this->_id;
533: if (!$vfs->exists($dir, $attachment_name)) {
534: throw new Whups_Exception(
535: sprintf(_("Attachment %s not found."),
536: $attachment_name),
537: 'horde.error');
538: }
539:
540: try {
541: $vfs->deleteFile($dir, $attachment_name);
542: } catch (Horde_Vfs_Exception $e) {
543: throw new Whups_Exception($e);
544: }
545: }
546:
547: 548: 549: 550: 551: 552: 553:
554: public function listAllAttachments()
555: {
556: $files = array();
557: $history = $GLOBALS['whups_driver']->getHistory($this->_id);
558: foreach ($history as $row) {
559: if (isset($row['changes'])) {
560: foreach ($row['changes'] as $change) {
561: if (isset($change['type']) &&
562: $change['type'] == 'attachment') {
563: $files[] = $change['value'];
564: }
565: }
566: }
567: }
568:
569: return array_unique($files);
570: }
571:
572: 573: 574:
575: public function show()
576: {
577: Whups::urlFor('ticket', $this->_id, true)->redirect();
578: }
579:
580: 581: 582: 583: 584:
585: public function feedLink()
586: {
587: return '<link rel="alternate" type="application/rss+xml" title="'
588: . htmlspecialchars('[#' . $this->getId() . '] ' . $this->get('summary'))
589: . '" href="' . Whups::urlFor('ticket_rss', $this->getId(), true, -1)
590: . '" />';
591: }
592:
593: 594: 595: 596: 597: 598: 599: 600:
601: static public function ($commentId, $group)
602: {
603: if (!empty($group)) {
604: $perms = $GLOBALS['injector']
605: ->getInstance('Horde_Perms');
606: $perms_core = $GLOBALS['injector']
607: ->getInstance('Horde_Core_Perms');
608: if (!$perms->exists('whups')) {
609: $perm = $perms_core->newPermission('whups');
610: $perm->addDefaultPermission(Horde_Perms::ALL, false);
611: $perms->addPermission($perm);
612: }
613: if (!$perms->exists('whups:comments')) {
614: $perms->addPermission($perms_core->newPermission('whups:comments'));
615: }
616: $perm = $perms_core->newPermission('whups:comments:' . $commentId);
617: $perm->addGroupPermission($group, Horde_Perms::READ, false);
618: return $perms->addPermission($perm);
619: }
620: }
621:
622: 623: 624: 625: 626: 627:
628: public function setDetails(Horde_Variables &$vars)
629: {
630: $vars->set('id', $this->getId());
631: foreach ($this->getDetails() as $varname => $value) {
632: $vars->set($varname, $value);
633: }
634:
635:
636: $vars->set('user_id_requester',
637: Whups::formatUser($this->get('user_id_requester')));
638: $vars->set('user_id_owner', Whups::getOwners($this->_id));
639:
640:
641: $attachments = array();
642: try {
643: $files = Whups::getAttachments($this->_id);
644: } catch (Whups_Exception $e) {
645: $GLOBALS['notification']->push($e->getMessage());
646: }
647: if ($files) {
648: foreach ($files as $file) {
649: $attachments[] = Whups::attachmentUrl(
650: $this->_id, $file, $this->_details['queue']);
651: }
652: $vars->set('attachments', implode("<br />\n", $attachments));
653: }
654: }
655:
656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666:
667: public function notify($author, $isNew, $listeners = array())
668: {
669: global $conf, $whups_driver;
670:
671:
672: $attributes = $whups_driver->getAttributesForType($this->get('type'));
673:
674: $fields = array(
675: 'queue' => _("Queue"),
676: 'version' => _("Version"),
677: 'type' => _("Type"),
678: 'state' => _("State"),
679: 'priority' => _("Priority"),
680: 'due' => _("Due"),
681: );
682:
683: $field_names = array_merge($fields, array(_("Created By"),
684: _("Updated By"),
685: _("Summary"),
686: _("Owners"),
687: _("New Attachment"),
688: _("Deleted Attachment")));
689: foreach ($attributes as $attribute) {
690: $field_names[] = $attribute['human_name'];
691: }
692:
693:
694: $length = 0;
695: foreach ($field_names as $field_name) {
696: $length = max($length, Horde_String::length($field_name));
697: }
698: $wrap_break = "\n" . str_repeat(' ', $length + 2) . '| ';
699: $wrap_width = 73 - $length;
700:
701:
702: $url = sprintf(_("Ticket URL: %s"),
703: Whups::urlFor('ticket', $this->_id, true, -1));
704:
705:
706: $table = "------------------------------------------------------------------------------\n"
707: . ' ' . Horde_String::pad(_("Ticket"), $length) . ' | '
708: . $this->_id . "\n" . ' '
709: . Horde_String::pad($isNew ? _("Created By") : _("Updated By"), $length)
710: . ' | ' . Whups::formatUser($author) . "\n";
711: if (isset($this->_changes['summary'])) {
712: $table .= '-' . Horde_String::pad(_("Summary"), $length) . ' | '
713: . Horde_String::wrap($this->_changes['summary']['from'],
714: $wrap_width, $wrap_break)
715: . "\n" . '+' . Horde_String::pad(_("Summary"), $length) . ' | '
716: . Horde_String::wrap($this->get('summary'), $wrap_width, $wrap_break)
717: . "\n";
718: } else {
719: $table .= ' ' . Horde_String::pad(_("Summary"), $length) . ' | '
720: . Horde_String::wrap($this->get('summary'), $wrap_width, $wrap_break)
721: . "\n";
722: }
723:
724: foreach ($fields as $field => $label) {
725: if ($name = $this->get($field . '_name')) {
726: if (isset($this->_changes[$field])) {
727: $table .= '-' . Horde_String::pad($label, $length) . ' | '
728: . Horde_String::wrap($this->_changes[$field]['from_name'],
729: $wrap_width, $wrap_break)
730: . "\n" . '+' . Horde_String::pad($label, $length) . ' | '
731: . Horde_String::wrap($name, $wrap_width, $wrap_break) . "\n";
732: } else {
733: $table .= ' ' . Horde_String::pad($label, $length) . ' | '
734: . Horde_String::wrap($name, $wrap_width, $wrap_break) . "\n";
735: }
736: }
737: }
738:
739:
740: foreach ($attributes as $id => $attribute) {
741: $attribute_id = 'attribute_' . $id;
742: $label = $attribute['human_name'];
743: if (isset($this->_changes[$attribute_id])) {
744: $table .= '-' . Horde_String::pad($label, $length) . ' | '
745: . Horde_String::wrap($this->_changes[$attribute_id]['from'],
746: $wrap_width, $wrap_break)
747: . "\n" . '+' . Horde_String::pad($label, $length) . ' | '
748: . Horde_String::wrap($this->_changes[$attribute_id]['to'],
749: $wrap_width, $wrap_break)
750: . "\n";
751: } else {
752: $table .= ' ' . Horde_String::pad($label, $length) . ' | '
753: . Horde_String::wrap($this->get($attribute_id),
754: $wrap_width, $wrap_break)
755: . "\n";
756: }
757: }
758:
759:
760: $owners = $oldOwners = Horde_String::wrap(
761: Whups::getOwners($this->_id, false, true),
762: $wrap_width, $wrap_break);
763: if (isset($this->_changes['oldowners'])) {
764: $oldOwners = Horde_String::wrap(
765: Whups::getOwners($this->_id, false, true,
766: $this->_changes['oldowners']),
767: $wrap_width, $wrap_break);
768: }
769: if ($owners != $oldOwners) {
770: $table .= '-' . Horde_String::pad(_("Owners"), $length) . ' | '
771: . $oldOwners . "\n" . '+' . Horde_String::pad(_("Owners"), $length)
772: . ' | ' . $owners . "\n";
773: } else {
774: $table .= ' ' . Horde_String::pad(_("Owners"), $length) . ' | '
775: . $owners . "\n";
776: }
777:
778:
779: if (isset($this->_changes['attachment'])) {
780: $table .= '+' . Horde_String::pad(_("New Attachment"), $length) . ' | '
781: . $this->_changes['attachment']['to']['name'] . "\n";
782: }
783: if (!empty($this->_changes['attachments'])) {
784: foreach ($this->_changes['attachments']['to'] as $attachment) {
785: $table .= '+' . Horde_String::pad(_("New Attachment"), $length)
786: . ' | ' . $attachment['name'] . "\n";
787: }
788: }
789:
790:
791: if (isset($this->_changes['delete-attachment'])) {
792: $table .= '+' . Horde_String::pad(_("Deleted Attachment"), $length)
793: . ' | ' . $this->_changes['delete-attachment']['to'] . "\n";
794: }
795:
796: $table .= "------------------------------------------------------------------------------";
797:
798:
799: if (empty($conf['mail']['reply'])) {
800: $dont_reply = _("DO NOT REPLY TO THIS MESSAGE. THIS EMAIL ADDRESS IS NOT MONITORED.") . "\n\n";
801: } else {
802: $dont_reply = '';
803: }
804:
805:
806: $view = new Horde_View(array('templatePath' => WHUPS_BASE . '/config'));
807: $view->ticket_url = $url;
808: $view->table = $table;
809: $view->dont_reply = empty($conf['mail']['reply']);
810: $view->date = strftime($GLOBALS['prefs']->getValue('date_format'));
811: $view->auth_name = $GLOBALS['injector']
812: ->getInstance('Horde_Core_Factory_Identity')
813: ->create()
814: ->getValue('fullname');
815: if (empty($view->auth_name)) {
816: $view->auth_name = $GLOBALS['registry']->getAuth('bare');
817: }
818:
819:
820: $message_file = WHUPS_BASE . '/config/'
821: . ($isNew ? 'create_email.plain' : 'notify_email.plain');
822: if (file_exists($message_file . '.' . $this->get('queue') . '.php')) {
823: $message_file .= '.' . $this->get('queue') . '.php';
824: } elseif (file_exists($message_file . '.local.php')) {
825: $message_file .= '.local.php';
826: } else {
827: $message_file .= '.php';
828: }
829: $message_file = basename($message_file);
830:
831: 832:
833: $subject = $this->get('summary');
834: if (!$isNew) {
835: $subject = 'Re: ' . $subject;
836: }
837:
838: if (empty($listeners)) {
839: if ($conf['mail']['incl_resp'] ||
840: !count(current($whups_driver->getOwners($this->_id)))) {
841:
842: $listeners = $whups_driver->getListeners(
843: $this->_id, true, true, true);
844: } else {
845:
846: $listeners = $whups_driver->getListeners(
847: $this->_id, true, true, false);
848: }
849:
850:
851: if (isset($this->_changes['queue'])) {
852: foreach ($whups_driver->getQueueUsers($this->_changes['queue']['from_name']) as $user) {
853: $listeners[$user] = 'queue';
854: }
855: }
856: }
857:
858: 859:
860: $whups_driver->mail(array('ticket' => $this,
861: 'recipients' => $listeners,
862: 'subject' => $subject,
863: 'view' => $view,
864: 'template' => $message_file,
865: 'from' => $author,
866: 'new' => $isNew));
867: }
868:
869: 870: 871:
872: public function toString()
873: {
874: $fields = array('queue' => _("Queue"),
875: 'version' => _("Version"),
876: 'type' => _("Type"),
877: 'state' => _("State"),
878: 'priority' => _("Priority"),
879: 'due' => _("Due"));
880:
881:
882: $length = 0;
883: foreach (array_merge($fields, array(_("Summary"), _("Owners")))
884: as $field) {
885: $length = max($length, Horde_String::length($field));
886: }
887: $wrap_break = "\n" . str_repeat(' ', $length + 2) . '| ';
888: $wrap_width = 73 - $length;
889:
890:
891: $message = ' ' . Horde_String::pad(_("Ticket"), $length) . ' | '
892: . $this->_id . "\n" . ' ' . Horde_String::pad(_("Summary"), $length)
893: . ' | ' . Horde_String::wrap($this->get('summary'),
894: $wrap_width, $wrap_break)
895: . "\n";
896:
897: foreach ($fields as $field => $label) {
898: if ($name = $this->get($field . '_name')) {
899: $message .= ' ' . Horde_String::pad($label, $length) . ' | '
900: . Horde_String::wrap($name, $wrap_width, $wrap_break) . "\n";
901: }
902: }
903:
904: $message .= ' ' . Horde_String::pad(_("Owners"), $length) . ' | '
905: . Horde_String::wrap(Whups::getOwners($this->_id, false, true),
906: $wrap_width, $wrap_break)
907: . "\n";
908:
909: return $message;
910: }
911:
912: public function __toString()
913: {
914: return $this->toString();
915: }
916:
917: 918: 919: 920: 921: 922:
923: public function addAttributes()
924: {
925: $attributes = $GLOBALS['whups_driver']
926: ->getAllTicketAttributesWithNames($this->getId());
927: foreach ($attributes as $attribute_id => $attribute) {
928: $this->set('attribute_' . $attribute_id, $attribute['value']);
929: }
930: return $attributes;
931: }
932:
933: }
934: