From 43091014e0d61ef485097bccb1041ff14b0c79a6 Mon Sep 17 00:00:00 2001 From: Synchro Date: Fri, 9 Jan 2015 14:13:47 +0100 Subject: [PATCH] Refactor and major cleanup of EasyPeasyICS, including a fix for #338 --- changelog.md | 1 + extras/EasyPeasyICS.php | 109 ++++++++++++++++++++++++++++------------ test/phpmailerTest.php | 33 +++++++++++- 3 files changed, 109 insertions(+), 34 deletions(-) diff --git a/changelog.md b/changelog.md index d47be4075..52bc328ad 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ * Remove html2text converter class, provide new mechanism for injecting converters * Improve pointers to docs and support in README * Add example file upload script +* Refactor and major cleanup of EasyPeasyICS, now a lot more usable ## Version 5.2.9 (Sept 25th 2014) * **Important: The autoloader is no longer autoloaded by the PHPMailer class** diff --git a/extras/EasyPeasyICS.php b/extras/EasyPeasyICS.php index b4c7a01c4..1d50b0195 100644 --- a/extras/EasyPeasyICS.php +++ b/extras/EasyPeasyICS.php @@ -40,66 +40,109 @@ public function __construct($calendarName = "") } /** - * Add an event to the calendar. - * @param string $start Time string for the start date and time - anything that strtotime() can parse - * @param string $end Time string for the end date and time - anything that strtotime() can parse - * @param string $summary A summary of the event + * Add an event to this calendar. + * @param string $start The start date and time as a unix timestamp + * @param string $end The end date and time as a unix timestamp + * @param string $summary A summary or title for the event * @param string $description A description of the event * @param string $url A URL for the event + * @param string $uid A unique identifier for the event - generated automatically if not provided + * @return array An array of event details, including any generated UID */ - public function addEvent($start, $end, $summary = "", $description = "", $url = "") + public function addEvent($start, $end, $summary = '', $description = '', $url = '', $uid = '') { - $this->events[] = array( - "start" => $start, - "end" => $end, - "summary" => $summary, - "description" => $description, - "url" => $url + if (empty($uid)) { + $uid = md5(uniqid(mt_rand(), true)) . '@EasyPeasyICS'; + } + $event = array( + 'start' => gmdate('Ymd', $start) . 'T' . gmdate('His', $start) . 'Z', + 'end' => gmdate('Ymd', $end) . 'T' . gmdate('His', $end) . 'Z', + 'summary' => $summary, + 'description' => $description, + 'url' => $url, + 'uid' => $uid ); + $this->events[] = $event; + return $event; + } + + /** + * @return array Get the array of events. + */ + public function getEvents() + { + return $this->events; + } + + /** + * Clear all events. + */ + public function clearEvents() + { + $this->events = array(); } /** - * Render a vcal string. - * @param bool $output Whether to output the calendar data directly (the default) or to return it. + * Get the name of the calendar. * @return string */ - public function render($output = true) + public function getName() { - $ics = ''; + return $this->calendarName; + } + /** + * Set the name of the calendar. + * @param $name + */ + public function setName($name) + { + $this->calendarName = $name; + } + + /** + * Render and optionally output a vcal string. + * @param bool $output Whether to output the calendar data directly (the default). + * @return string The complete rendered vlal + */ + public function render($output = true) + { //Add header - $ics .= "BEGIN:VCALENDAR + $ics = 'BEGIN:VCALENDAR METHOD:PUBLISH VERSION:2.0 -X-WR-CALNAME:" . $this->calendarName . " -PRODID:-//hacksw/handcal//NONSGML v1.0//EN"; +X-WR-CALNAME:' . $this->calendarName . ' +PRODID:-//hacksw/handcal//NONSGML v1.0//EN'; //Add events foreach ($this->events as $event) { - $ics .= " + $ics .= ' BEGIN:VEVENT -UID:" . md5(uniqid(mt_rand(), true)) . "@EasyPeasyICS.php -DTSTAMP:" . gmdate('Ymd') . 'T' . gmdate('His') . "Z -DTSTART:" . gmdate('Ymd', $event["start"]) . "T" . gmdate('His', $event["start"]) . "Z -DTEND:" . gmdate('Ymd', $event["end"]) . "T" . gmdate('His', $event["end"]) . "Z -SUMMARY:" . str_replace("\n", "\\n", $event['summary']) . " -DESCRIPTION:" . str_replace("\n", "\\n", $event['description']) . " -URL;VALUE=URI:" . $event['url'] . " -END:VEVENT"; +UID:' . $event['uid'] . ' +DTSTAMP:' . gmdate('Ymd') . 'T' . gmdate('His') . 'Z +DTSTART:' . $event['start'] . ' +DTEND:' . $event['end'] . ' +SUMMARY:' . str_replace("\n", "\\n", $event['summary']) . ' +DESCRIPTION:' . str_replace("\n", "\\n", $event['description']) . ' +URL;VALUE=URI:' . $event['url'] . ' +END:VEVENT'; } //Add footer - $ics .= " -END:VCALENDAR"; + $ics .= ' +END:VCALENDAR'; if ($output) { //Output + $filename = $this->calendarName; + //Filename needs quoting if it contains spaces + if (strpos($filename, ' ') !== false) { + $filename = '"'.$filename.'"'; + } header('Content-type: text/calendar; charset=utf-8'); - header('Content-Disposition: inline; filename=' . $this->calendarName . '.ics'); + header('Content-Disposition: inline; filename=' . $filename . '.ics'); echo $ics; - return ''; - } else { - return $ics; } + return $ics; } } diff --git a/test/phpmailerTest.php b/test/phpmailerTest.php index f54520cac..f6df41bfc 100644 --- a/test/phpmailerTest.php +++ b/test/phpmailerTest.php @@ -929,12 +929,43 @@ public function testAltBodyAttachment() */ public function testIcal() { + //Standalone ICS tests + require_once '../extras/EasyPeasyICS.php'; + $ICS = new EasyPeasyICS("PHPMailer test calendar"); + $this->assertNotEmpty( + $ICS->addEvent( + strtotime('tomorrow 10:00 Europe/Paris'), + strtotime('tomorrow 11:00 Europe/Paris'), + 'PHPMailer iCal test', + 'A test of PHPMailer iCal support', + 'https://github.com/PHPMailer/PHPMailer' + ), + 'Generated event string is empty' + ); + $ICS->addEvent( + strtotime('tomorrow 10:00 Europe/Paris'), + strtotime('tomorrow 11:00 Europe/Paris'), + 'PHPMailer iCal test', + 'A test of PHPMailer iCal support', + 'https://github.com/PHPMailer/PHPMailer' + ); + $events = $ICS->getEvents(); + $this->assertEquals(2, count($events), 'Event count mismatch'); + $ICS->clearEvents(); + $events = $ICS->getEvents(); + $this->assertEquals(0, count($events), 'Event clearing failed'); + $ICS->setName('test'); + $this->assertEquals('test', $ICS->getName(), 'Setting ICS name failed'); + $this->assertNotEmpty($ICS->render(false), 'Empty calendar'); + //Need to test generated output but PHPUnit isn't playing nice + //$rendered = $ICS->render(); + + //Now test sending an ICS $this->Mail->Body = 'This is the HTML part of the email.'; $this->Mail->AltBody = 'This is the text part of the email.'; $this->Mail->Subject .= ': iCal'; $this->Mail->isHTML(true); $this->buildBody(); - require_once '../extras/EasyPeasyICS.php'; $ICS = new EasyPeasyICS("PHPMailer test calendar"); $ICS->addEvent( strtotime('tomorrow 10:00 Europe/Paris'),