[ Index ] |
|
Code source de IMP H3 (4.1.5) |
1 <?php 2 /** 3 * The IMP_MIME_Viewer_itip class displays vCalendar/iCalendar data 4 * and provides an option to import the data into a calendar source, 5 * if one is available. 6 * 7 * $Horde: imp/lib/MIME/Viewer/itip.php,v 1.37.2.30 2007/05/07 14:20:31 jan Exp $ 8 * 9 * Copyright 2002-2007 Chuck Hagenbuch <chuck@horde.org> 10 * 11 * See the enclosed file COPYING for license information (LGPL). If you 12 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 13 * 14 * @author Chuck Hagenbuch <chuck@horde.org> 15 * @author Mike Cochrane <mike@graftonhall.co.nz> 16 * @since IMP 4.0 17 * @package Horde_MIME_Viewer 18 */ 19 class IMP_MIME_Viewer_itip extends MIME_Viewer { 20 21 /** 22 * Force viewing of a part inline, regardless of the Content-Disposition 23 * of the MIME Part. 24 * 25 * @var boolean 26 */ 27 var $_forceinline = true; 28 29 /** 30 * The messages to output to the user. 31 * 32 * @var array 33 */ 34 var $_msgs = array(); 35 36 /** 37 * The method as marked in either the iCal structure or message header. 38 * 39 * @var string 40 */ 41 var $_method = 'PUBLISH'; 42 43 /** 44 * The headers of the message. 45 * 46 * @var string 47 */ 48 var $_headers; 49 50 /** 51 * Render out the currently set iCalendar contents. 52 * 53 * @param array $params Any parameters the Viewer may need. 54 * 55 * @return string The rendered contents. 56 */ 57 function render($params = array()) 58 { 59 global $registry; 60 require_once 'Horde/iCalendar.php'; 61 62 // Extract the data. 63 $data = $this->mime_part->getContents(); 64 if (empty($this->_headers) && is_a($params[0], 'IMP_Contents')) { 65 $this->_headers = $params[0]->getHeaderOb(); 66 } 67 68 // Parse the iCal file. 69 $vCal = new Horde_iCalendar(); 70 if (!$vCal->parsevCalendar($data)) { 71 return '<h1>' . _("The calendar data is invalid") . '</h1>' . 72 '<pre>' . htmlspecialchars($data) . '</pre>'; 73 } 74 75 // Check if we got vcard data with the wrong vcalendar mime 76 // type. 77 $c = $vCal->getComponentClasses(); 78 if (count($c) == 1 && !empty($c['horde_icalendar_vcard'])) { 79 $vcard_renderer = &Mime_Viewer::factory($this->mime_part, 'text/x-vcard'); 80 return $vcard_renderer->render($params); 81 } 82 83 // Get the method type. 84 $this->_method = $vCal->getAttribute('METHOD'); 85 if (is_a($this->_method, 'PEAR_Error')) { 86 $this->_method = ''; 87 } 88 89 // Get the iCalendar file components. 90 $components = $vCal->getComponents(); 91 92 // Handle the action requests. 93 $actions = Util::getFormData('action', array()); 94 foreach ($actions as $key => $action) { 95 $this->_msgs[$key] = array(); 96 switch ($action) { 97 case 'delete': 98 // vEvent cancellation. 99 if ($registry->hasMethod('calendar/delete')) { 100 $guid = $components[$key]->getAttribute('UID'); 101 $event = $registry->call('calendar/delete', array('guid' => $guid)); 102 if (is_a($event, 'PEAR_Error')) { 103 $this->_msgs[$key][] = array('error', sprintf(_("There was an error deleting the event: %s."), $event->getMessage())); 104 } else { 105 $this->_msgs[$key][] = array('success', _("Event successfully deleted.")); 106 } 107 } else { 108 $this->_msgs[$key][] = array('warning', _("This action is not supported.")); 109 } 110 break; 111 112 case 'update': 113 // vEvent reply. 114 if ($registry->hasMethod('calendar/updateAttendee')) { 115 $event = $registry->call('calendar/updateAttendee', array('response' => $components[$key])); 116 if (is_a($event, 'PEAR_Error')) { 117 $this->_msgs[$key][] = array('error', sprintf(_("There was an error updating the event: %s."), $event->getMessage())); 118 } else { 119 $this->_msgs[$key][] = array('success', _("Respondent Status Updated.")); 120 } 121 } else { 122 $this->_msgs[$key][] = array('warning', _("This action is not supported.")); 123 } 124 break; 125 126 case 'import': 127 case 'accept-import': 128 // vFreebusy reply. 129 // vFreebusy publish. 130 // vEvent request. 131 // vEvent publish. 132 // vTodo publish. 133 // vJournal publish. 134 switch ($components[$key]->getType()) { 135 case 'vEvent': 136 // Import into Kronolith. 137 if ($registry->hasMethod('calendar/import')) { 138 $guid = $registry->call('calendar/import', array('content' => $components[$key], 'contentType' => 'text/calendar')); 139 if (is_a($guid, 'PEAR_Error')) { 140 $this->_msgs[$key][] = array('error', sprintf(_("There was an error importing the event: %s."), $guid->getMessage())); 141 } else { 142 $url = Horde::url($registry->link('calendar/show', array('uid' => $guid))); 143 $this->_msgs[$key][] = array('success', _("The event was added to your calendar.") . 144 ' ' . Horde::link($url, _("View event"), null, '_blank') . Horde::img('mime/icalendar.png', _("View event"), null, $registry->getImageDir('horde')) . '</a>'); 145 } 146 } else { 147 $this->_msgs[$key][] = array('warning', _("This action is not supported.")); 148 } 149 break; 150 151 case 'vFreebusy': 152 // Import into Kronolith. 153 if ($registry->hasMethod('calendar/import_vfreebusy')) { 154 $res = $registry->call('calendar/import_vfreebusy', array($components[$key])); 155 if (is_a($res, 'PEAR_Error')) { 156 $this->_msgs[$key][] = array('error', sprintf(_("There was an error importing user's free/busy information: %s."), $res->getMessage())); 157 } else { 158 $this->_msgs[$key][] = array('success', _("The user's free/busy information was sucessfully stored.")); 159 } 160 } else { 161 $this->_msgs[$key][] = array('warning', _("This action is not supported.")); 162 } 163 break; 164 165 case 'vTodo': 166 // Import into Nag. 167 if ($registry->hasMethod('tasks/import')) { 168 $guid = $registry->call('tasks/import', array($components[$key], 'text/x-vtodo')); 169 if (is_a($guid, 'PEAR_Error')) { 170 $this->_msgs[$key][] = array('error', sprintf(_("There was an error importing the task: %s."), $guid->getMessage())); 171 } else { 172 $url = Horde::url($registry->link('tasks/show', array('uid' => $guid))); 173 $this->_msgs[$key][] = array('success', _("The task has been added to your tasklist.") . 174 ' ' . Horde::link($url, _("View task"), null, '_blank') . Horde::img('mime/icalendar.png', _("View task"), null, $registry->getImageDir('horde')) . '</a>'); 175 } 176 } else { 177 $this->_msgs[$key][] = array('warning', _("This action is not supported.")); 178 } 179 break; 180 181 case 'vJournal': 182 default: 183 $this->_msgs[$key][] = array('warning', _("This action is not yet implemented.")); 184 } 185 186 if ($action != 'accept-import') { 187 break; 188 } 189 190 case 'accept': 191 case 'accept-import': 192 case 'deny': 193 case 'tentative': 194 // vEvent request. 195 if (isset($components[$key]) && 196 $components[$key]->getType() == 'vEvent') { 197 $vEvent = $components[$key]; 198 199 // Get the organizer details. 200 $organizer = $vEvent->getAttribute('ORGANIZER'); 201 if (is_a($organizer, 'PEAR_Error')) { 202 break; 203 } 204 $organizer = parse_url($organizer); 205 $organizerEmail = $organizer['path']; 206 $organizer = $vEvent->getAttribute('ORGANIZER', true); 207 $organizerName = isset($organizer['cn']) ? $organizer['cn'] : ''; 208 209 require_once 'Horde/Identity.php'; 210 require_once 'Horde/MIME.php'; 211 require_once 'Horde/MIME/Headers.php'; 212 require_once 'Horde/MIME/Part.php'; 213 214 // Build the reply. 215 $vCal = new Horde_iCalendar(); 216 $vCal->setAttribute('PRODID', '-//The Horde Project//' . HORDE_AGENT_HEADER . '//EN'); 217 $vCal->setAttribute('METHOD', 'REPLY'); 218 219 $vEvent_reply = &Horde_iCalendar::newComponent('vevent', $vCal); 220 $vEvent_reply->setAttribute('UID', $vEvent->getAttribute('UID')); 221 if (!is_a($vEvent->getAttribute('SUMMARY'), 'PEAR_error')) { 222 $vEvent_reply->setAttribute('SUMMARY', $vEvent->getAttribute('SUMMARY')); 223 } 224 if (!is_a($vEvent->getAttribute('DESCRIPTION'), 'PEAR_error')) { 225 $vEvent_reply->setAttribute('DESCRIPTION', $vEvent->getAttribute('DESCRIPTION')); 226 } 227 $dtstart = $vEvent->getAttribute('DTSTART', true); 228 $vEvent_reply->setAttribute('DTSTART', $vEvent->getAttribute('DTSTART'), array_pop($dtstart)); 229 if (!is_a($vEvent->getAttribute('DTEND'), 'PEAR_error')) { 230 $dtend = $vEvent->getAttribute('DTEND', true); 231 $vEvent_reply->setAttribute('DTEND', $vEvent->getAttribute('DTEND'), array_pop($dtend)); 232 } else { 233 $duration = $vEvent->getAttribute('DURATION', true); 234 $vEvent_reply->setAttribute('DURATION', $vEvent->getAttribute('DURATION'), array_pop($duration)); 235 } 236 if (!is_a($vEvent->getAttribute('SEQUENCE'), 'PEAR_error')) { 237 $vEvent_reply->setAttribute('SEQUENCE', $vEvent->getAttribute('SEQUENCE')); 238 } 239 $vEvent_reply->setAttribute('ORGANIZER', $vEvent->getAttribute('ORGANIZER'), array_pop($organizer)); 240 241 // Find out who we are and update status. 242 $identity = &Identity::singleton(array('imp', 'imp')); 243 $attendees = $vEvent->getAttribute('ATTENDEE'); 244 if (!is_array($attendees)) { 245 $attendees = array($attendees); 246 } 247 foreach ($attendees as $attendee) { 248 $attendee = preg_replace('/mailto:/i', '', $attendee); 249 if (!is_null($id = $identity->getMatchingIdentity($attendee))) { 250 $identity->setDefault($id); 251 break; 252 } 253 } 254 $email = $identity->getFromAddress(); 255 $cn = $identity->getValue('fullname'); 256 $params = array('CN' => $cn); 257 258 switch ($action) { 259 case 'accept': 260 case 'accept-import': 261 $message = sprintf(_("%s has accepted."), $cn); 262 $subject = _("Accepted: ") . $vEvent->getAttribute('SUMMARY'); 263 $params['PARTSTAT'] = 'ACCEPTED'; 264 break; 265 266 case 'deny': 267 $message = sprintf(_("%s has declined."), $cn); 268 $subject = _("Declined: ") . $vEvent->getAttribute('SUMMARY'); 269 $params['PARTSTAT'] = 'DECLINED'; 270 break; 271 272 case 'tentative': 273 $message = sprintf(_("%s has tentatively accepted."), $cn); 274 $subject = _("Tentative: ") . $vEvent->getAttribute('SUMMARY'); 275 $params['PARTSTAT'] = 'TENTATIVE'; 276 break; 277 } 278 279 $vEvent_reply->setAttribute('ATTENDEE', 'mailto:' . $email, $params); 280 $vCal->addComponent($vEvent_reply); 281 282 $mime = new MIME_Part('multipart/alternative'); 283 $body = new MIME_Part('text/plain', 284 String::wrap($message, 76, "\n"), 285 NLS::getCharset()); 286 287 $ics = new MIME_Part('text/calendar', $vCal->exportvCalendar()); 288 $ics->setName('event-reply.ics'); 289 $ics->setContentTypeParameter('METHOD', 'REPLY'); 290 $ics->setCharset(NLS::getCharset()); 291 292 $mime->addPart($body); 293 $mime->addPart($ics); 294 $mime = &MIME_Message::convertMimePart($mime); 295 296 // Build the reply headers. 297 $msg_headers = new MIME_Headers(); 298 $msg_headers->addReceivedHeader(); 299 $msg_headers->addMessageIdHeader(); 300 $msg_headers->addHeader('Date', date('r')); 301 $msg_headers->addHeader('From', $email); 302 $msg_headers->addHeader('To', $organizerEmail); 303 304 $identity->setDefault(Util::getFormData('identity')); 305 $replyto = $identity->getValue('replyto_addr'); 306 if (!empty($replyto) && ($replyto != $email)) { 307 $msg_headers->addHeader('Reply-to', $replyto); 308 } 309 $msg_headers->addHeader('Subject', MIME::encode($subject, NLS::getCharset())); 310 $msg_headers->addMIMEHeaders($mime); 311 312 // Send the reply. 313 $status = $mime->send($organizerEmail, $msg_headers); 314 if (is_a($status, 'PEAR_Error')) { 315 $this->_msgs[$key][] = array('error', sprintf(_("Error sending reply: %s."), $status->getMessage())); 316 } else { 317 $this->_msgs[$key][] = array('success', _("Reply Sent.")); 318 } 319 } else { 320 $this->_msgs[$key][] = array('warning', _("This action is not supported.")); 321 } 322 break; 323 324 case 'send': 325 // vEvent refresh. 326 if (isset($components[$key]) && 327 $components[$key]->getType() == 'vEvent') { 328 $vEvent = $components[$key]; 329 } 330 331 // vTodo refresh. 332 case 'reply': 333 case 'reply2m': 334 // vfreebusy request. 335 if (isset($components[$key]) && 336 $components[$key]->getType() == 'vFreebusy') { 337 $vFb = $components[$key]; 338 339 // Get the organizer details. 340 $organizer = $vFb->getAttribute('ORGANIZER'); 341 if (is_a($organizer, 'PEAR_Error')) { 342 break; 343 } 344 $organizer = parse_url($organizer); 345 $organizerEmail = $organizer['path']; 346 $organizer = $vFb->getAttribute('ORGANIZER', true); 347 $organizerName = isset($organizer['cn']) ? $organizer['cn'] : ''; 348 349 if ($action == 'reply2m') { 350 $startStamp = time(); 351 $endStamp = $startStamp + (60 * 24 * 3600); 352 } else { 353 $startStamp = $vFb->getAttribute('DTSTART'); 354 if (is_a($startStamp, 'PEAR_Error')) { 355 $startStamp = time(); 356 } 357 $endStamp = $vFb->getAttribute('DTEND'); 358 if (is_a($endStamp, 'PEAR_Error')) { 359 $duration = $vFb->getAttribute('DURATION'); 360 if (is_a($duration, 'PEAR_Error')) { 361 $endStamp = $startStamp + (60 * 24 * 3600); 362 } else { 363 $endStamp = $startStamp + $duration; 364 } 365 } 366 } 367 $vfb_reply = $registry->call('calendar/getFreeBusy', 368 array('startStamp' => $startStamp, 369 'endStamp' => $endStamp)); 370 require_once 'Horde/Identity.php'; 371 require_once 'Horde/MIME.php'; 372 require_once 'Horde/MIME/Headers.php'; 373 require_once 'Horde/MIME/Part.php'; 374 375 // Find out who we are and update status. 376 $identity = &Identity::singleton(); 377 $email = $identity->getFromAddress(); 378 $cn = $identity->getValue('fullname'); 379 380 // Build the reply. 381 $vCal = new Horde_iCalendar(); 382 $vCal->setAttribute('PRODID', '-//The Horde Project//' . HORDE_AGENT_HEADER . '//EN'); 383 $vCal->setAttribute('METHOD', 'REPLY'); 384 $vCal->addComponent($vfb_reply); 385 386 $mime = new MIME_Message(); 387 $message = _("Attached is a reply to a calendar request you sent."); 388 $body = new MIME_Part('text/plain', 389 String::wrap($message, 76, "\n"), 390 NLS::getCharset()); 391 392 $ics = new MIME_Part('text/calendar', $vCal->exportvCalendar()); 393 $ics->setName('icalendar.ics'); 394 $ics->setContentTypeParameter('METHOD', 'REPLY'); 395 $ics->setCharset(NLS::getCharset()); 396 397 $mime->addPart($body); 398 $mime->addPart($ics); 399 400 // Build the reply headers. 401 $msg_headers = new MIME_Headers(); 402 $msg_headers->addReceivedHeader(); 403 $msg_headers->addMessageIdHeader(); 404 $msg_headers->addHeader('Date', date('r')); 405 $msg_headers->addHeader('From', $email); 406 $msg_headers->addHeader('To', $organizerEmail); 407 408 $identity->setDefault(Util::getFormData('identity')); 409 $replyto = $identity->getValue('replyto_addr'); 410 if (!empty($replyto) && ($replyto != $email)) { 411 $msg_headers->addHeader('Reply-to', $replyto); 412 } 413 $msg_headers->addHeader('Subject', MIME::encode(_("Free/Busy Request Response"), NLS::getCharset())); 414 $msg_headers->addMIMEHeaders($mime); 415 416 // Send the reply. 417 $status = $mime->send($organizerEmail, $msg_headers); 418 if (is_a($status, 'PEAR_Error')) { 419 $this->_msgs[$key][] = array('error', sprintf(_("Error sending reply: %s."), $status->getMessage())); 420 } else { 421 $this->_msgs[$key][] = array('success', _("Reply Sent.")); 422 } 423 } else { 424 $this->_msgs[$key][] = array('warning', _("Invalid Action selected for this component.")); 425 } 426 break; 427 428 case 'nosup': 429 // vFreebusy request. 430 default: 431 $this->_msgs[$key][] = array('warning', _("This action is not yet implemented.")); 432 break; 433 } 434 } 435 436 // Create the HTML to display the iCal file. 437 $html = ''; 438 if (MIME_Contents::viewAsAttachment()) { 439 $html .= Util::bufferOutput('require', $registry->get('templates', 'horde') . '/common-header.inc'); 440 } 441 $html .= '<form method="post" name="iCal" action="' . Horde::selfUrl(true) . '">'; 442 443 foreach ($components as $key => $component) { 444 switch ($component->getType()) { 445 case 'vEvent': 446 $html .= $this->_vEvent($component, $key); 447 break; 448 449 case 'vTimeZone': 450 // Ignore them. 451 break; 452 453 case 'vFreebusy': 454 $html .= $this->_vFreebusy($component, $key); 455 break; 456 457 // @todo: handle stray vcards here as well. 458 default: 459 $html .= sprintf(_("Unhandled component of type: %s"), $component->getType()); 460 } 461 } 462 463 // Need to work out if we are inline and actually need this. 464 $html .= '</form>'; 465 if (MIME_Contents::viewAsAttachment()) { 466 $html .= Util::bufferOutput('require', $registry->get('templates', 'horde') . '/common-footer.inc'); 467 } 468 469 return $html; 470 } 471 472 /** 473 * Return text/html as the content-type. 474 * 475 * @return string "text/html" constant 476 */ 477 function getType() 478 { 479 return 'text/html; charset=' . NLS::getCharset(); 480 } 481 482 /** 483 * Return the html for a vFreebusy. 484 */ 485 function _vFreebusy($vfb, $id) 486 { 487 global $registry, $prefs; 488 489 $html = ''; 490 $desc = ''; 491 $sender = $vfb->getName(); 492 switch ($this->_method) { 493 case 'PUBLISH': 494 $desc = _("%s has sent you free/busy information."); 495 break; 496 497 case 'REQUEST': 498 $sender = $this->_headers->getValue('From'); 499 $desc = _("%s requests your free/busy information."); 500 break; 501 502 case 'REPLY': 503 $desc = _("%s has replied to a free/busy request."); 504 break; 505 } 506 507 $html .= '<h1 class="header">' . sprintf($desc, $sender) . '</h1>'; 508 509 if ($this->_msgs) { 510 foreach ($this->_msgs[$id] as $msg) { 511 $html .= '<p class="notice">' . Horde::img('alerts/' . $msg[0] . '.png', '', null, $registry->getImageDir('horde')) . $msg[1] . '</p>'; 512 } 513 } 514 515 $start = $vfb->getAttribute('DTSTART'); 516 if (!is_a($start, 'PEAR_Error')) { 517 if (is_array($start)) { 518 $html .= '<p><strong>' . _("Start") . ':</strong> ' . strftime($prefs->getValue('date_format'), mktime(0, 0, 0, $start['month'], $start['mday'], $start['year'])) . '</p>'; 519 } else { 520 $html .= '<p><strong>' . _("Start") . ':</strong> ' . strftime($prefs->getValue('date_format') . ' ' . $prefs->getValue('time_format'), $start) . '</p>'; 521 } 522 } 523 524 $end = $vfb->getAttribute('DTEND'); 525 if (!is_a($end, 'PEAR_Error')) { 526 if (is_array($end)) { 527 $html .= '<p><strong>' . _("End") . ':</strong> ' . strftime($prefs->getValue('date_format'), mktime(0, 0, 0, $end['month'], $end['mday'], $end['year'])) . '</p>'; 528 } else { 529 $html .= '<p><strong>' . _("End") . ':</strong> ' . strftime($prefs->getValue('date_format') . ' ' . $prefs->getValue('time_format'), $end) . '</p>'; 530 } 531 } 532 533 $html .= '<h2 class="smallheader">' . _("Actions") . '</h2>' . 534 '<select name="action[' . $id . ']">'; 535 536 switch ($this->_method) { 537 case 'PUBLISH': 538 if ($registry->hasMethod('calendar/import_vfreebusy')) { 539 $html .= '<option value="import">' . _("Remember the free/busy information.") . '</option>'; 540 } else { 541 $html .= '<option value="nosup">' . _("Reply with Not Supported Message") . '</option>'; 542 } 543 break; 544 545 case 'REQUEST': 546 if ($registry->hasMethod('calendar/getFreeBusy')) { 547 $html .= '<option value="reply">' . _("Reply with requested free/busy information.") . '</option>' . 548 '<option value="reply2m">' . _("Reply with free/busy for next 2 months.") . '</option>'; 549 } else { 550 $html .= '<option value="nosup">' . _("Reply with Not Supported Message") . '</option>'; 551 } 552 553 $html .= '<option value="deny">' . _("Deny request for free/busy information") . '</option>'; 554 break; 555 556 case 'REPLY': 557 if ($registry->hasMethod('calendar/import_vfreebusy')) { 558 $html .= '<option value="import">' . _("Remember the free/busy information.") . '</option>'; 559 } else { 560 $html .= '<option value="nosup">' . _("Reply with Not Supported Message") . '</option>'; 561 } 562 break; 563 } 564 565 return $html . '</select> <input type="submit" class="button" value="' . _("Go") . '/>'; 566 } 567 568 /** 569 * Returns the html for a vEvent. 570 * 571 * @todo IMP 5: move organizerName() from Horde_iCalendar_vevent to 572 * Horde_iCalendar 573 */ 574 function _vEvent($vevent, $id) 575 { 576 global $registry, $prefs; 577 578 $html = ''; 579 $desc = ''; 580 $sender = $vevent->organizerName(); 581 $options = array(); 582 583 $attendees = $vevent->getAttribute('ATTENDEE'); 584 if (!is_a($attendees, 'PEAR_Error') && 585 !empty($attendees) && 586 !is_array($attendees)) { 587 $attendees = array($attendees); 588 } 589 $attendee_params = $vevent->getAttribute('ATTENDEE', true); 590 591 switch ($this->_method) { 592 case 'PUBLISH': 593 $desc = _("%s wishes to make you aware of \"%s\"."); 594 if ($registry->hasMethod('calendar/import')) { 595 $options[] = '<option value="import">' . _("Add this to my calendar") . '</option>'; 596 } 597 break; 598 599 case 'REQUEST': 600 // Check that you are one of the attendees here. 601 $is_attendee = false; 602 $rsvp = false; 603 if (!is_a($attendees, 'PEAR_Error') && !empty($attendees)) { 604 require_once 'Horde/Identity.php'; 605 $identity = &Identity::singleton(array('imp', 'imp')); 606 for ($i = 0, $c = count($attendees); $i < $c; ++$i) { 607 $attendee = parse_url($attendees[$i]); 608 if (!empty($attendee['path']) && 609 $identity->hasAddress($attendee['path'])) { 610 $is_attendee = true; 611 if (!empty($attendee_params[$i]['RSVP']) && 612 String::upper($attendee_params[$i]['RSVP']) == 'TRUE') { 613 $rsvp = true; 614 } 615 break; 616 } 617 } 618 } 619 620 $desc = $is_attendee 621 ? _("%s requests your presence at \"%s\".") 622 : _("%s wishes to make you aware of \"%s\"."); 623 if ($registry->hasMethod('calendar/import')) { 624 if ($rsvp) { 625 $options[] = '<option value="accept-import">' . _("Accept and add to my calendar") . '</option>'; 626 } 627 $options[] = '<option value="import">' . _("Add to my calendar") . '</option>'; 628 } 629 if ($rsvp) { 630 $options[] = '<option value="accept">' . _("Accept request") . '</option>'; 631 $options[] = '<option value="tentative">' . _("Tentatively Accept request") . '</option>'; 632 $options[] = '<option value="deny">' . _("Deny request") . '</option>'; 633 } 634 // $options[] = '<option value="delegate">' . _("Delegate position") . '</option>'; 635 break; 636 637 case 'ADD': 638 $desc = _("%s wishes to ammend \"%s\"."); 639 if ($registry->hasMethod('calendar/import')) { 640 $options[] = '<option value="import">' . _("Update this event on my calendar") . '</option>'; 641 } 642 break; 643 644 case 'REFRESH': 645 $desc = _("%s wishes to receive the latest information about \"%s\"."); 646 $options[] = '<option value="send">' . _("Send Latest Information") . '</option>'; 647 if (!$found && $registry->hasMethod('calendar/eventFromGUID')) { 648 $existing_vevent = $registry->call('calendar/eventFromGUID', array('guid' => $vevent->getAttribute('UID'))); 649 if (!is_a($existing_vevent, 'Pear_error')) { 650 $existing_vevent->updateFromvEvent($vevent); 651 $vevent = $existing_vevent; 652 $found = true; 653 } 654 } 655 break; 656 657 case 'REPLY': 658 $desc = _("%s has replied to the invitation to \"%s\"."); 659 $sender = $this->_headers->getValue('From'); 660 if ($registry->hasMethod('calendar/updateAttendee')) { 661 $options[] = '<option value="update">' . _("Update respondent status") . '</option>'; 662 } 663 break; 664 665 case 'CANCEL': 666 $desc = _("%s has cancelled \"%s\"."); 667 if ($registry->hasMethod('calendar/delete')) { 668 $options[] = '<option value="delete">' . _("Delete from my calendar") . '</option>'; 669 } 670 break; 671 } 672 673 $summary = $vevent->getAttribute('SUMMARY'); 674 if (is_a($summary, 'PEAR_Error')) { 675 $desc = sprintf($desc, htmlspecialchars($sender), _("Unknown Meeting")); 676 } else { 677 $desc = sprintf($desc, htmlspecialchars($sender), htmlspecialchars($summary)); 678 } 679 680 $html .= '<h2 class="header">' . $desc . '</h2>'; 681 682 if ($this->_msgs) { 683 foreach ($this->_msgs[$id] as $msg) { 684 $html .= '<p class="notice">' . Horde::img('alerts/' . $msg[0] . '.png', '', null, $registry->getImageDir('horde')) . $msg[1] . '</p>'; 685 } 686 } 687 688 $start = $vevent->getAttribute('DTSTART'); 689 if (!is_a($start, 'PEAR_Error')) { 690 if (is_array($start)) { 691 $html .= '<p><strong>' . _("Start") . ':</strong> ' . strftime($prefs->getValue('date_format'), mktime(0, 0, 0, $start['month'], $start['mday'], $start['year'])) . '</p>'; 692 } else { 693 $html .= '<p><strong>' . _("Start") . ':</strong> ' . strftime($prefs->getValue('date_format') . ' ' . $prefs->getValue('time_format'), $start) . '</p>'; 694 } 695 } 696 697 $end = $vevent->getAttribute('DTEND'); 698 if (!is_a($end, 'PEAR_Error')) { 699 if (is_array($end)) { 700 $html .= '<p><strong>' . _("End") . ':</strong> ' . strftime($prefs->getValue('date_format'), mktime(0, 0, 0, $end['month'], $end['mday'], $end['year'])) . '</p>'; 701 } else { 702 $html .= '<p><strong>' . _("End") . ':</strong> ' . strftime($prefs->getValue('date_format') . ' ' . $prefs->getValue('time_format'), $end) . '</p>'; 703 } 704 } 705 706 $sum = $vevent->getAttribute('SUMMARY'); 707 if (!is_a($sum, 'PEAR_Error')) { 708 $html .= '<p><strong>' . _("Summary") . ':</strong> ' . htmlspecialchars($sum) . '</p>'; 709 } else { 710 $html .= '<p><strong>' . _("Summary") . ':</strong> <em>' . _("None") . '</em></p>'; 711 } 712 713 $desc = $vevent->getAttribute('DESCRIPTION'); 714 if (!is_a($desc, 'PEAR_Error')) { 715 $html .= '<p><strong>' . _("Description") . ':</strong> ' . nl2br(htmlspecialchars($desc)) . '</p>'; 716 } 717 718 $loc = $vevent->getAttribute('LOCATION'); 719 if (!is_a($loc, 'PEAR_Error')) { 720 $html .= '<p><strong>' . _("Location") . ':</strong>' . htmlspecialchars($loc) . '</p>'; 721 } 722 723 if (!is_a($attendees, 'PEAR_Error') && !empty($attendees)) { 724 $html .= '<h2 class="smallheader">' . _("Attendees") . '</h2>'; 725 726 $html .= '<table><thead class="leftAlign"><tr><th>' . _("Name") . '</th><th>' . _("Role") . '</th><th>' . _("Status") . '</th></tr></thead><tbody>'; 727 foreach ($attendees as $key => $attendee) { 728 $attendee = parse_url($attendee); 729 $attendee = empty($attendee['path']) ? _("Unknown") : $attendee['path']; 730 731 if (isset($attendee_params[$key]['CN'])) { 732 $attendee = $attendee_params[$key]['CN']; 733 } 734 735 $role = _("Required Participant"); 736 if (isset($attendee_params[$key]['ROLE'])) { 737 switch ($attendee_params[$key]['ROLE']) { 738 case 'CHAIR': 739 $role = _("Chair Person"); 740 break; 741 742 case 'OPT-PARTICIPANT': 743 $role = _("Optional Participant"); 744 break; 745 746 case 'NON-PARTICIPANT': 747 $role = _("Non Participant"); 748 break; 749 750 case 'REQ-PARTICIPANT': 751 default: 752 // Already set above. 753 break; 754 } 755 } 756 757 $status = _("Awaiting Response"); 758 if (isset($attendee_params[$key]['PARTSTAT'])) { 759 $status = $this->_partstatToString($attendee_params[$key]['PARTSTAT'], $status); 760 } 761 762 $html .= '<tr><td>' . htmlspecialchars($attendee) . '</td><td>' . htmlspecialchars($role) . '</td><td>' . htmlspecialchars($status) . '</td></tr>'; 763 } 764 $html .= '</tbody></table>'; 765 } 766 767 if ($options) { 768 $html .= '<h2 class="smallheader">' . _("Actions") . '</h2>' . 769 '<select name="action[' . $id . ']">' . 770 implode("\n", $options) . 771 '</select> <input type="submit" class="button" value="' . _("Go") . '" />'; 772 } 773 774 return $html; 775 } 776 777 /** 778 * Translate the Participation status to string. 779 * 780 * @param string $value The value of PARTSTAT. 781 * @param string $default The value to return as default. 782 * 783 * @return string The translated string. 784 */ 785 function _partstatToString($value, $default = null) 786 { 787 switch ($value) { 788 case 'ACCEPTED': 789 return _("Accepted"); 790 break; 791 792 case 'DECLINED': 793 return _("Declined"); 794 break; 795 796 case 'TENTATIVE': 797 return _("Tentatively Accepted"); 798 break; 799 800 case 'DELEGATED': 801 return _("Delegated"); 802 break; 803 804 case 'COMPLETED': 805 return _("Completed"); 806 break; 807 808 case 'IN-PROCESS': 809 return _("In Process"); 810 break; 811 812 case 'NEEDS-ACTION': 813 default: 814 return is_null($default) ? _("Needs Action") : $default; 815 } 816 } 817 818 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 12:30:07 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |