Page MenuHomePhabricator

D16552.id39836.diff
No OneTemporary

D16552.id39836.diff

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}";
}
@@ -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,4 +1,6 @@
BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Phacility//Phabricator//EN
BEGIN:VEVENT
UID:tea-time
CREATED:20160915T070000Z

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 18, 5:45 AM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7708183
Default Alt Text
D16552.id39836.diff (7 KB)

Event Timeline