Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15431248
D16552.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D16552.diff
View Options
diff --git a/src/parser/calendar/data/PhutilCalendarAbsoluteDateTime.php b/src/parser/calendar/data/PhutilCalendarAbsoluteDateTime.php
--- a/src/parser/calendar/data/PhutilCalendarAbsoluteDateTime.php
+++ b/src/parser/calendar/data/PhutilCalendarAbsoluteDateTime.php
@@ -51,11 +51,30 @@
->setHour((int)$matches['h'])
->setMinute((int)$matches['i'])
->setSecond((int)$matches['s']);
+ } else {
+ $datetime
+ ->setIsAllDay(true);
}
return $datetime;
}
+ public static function newFromEpoch($epoch, $timezone = 'UTC') {
+ $date = new DateTime('@'.$epoch);
+
+ $zone = new DateTimeZone($timezone);
+ $date->setTimezone($zone);
+
+ return id(new self())
+ ->setYear((int)$date->format('Y'))
+ ->setMonth((int)$date->format('m'))
+ ->setDay((int)$date->format('d'))
+ ->setHour((int)$date->format('H'))
+ ->setMinute((int)$date->format('i'))
+ ->setSecond((int)$date->format('s'))
+ ->setTimezone($timezone);
+ }
+
public function setYear($year) {
$this->year = $year;
return $this;
diff --git a/src/parser/calendar/data/PhutilCalendarDateTime.php b/src/parser/calendar/data/PhutilCalendarDateTime.php
--- a/src/parser/calendar/data/PhutilCalendarDateTime.php
+++ b/src/parser/calendar/data/PhutilCalendarDateTime.php
@@ -4,6 +4,7 @@
extends Phobject {
private $viewerTimezone;
+ private $isAllDay = false;
public function setViewerTimezone($viewer_timezone) {
$this->viewerTimezone = $viewer_timezone;
@@ -14,6 +15,15 @@
return $this->viewerTimezone;
}
+ public function setIsAllDay($is_all_day) {
+ $this->isAllDay = $is_all_day;
+ return $this;
+ }
+
+ public function getIsAllDay() {
+ return $this->isAllDay;
+ }
+
public function getEpoch() {
$datetime = $this->newPHPDateTime();
return (int)$datetime->format('U');
@@ -22,7 +32,12 @@
public function getISO8601() {
$datetime = $this->newPHPDateTime();
$datetime->setTimezone(new DateTimeZone('UTC'));
- return $datetime->format('Ymd\\THis\\Z');
+
+ if ($this->getIsAllDay()) {
+ return $datetime->format('Ymd');
+ } else {
+ return $datetime->format('Ymd\\THis\\Z');
+ }
}
abstract protected function newPHPDateTimeZone();
diff --git a/src/parser/calendar/data/PhutilCalendarProxyDateTime.php b/src/parser/calendar/data/PhutilCalendarProxyDateTime.php
--- a/src/parser/calendar/data/PhutilCalendarProxyDateTime.php
+++ b/src/parser/calendar/data/PhutilCalendarProxyDateTime.php
@@ -23,6 +23,15 @@
return $this->getProxy()->getViewerTimezone();
}
+ public function setIsAllDay($is_all_day) {
+ $this->getProxy()->setIsAllDay($is_all_day);
+ return $this;
+ }
+
+ public function getIsAllDay() {
+ return $this->getProxy()->getIsAllDay();
+ }
+
protected function newPHPDateTimezone() {
return $this->getProxy()->newPHPDateTimezone();
}
diff --git a/src/parser/calendar/ics/PhutilICSWriter.php b/src/parser/calendar/ics/PhutilICSWriter.php
--- a/src/parser/calendar/ics/PhutilICSWriter.php
+++ b/src/parser/calendar/ics/PhutilICSWriter.php
@@ -56,7 +56,7 @@
foreach ($property['parameters'] as $parameter) {
$paramname = $parameter['name'];
- $paramvalue = 'TODO';
+ $paramvalue = $parameter['value'];
$propline[] = ";{$paramname}={$paramvalue}";
}
@@ -95,14 +95,14 @@
// If adding this character would bring the line over 75 bytes, start
// a new line.
if (strlen($buf) + strlen($character) > 75) {
- $out[] = $buf."\n";
+ $out[] = $buf."\r\n";
$buf = ' ';
}
$buf .= $character;
}
- $out[] = $buf."\n";
+ $out[] = $buf."\r\n";
return implode('', $out);
}
@@ -110,7 +110,7 @@
private function getNodeProperties(PhutilCalendarNode $node) {
switch ($node->getNodeType()) {
case PhutilCalendarDocumentNode::NODETYPE:
- return array();
+ return $this->getDocumentNodeProperties($node);
case PhutilCalendarEventNode::NODETYPE:
return $this->getEventNodeProperties($node);
default:
@@ -118,6 +118,21 @@
}
}
+ private function getDocumentNodeProperties(
+ PhutilCalendarDocumentNode $event) {
+ $properties = array();
+
+ $properties[] = $this->newTextProperty(
+ 'VERSION',
+ '2.0');
+
+ $properties[] = $this->newTextProperty(
+ 'PRODID',
+ '-//Phacility//Phabricator//EN');
+
+ return $properties;
+ }
+
private function getEventNodeProperties(PhutilCalendarEventNode $event) {
$properties = array();
@@ -208,6 +223,16 @@
PhutilCalendarDateTime $value,
array $parameters = array()) {
$datetime = $value->getISO8601();
+
+ if ($value->getIsAllDay()) {
+ $parameters[] = array(
+ 'name' => 'VALUE',
+ 'values' => array(
+ 'DATE',
+ ),
+ );
+ }
+
return $this->newProperty($name, $datetime, $parameters);
}
@@ -216,12 +241,39 @@
$value,
array $parameters = array()) {
- // TODO: Actually handle parameters.
+ $map = array(
+ '^' => '^^',
+ "\n" => '^n',
+ '"' => "^'",
+ );
+
+ $writable_params = array();
+ foreach ($parameters as $k => $parameter) {
+ $value_list = array();
+ foreach ($parameter['values'] as $v) {
+ $v = str_replace(array_keys($map), array_values($map), $v);
+
+ // If the parameter value isn't a very simple one, quote it.
+
+ // RFC5545 says that we MUST quote it if it has a colon, a semicolon,
+ // or a comma, and that we MUST quote it if it's a URI.
+ if (!preg_match('/^[A-Za-z0-9]*\z/', $v)) {
+ $v = '"'.$v.'"';
+ }
+
+ $value_list[] = $v;
+ }
+
+ $writable_params[] = array(
+ 'name' => $parameter['name'],
+ 'value' => implode(',', $value_list),
+ );
+ }
return array(
'name' => $name,
'value' => $value,
- 'parameters' => array(),
+ 'parameters' => $writable_params,
);
}
diff --git a/src/parser/calendar/ics/__tests__/PhutilICSWriterTestCase.php b/src/parser/calendar/ics/__tests__/PhutilICSWriterTestCase.php
--- a/src/parser/calendar/ics/__tests__/PhutilICSWriterTestCase.php
+++ b/src/parser/calendar/ics/__tests__/PhutilICSWriterTestCase.php
@@ -2,7 +2,7 @@
final class PhutilICSWriterTestCase extends PhutilTestCase {
- public function testICSWriter() {
+ public function testICSWriterTeaTime() {
$teas = array(
'earl grey tea',
'English breakfast tea',
@@ -37,6 +37,25 @@
$this->assertICS('writer-tea-time.ics', $ics_data);
}
+ public function testICSWriterAllDay() {
+ $event = id(new PhutilCalendarEventNode())
+ ->setUID('christmas-day')
+ ->setName('Christmas 2016')
+ ->setDescription('A minor religious holiday.')
+ ->setCreatedDateTime(
+ PhutilCalendarAbsoluteDateTime::newFromISO8601('20160901T232425Z'))
+ ->setModifiedDateTime(
+ PhutilCalendarAbsoluteDateTime::newFromISO8601('20160901T232425Z'))
+ ->setStartDateTime(
+ PhutilCalendarAbsoluteDateTime::newFromISO8601('20161225'))
+ ->setEndDateTime(
+ PhutilCalendarAbsoluteDateTime::newFromISO8601('20161226'));
+
+ $ics_data = $this->writeICSSingleEvent($event);
+
+ $this->assertICS('writer-christmas.ics', $ics_data);
+ }
+
private function writeICSSingleEvent(PhutilCalendarEventNode $event) {
$calendar = id(new PhutilCalendarDocumentNode())
->appendChild($event);
diff --git a/src/parser/calendar/ics/__tests__/data/writer-christmas.ics b/src/parser/calendar/ics/__tests__/data/writer-christmas.ics
new file mode 100644
--- /dev/null
+++ b/src/parser/calendar/ics/__tests__/data/writer-christmas.ics
@@ -0,0 +1,13 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Phacility//Phabricator//EN
+BEGIN:VEVENT
+UID:christmas-day
+CREATED:20160901T232425Z
+DTSTAMP:20160901T232425Z
+DTSTART;VALUE=DATE:20161225
+DTEND;VALUE=DATE:20161226
+SUMMARY:Christmas 2016
+DESCRIPTION:A minor religious holiday.
+END:VEVENT
+END:VCALENDAR
diff --git a/src/parser/calendar/ics/__tests__/data/writer-tea-time.ics b/src/parser/calendar/ics/__tests__/data/writer-tea-time.ics
--- a/src/parser/calendar/ics/__tests__/data/writer-tea-time.ics
+++ b/src/parser/calendar/ics/__tests__/data/writer-tea-time.ics
@@ -1,14 +1,16 @@
-BEGIN:VCALENDAR
-BEGIN:VEVENT
-UID:tea-time
-CREATED:20160915T070000Z
-DTSTAMP:20160915T070000Z
-DTSTART:20160916T150000Z
-DTEND:20160916T160000Z
-SUMMARY:Tea Time
-DESCRIPTION:Tea and\, perhaps\, crumpets.\nYour presence is requested!\nThi
- s is a long list of types of tea to test line wrapping: earl grey tea\, En
- glish breakfast tea\, black tea\, green tea\, t-rex\, oolong tea\, mint te
- a\, tea with milk.
-END:VEVENT
-END:VCALENDAR
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Phacility//Phabricator//EN
+BEGIN:VEVENT
+UID:tea-time
+CREATED:20160915T070000Z
+DTSTAMP:20160915T070000Z
+DTSTART:20160916T150000Z
+DTEND:20160916T160000Z
+SUMMARY:Tea Time
+DESCRIPTION:Tea and\, perhaps\, crumpets.\nYour presence is requested!\nThi
+ s is a long list of types of tea to test line wrapping: earl grey tea\, En
+ glish breakfast tea\, black tea\, green tea\, t-rex\, oolong tea\, mint te
+ a\, tea with milk.
+END:VEVENT
+END:VCALENDAR
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 25, 11:17 AM (5 d, 19 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7384327
Default Alt Text
D16552.diff (9 KB)
Attached To
Mode
D16552: Support more ICS parameters and properties
Attached
Detach File
Event Timeline
Log In to Comment