1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 19:40:55 +01:00

Convert Calendar Events to use RRULE frequency constants in various other places

Summary:
Ref T10747.

  - Store recurrence as RRULEs internally.
  - Use RRULE constants.
  - Migrate existing rules to RRULEs.

Test Plan: Ran migration, nothing seemed broken?

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10747

Differential Revision: https://secure.phabricator.com/D16670
This commit is contained in:
epriestley 2016-10-05 10:51:09 -07:00
parent 20f7de91ce
commit 3164ff68db
5 changed files with 146 additions and 68 deletions

View file

@ -0,0 +1,44 @@
<?php
$table = new PhabricatorCalendarEvent();
$conn = $table->establishConnection('w');
$table_name = 'calendar_event';
foreach (new LiskRawMigrationIterator($conn, $table_name) as $row) {
$parameters = phutil_json_decode($row['parameters']);
if (isset($parameters['recurrenceRule'])) {
// This event has already been migrated.
continue;
}
if (!$row['isRecurring']) {
continue;
}
$old_rule = $row['recurrenceFrequency'];
if (!$old_rule) {
continue;
}
try {
$frequency = phutil_json_decode($old_rule);
if ($frequency) {
$frequency_rule = $frequency['rule'];
$frequency_rule = phutil_utf8_strtoupper($frequency_rule);
$rrule = id(new PhutilCalendarRecurrenceRule())
->setFrequency($frequency_rule);
}
} catch (Exception $ex) {
continue;
}
$parameters['recurrenceRule'] = $rrule->toDictionary();
queryfx(
$conn,
'UPDATE %T SET parameters = %s WHERE id = %d',
$table_name,
phutil_json_encode($parameters),
$row['id']);
}

View file

@ -348,9 +348,16 @@ final class PhabricatorCalendarEventViewController
->render(); ->render();
} }
$rule = $event->getFrequencyRule(); $rrule = $event->newRecurrenceRule();
switch ($rule) {
case PhabricatorCalendarEvent::FREQUENCY_DAILY: if ($rrule) {
$frequency = $rrule->getFrequency();
} else {
$frequency = null;
}
switch ($frequency) {
case PhutilCalendarRecurrenceRule::FREQUENCY_DAILY:
if ($is_parent) { if ($is_parent) {
$message = pht('This event repeats every day.'); $message = pht('This event repeats every day.');
} else { } else {
@ -359,7 +366,7 @@ final class PhabricatorCalendarEventViewController
$parent_link); $parent_link);
} }
break; break;
case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: case PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY:
if ($is_parent) { if ($is_parent) {
$message = pht('This event repeats every week.'); $message = pht('This event repeats every week.');
} else { } else {
@ -368,7 +375,7 @@ final class PhabricatorCalendarEventViewController
$parent_link); $parent_link);
} }
break; break;
case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: case PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY:
if ($is_parent) { if ($is_parent) {
$message = pht('This event repeats every month.'); $message = pht('This event repeats every month.');
} else { } else {
@ -377,7 +384,7 @@ final class PhabricatorCalendarEventViewController
$parent_link); $parent_link);
} }
break; break;
case PhabricatorCalendarEvent::FREQUENCY_YEARLY: case PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY:
if ($is_parent) { if ($is_parent) {
$message = pht('This event repeats every year.'); $message = pht('This event repeats every year.');
} else { } else {

View file

@ -68,10 +68,10 @@ final class PhabricatorCalendarEventEditEngine
} }
$frequency_options = array( $frequency_options = array(
PhabricatorCalendarEvent::FREQUENCY_DAILY => pht('Daily'), PhutilCalendarRecurrenceRule::FREQUENCY_DAILY => pht('Daily'),
PhabricatorCalendarEvent::FREQUENCY_WEEKLY => pht('Weekly'), PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY => pht('Weekly'),
PhabricatorCalendarEvent::FREQUENCY_MONTHLY => pht('Monthly'), PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY => pht('Monthly'),
PhabricatorCalendarEvent::FREQUENCY_YEARLY => pht('Yearly'), PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY => pht('Yearly'),
); );
$fields = array( $fields = array(
@ -142,6 +142,14 @@ final class PhabricatorCalendarEventEditEngine
->setConduitTypeDescription(pht('Mark the event as a recurring event.')) ->setConduitTypeDescription(pht('Mark the event as a recurring event.'))
->setValue($object->getIsRecurring()); ->setValue($object->getIsRecurring());
$rrule = $object->newRecurrenceRule();
if ($rrule) {
$frequency = $rrule->getFrequency();
} else {
$frequency = null;
}
$fields[] = id(new PhabricatorSelectEditField()) $fields[] = id(new PhabricatorSelectEditField())
->setKey('frequency') ->setKey('frequency')
->setLabel(pht('Frequency')) ->setLabel(pht('Frequency'))
@ -151,7 +159,7 @@ final class PhabricatorCalendarEventEditEngine
->setDescription(pht('Recurring event frequency.')) ->setDescription(pht('Recurring event frequency.'))
->setConduitDescription(pht('Change the event frequency.')) ->setConduitDescription(pht('Change the event frequency.'))
->setConduitTypeDescription(pht('New event frequency.')) ->setConduitTypeDescription(pht('New event frequency.'))
->setValue($object->getFrequencyRule()); ->setValue($frequency);
} }
if ($this->getIsCreate() || $object->getIsRecurring()) { if ($this->getIsCreate() || $object->getIsRecurring()) {

View file

@ -25,7 +25,6 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
protected $isStub; protected $isStub;
protected $isRecurring = 0; protected $isRecurring = 0;
protected $recurrenceFrequency = array();
private $isGhostEvent = false; private $isGhostEvent = false;
protected $instanceOfEventPHID; protected $instanceOfEventPHID;
@ -52,12 +51,7 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
protected $dateFrom; protected $dateFrom;
protected $dateTo; protected $dateTo;
protected $recurrenceEndDate; protected $recurrenceEndDate;
protected $recurrenceFrequency = array();
// Frequency Constants
const FREQUENCY_DAILY = 'daily';
const FREQUENCY_WEEKLY = 'weekly';
const FREQUENCY_MONTHLY = 'monthly';
const FREQUENCY_YEARLY = 'yearly';
public static function initializeNewCalendarEvent(PhabricatorUser $actor) { public static function initializeNewCalendarEvent(PhabricatorUser $actor) {
$app = id(new PhabricatorApplicationQuery()) $app = id(new PhabricatorApplicationQuery())
@ -85,10 +79,6 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
->setIsAllDay(0) ->setIsAllDay(0)
->setIsStub(0) ->setIsStub(0)
->setIsRecurring(0) ->setIsRecurring(0)
->setRecurrenceFrequency(
array(
'rule' => self::FREQUENCY_WEEKLY,
))
->setIcon($default_icon) ->setIcon($default_icon)
->setViewPolicy($view_policy) ->setViewPolicy($view_policy)
->setEditPolicy($edit_policy) ->setEditPolicy($edit_policy)
@ -120,7 +110,6 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
->setInstanceOfEventPHID($this->getPHID()) ->setInstanceOfEventPHID($this->getPHID())
->setSequenceIndex($sequence) ->setSequenceIndex($sequence)
->setIsRecurring(true) ->setIsRecurring(true)
->setRecurrenceFrequency($this->getRecurrenceFrequency())
->attachParentEvent($this) ->attachParentEvent($this)
->setAllDayDateFrom(0) ->setAllDayDateFrom(0)
->setAllDayDateTo(0) ->setAllDayDateTo(0)
@ -456,27 +445,6 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
return $this; return $this;
} }
public function getFrequencyRule() {
return idx($this->recurrenceFrequency, 'rule');
}
public function getFrequencyUnit() {
$frequency = $this->getFrequencyRule();
switch ($frequency) {
case 'daily':
return 'day';
case 'weekly':
return 'week';
case 'monthly':
return 'month';
case 'yearly':
return 'year';
default:
return 'day';
}
}
public function getURI() { public function getURI() {
if ($this->getIsGhostEvent()) { if ($this->getIsGhostEvent()) {
$base = $this->getParentEvent()->getURI(); $base = $this->getParentEvent()->getURI();
@ -840,20 +808,27 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
$datetime->newAbsoluteDateTime()->toDictionary()); $datetime->newAbsoluteDateTime()->toDictionary());
} }
public function setRecurrenceRule(PhutilCalendarRecurrenceRule $rrule) {
return $this->setParameter(
'recurrenceRule',
$rrule->toDictionary());
}
public function newRecurrenceRule() { public function newRecurrenceRule() {
if ($this->isChildEvent()) { if ($this->isChildEvent()) {
return $this->getParentEvent()->newRecurrenceRule(); return $this->getParentEvent()->newRecurrenceRule();
} }
// TODO: This is a little fragile since it relies on the convenient if (!$this->getIsRecurring()) {
// definition of FREQUENCY constants here and in RecurrenceRule, but return null;
// should be gone soon. }
$map = array(
'FREQ' => phutil_utf8_strtoupper($this->getFrequencyRule()),
);
$rrule = PhutilCalendarRecurrenceRule::newFromDictionary($map); $dict = $this->getParameter('recurrenceRule');
if (!$dict) {
return null;
}
$rrule = PhutilCalendarRecurrenceRule::newFromDictionary($dict);
$start = $this->newStartDateTime(); $start = $this->newStartDateTime();
$rrule->setStartDateTime($start); $rrule->setStartDateTime($start);
@ -869,6 +844,10 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
$set = new PhutilCalendarRecurrenceSet(); $set = new PhutilCalendarRecurrenceSet();
$rrule = $this->newRecurrenceRule(); $rrule = $this->newRecurrenceRule();
if (!$rrule) {
return null;
}
$set->addSource($rrule); $set->addSource($rrule);
return $set; return $set;

View file

@ -6,32 +6,66 @@ final class PhabricatorCalendarEventFrequencyTransaction
const TRANSACTIONTYPE = 'calendar.frequency'; const TRANSACTIONTYPE = 'calendar.frequency';
public function generateOldValue($object) { public function generateOldValue($object) {
return $object->getFrequencyRule(); $rrule = $object->newRecurrenceRule();
if (!$rrule) {
return null;
}
return $rrule->getFrequency();
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$object->setRecurrenceFrequency( $rrule = id(new PhutilCalendarRecurrenceRule())
array( ->setFrequency($value);
'rule' => $value,
)); $dict = $rrule->toDictionary();
$object->setRecurrenceRule($dict);
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$valid = array(
PhutilCalendarRecurrenceRule::FREQUENCY_DAILY,
PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY,
PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY,
PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY,
);
$valid = array_fuse($valid);
foreach ($xactions as $xaction) {
$value = $xaction->getNewValue();
if (!isset($valid[$value])) {
$errors[] = $this->newInvalidError(
pht(
'Event frequency "%s" is not valid. Valid frequences are: %s.',
$value,
implode(', ', $valid)),
$xaction);
}
}
return $errors;
} }
public function getTitle() { public function getTitle() {
$frequency = $this->getFrequencyRule($this->getNewValue()); $frequency = $this->getFrequency($this->getNewValue());
switch ($frequency) { switch ($frequency) {
case PhabricatorCalendarEvent::FREQUENCY_DAILY: case PhutilCalendarRecurrenceRule::FREQUENCY_DAILY:
return pht( return pht(
'%s set this event to repeat daily.', '%s set this event to repeat daily.',
$this->renderAuthor()); $this->renderAuthor());
case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: case PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY:
return pht( return pht(
'%s set this event to repeat weekly.', '%s set this event to repeat weekly.',
$this->renderAuthor()); $this->renderAuthor());
case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: case PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY:
return pht( return pht(
'%s set this event to repeat monthly.', '%s set this event to repeat monthly.',
$this->renderAuthor()); $this->renderAuthor());
case PhabricatorCalendarEvent::FREQUENCY_YEARLY: case PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY:
return pht( return pht(
'%s set this event to repeat yearly.', '%s set this event to repeat yearly.',
$this->renderAuthor()); $this->renderAuthor());
@ -39,24 +73,24 @@ final class PhabricatorCalendarEventFrequencyTransaction
} }
public function getTitleForFeed() { public function getTitleForFeed() {
$frequency = $this->getFrequencyRule($this->getNewValue()); $frequency = $this->getFrequency($this->getNewValue());
switch ($frequency) { switch ($frequency) {
case PhabricatorCalendarEvent::FREQUENCY_DAILY: case PhutilCalendarRecurrenceRule::FREQUENCY_DAILY:
return pht( return pht(
'%s set %s to repeat daily.', '%s set %s to repeat daily.',
$this->renderAuthor(), $this->renderAuthor(),
$this->renderObject()); $this->renderObject());
case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: case PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY:
return pht( return pht(
'%s set %s to repeat weekly.', '%s set %s to repeat weekly.',
$this->renderAuthor(), $this->renderAuthor(),
$this->renderObject()); $this->renderObject());
case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: case PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY:
return pht( return pht(
'%s set %s to repeat monthly.', '%s set %s to repeat monthly.',
$this->renderAuthor(), $this->renderAuthor(),
$this->renderObject()); $this->renderObject());
case PhabricatorCalendarEvent::FREQUENCY_YEARLY: case PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY:
return pht( return pht(
'%s set %s to repeat yearly.', '%s set %s to repeat yearly.',
$this->renderAuthor(), $this->renderAuthor(),
@ -64,12 +98,18 @@ final class PhabricatorCalendarEventFrequencyTransaction
} }
} }
private function getFrequencyRule($value) { private function getFrequency($value) {
// NOTE: This is normalizing three generations of these transactions
// to use RRULE constants. It would be vaguely nice to migrate them
// for consistency.
if (is_array($value)) { if (is_array($value)) {
$value = idx($value, 'rule'); $value = idx($value, 'rule');
} else { } else {
return $value; $value = $value;
} }
return phutil_utf8_strtoupper($value);
} }
} }