diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php index 378b27d5ce..2b215ccf1e 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php @@ -1,199 +1,218 @@ <?php final class PhabricatorCalendarEventEditController extends PhabricatorCalendarController { private $id; public function willProcessRequest(array $data) { $this->id = idx($data, 'id'); } public function isCreate() { return !$this->id; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $error_name = true; $validation_exception = null; $start_time = id(new AphrontFormDateControl()) ->setUser($user) ->setName('start') ->setLabel(pht('Start')) ->setInitialTime(AphrontFormDateControl::TIME_START_OF_DAY); $end_time = id(new AphrontFormDateControl()) ->setUser($user) ->setName('end') ->setLabel(pht('End')) ->setInitialTime(AphrontFormDateControl::TIME_END_OF_DAY); if ($this->isCreate()) { $event = PhabricatorCalendarEvent::initializeNewCalendarEvent($user); $end_value = $end_time->readValueFromRequest($request); $start_value = $start_time->readValueFromRequest($request); $submit_label = pht('Create'); $filter = 'event/create/'; $page_title = pht('Create Event'); $redirect = 'created'; + $subscribers = array(); } else { $event = id(new PhabricatorCalendarEventQuery()) ->setViewer($user) ->withIDs(array($this->id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$event) { return new Aphront404Response(); } $end_time->setValue($event->getDateTo()); $start_time->setValue($event->getDateFrom()); $submit_label = pht('Update'); $filter = 'event/edit/'.$event->getID().'/'; $page_title = pht('Update Event'); $redirect = 'updated'; + + $subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID( + $event->getPHID()); } $errors = array(); if ($request->isFormPost()) { $xactions = array(); $name = $request->getStr('name'); $type = $request->getInt('status'); $start_value = $start_time->readValueFromRequest($request); $end_value = $end_time->readValueFromRequest($request); $description = $request->getStr('description'); + $subscribers = $request->getArr('subscribers'); if ($start_time->getError()) { $errors[] = pht('Invalid start time; reset to default.'); } if ($end_time->getError()) { $errors[] = pht('Invalid end time; reset to default.'); } if (!$errors) { $xactions[] = id(new PhabricatorCalendarEventTransaction()) ->setTransactionType( PhabricatorCalendarEventTransaction::TYPE_NAME) ->setNewValue($name); $xactions[] = id(new PhabricatorCalendarEventTransaction()) ->setTransactionType( PhabricatorCalendarEventTransaction::TYPE_START_DATE) ->setNewValue($start_value); $xactions[] = id(new PhabricatorCalendarEventTransaction()) ->setTransactionType( PhabricatorCalendarEventTransaction::TYPE_END_DATE) ->setNewValue($end_value); $xactions[] = id(new PhabricatorCalendarEventTransaction()) ->setTransactionType( PhabricatorCalendarEventTransaction::TYPE_STATUS) ->setNewValue($type); + $xactions[] = id(new PhabricatorCalendarEventTransaction()) + ->setTransactionType( + PhabricatorTransactions::TYPE_SUBSCRIBERS) + ->setNewValue(array('=' => array_fuse($subscribers))); + $xactions[] = id(new PhabricatorCalendarEventTransaction()) ->setTransactionType( PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION) ->setNewValue($description); $editor = id(new PhabricatorCalendarEventEditor()) ->setActor($user) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true); try { $xactions = $editor->applyTransactions($event, $xactions); $response = id(new AphrontRedirectResponse()); return $response->setURI('/E'.$event->getID()); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; $error_name = $ex ->getShortMessage(PhabricatorCalendarEventTransaction::TYPE_NAME); } } } $error_view = null; if ($errors) { $error_view = id(new PHUIInfoView()) ->setTitle(pht('Status can not be set!')) ->setErrors($errors); } $name = id(new AphrontFormTextControl()) ->setLabel(pht('Name')) ->setName('name') ->setValue($event->getName()) ->setError($error_name); $status_select = id(new AphrontFormSelectControl()) ->setLabel(pht('Status')) ->setName('status') ->setValue($event->getStatus()) ->setOptions($event->getStatusOptions()); $description = id(new AphrontFormTextAreaControl()) ->setLabel(pht('Description')) ->setName('description') ->setValue($event->getDescription()); + $subscribers = id(new AphrontFormTokenizerControl()) + ->setLabel(pht('Subscribers')) + ->setName('subscribers') + ->setValue($subscribers) + ->setUser($user) + ->setDatasource(new PhabricatorMetaMTAMailableDatasource()); + + $form = id(new AphrontFormView()) ->setUser($user) ->appendChild($name) ->appendChild($status_select) ->appendChild($start_time) ->appendChild($end_time) + ->appendControl($subscribers) ->appendChild($description); $submit = id(new AphrontFormSubmitControl()) ->setValue($submit_label); if ($this->isCreate()) { $submit->addCancelButton($this->getApplicationURI()); } else { $submit->addCancelButton('/E'.$event->getID()); } $form->appendChild($submit); $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($page_title) ->setFormErrors($errors) ->setForm($form); $nav = $this->buildSideNavView($event); $nav->selectFilter($filter); $crumbs = $this->buildApplicationCrumbs(); if (!$this->isCreate()) { $crumbs->addTextCrumb('E'.$event->getId(), '/E'.$event->getId()); } $crumbs->addTextCrumb($page_title); $object_box = id(new PHUIObjectBoxView()) ->setHeaderText($page_title) ->setValidationException($validation_exception) ->appendChild($form); $nav->appendChild( array( $crumbs, $object_box, )); return $this->buildApplicationPage( $nav, array( 'title' => $page_title, )); } } diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php index 8531ab9236..e4b2cfcdb2 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php @@ -1,121 +1,124 @@ <?php final class PhabricatorCalendarEventViewController extends PhabricatorCalendarController { private $id; public function shouldAllowPublic() { return true; } public function willProcessRequest(array $data) { $this->id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $event = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) ->withIDs(array($this->id)) ->executeOne(); if (!$event) { return new Aphront404Response(); } $title = 'E'.$event->getID(); $page_title = $title.' '.$event->getName(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title, '/E'.$event->getID()); $timeline = $this->buildTransactionTimeline( $event, new PhabricatorCalendarEventTransactionQuery()); $header = $this->buildHeaderView($event); $actions = $this->buildActionView($event); $properties = $this->buildPropertyView($event); $properties->setActionList($actions); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); return $this->buildApplicationPage( array( $crumbs, $box, $timeline, ), array( 'title' => $page_title, )); } private function buildHeaderView(PhabricatorCalendarEvent $event) { $viewer = $this->getRequest()->getUser(); return id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($event->getName()) ->setPolicyObject($event); } private function buildActionView(PhabricatorCalendarEvent $event) { $viewer = $this->getRequest()->getUser(); $id = $event->getID(); $actions = id(new PhabricatorActionListView()) ->setObjectURI($this->getApplicationURI('event/'.$id.'/')) - ->setUser($viewer); + ->setUser($viewer) + ->setObject($event); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $event, PhabricatorPolicyCapability::CAN_EDIT); $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Event')) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI("event/edit/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Cancel Event')) ->setIcon('fa-times') ->setHref($this->getApplicationURI("event/delete/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); return $actions; } private function buildPropertyView(PhabricatorCalendarEvent $event) { $viewer = $this->getRequest()->getUser(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($event); $properties->addProperty( pht('Starts'), phabricator_datetime($event->getDateFrom(), $viewer)); $properties->addProperty( pht('Ends'), phabricator_datetime($event->getDateTo(), $viewer)); + $properties->invokeWillRenderEvent(); + $properties->addSectionHeader( pht('Description'), PHUIPropertyListView::ICON_SUMMARY); $properties->addTextContent($event->getDescription()); return $properties; } } diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php index b865bb85ac..cc6e4410f9 100644 --- a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php +++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php @@ -1,145 +1,147 @@ <?php final class PhabricatorCalendarEventEditor extends PhabricatorApplicationTransactionEditor { public function getEditorApplicationClass() { return 'PhabricatorCalendarApplication'; } public function getEditorObjectsDescription() { return pht('Calendar'); } public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorCalendarEventTransaction::TYPE_NAME; $types[] = PhabricatorCalendarEventTransaction::TYPE_START_DATE; $types[] = PhabricatorCalendarEventTransaction::TYPE_END_DATE; $types[] = PhabricatorCalendarEventTransaction::TYPE_STATUS; $types[] = PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; return $types; } protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorCalendarEventTransaction::TYPE_NAME: return $object->getName(); case PhabricatorCalendarEventTransaction::TYPE_START_DATE: return $object->getDateFrom(); case PhabricatorCalendarEventTransaction::TYPE_END_DATE: return $object->getDateTo(); case PhabricatorCalendarEventTransaction::TYPE_STATUS: $status = $object->getStatus(); if ($status === null) { return null; } return (int)$status; case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: return $object->getDescription(); } return parent::getCustomTransactionOldValue($object, $xaction); } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorCalendarEventTransaction::TYPE_NAME: case PhabricatorCalendarEventTransaction::TYPE_START_DATE: case PhabricatorCalendarEventTransaction::TYPE_END_DATE: case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: return $xaction->getNewValue(); case PhabricatorCalendarEventTransaction::TYPE_STATUS: return (int)$xaction->getNewValue(); } return parent::getCustomTransactionNewValue($object, $xaction); } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorCalendarEventTransaction::TYPE_NAME: $object->setName($xaction->getNewValue()); return; case PhabricatorCalendarEventTransaction::TYPE_START_DATE: $object->setDateFrom($xaction->getNewValue()); return; case PhabricatorCalendarEventTransaction::TYPE_END_DATE: $object->setDateTo($xaction->getNewValue()); return; case PhabricatorCalendarEventTransaction::TYPE_STATUS: $object->setStatus($xaction->getNewValue()); return; case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: $object->setDescription($xaction->getNewValue()); return; case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_EDGE: + case PhabricatorTransactions::TYPE_SUBSCRIBERS: return; } return parent::applyCustomInternalTransaction($object, $xaction); } protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorCalendarEventTransaction::TYPE_NAME: case PhabricatorCalendarEventTransaction::TYPE_START_DATE: case PhabricatorCalendarEventTransaction::TYPE_END_DATE: case PhabricatorCalendarEventTransaction::TYPE_STATUS: case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_EDGE: + case PhabricatorTransactions::TYPE_SUBSCRIBERS: return; } return parent::applyCustomExternalTransaction($object, $xaction); } protected function validateTransaction( PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorCalendarEventTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField( $object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError( $type, pht('Required'), pht('Event name is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; } return $errors; } } diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php index 936bd023e1..820cd3d621 100644 --- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php +++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php @@ -1,211 +1,211 @@ <?php final class PhabricatorCalendarEventSearchEngine extends PhabricatorApplicationSearchEngine { public function getResultTypeDescription() { return pht('Calendar Events'); } public function getApplicationClassName() { return 'PhabricatorCalendarApplication'; } public function buildSavedQueryFromRequest(AphrontRequest $request) { $saved = new PhabricatorSavedQuery(); $saved->setParameter( 'rangeStart', $this->readDateFromRequest($request, 'rangeStart')); $saved->setParameter( 'rangeEnd', $this->readDateFromRequest($request, 'rangeEnd')); $saved->setParameter( 'upcoming', $this->readBoolFromRequest($request, 'upcoming')); $saved->setParameter( 'invitedPHIDs', $this->readUsersFromRequest($request, 'invited')); $saved->setParameter( 'creatorPHIDs', $this->readUsersFromRequest($request, 'creators')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhabricatorCalendarEventQuery()); $min_range = null; $max_range = null; if ($saved->getParameter('rangeStart')) { $min_range = $saved->getParameter('rangeStart'); } if ($saved->getParameter('rangeEnd')) { $max_range = $saved->getParameter('rangeEnd'); } if ($saved->getParameter('upcoming')) { if ($min_range) { $min_range = max(time(), $min_range); } else { $min_range = time(); } } if ($min_range || $max_range) { $query->withDateRange($min_range, $max_range); } $invited_phids = $saved->getParameter('invitedPHIDs'); if ($invited_phids) { $query->withInvitedPHIDs($invited_phids); } $creator_phids = $saved->getParameter('creatorPHIDs'); if ($creator_phids) { $query->withCreatorPHIDs($creator_phids); } return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved) { $range_start = $saved->getParameter('rangeStart'); $range_end = $saved->getParameter('rangeEnd'); $upcoming = $saved->getParameter('upcoming'); $invited_phids = $saved->getParameter('invitedPHIDs', array()); $creator_phids = $saved->getParameter('creatorPHIDs', array()); $form ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) ->setName('creators') ->setLabel(pht('Created By')) ->setValue($creator_phids)) ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) ->setName('invited') ->setLabel(pht('Invited')) ->setValue($invited_phids)) ->appendChild( id(new AphrontFormDateControl()) ->setLabel(pht('Occurs After')) ->setUser($this->requireViewer()) ->setName('rangeStart') ->setAllowNull(true) ->setValue($range_start)) ->appendChild( id(new AphrontFormDateControl()) ->setLabel(pht('Occurs Before')) ->setUser($this->requireViewer()) ->setName('rangeEnd') ->setAllowNull(true) ->setValue($range_end)) ->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'upcoming', 1, pht('Show only upcoming events.'), $upcoming)); } protected function getURI($path) { return '/calendar/event/'.$path; } protected function getBuiltinQueryNames() { $names = array( 'upcoming' => pht('Upcoming Events'), 'all' => pht('All Events'), ); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'upcoming': return $query->setParameter('upcoming', true); case 'all': return $query; } return parent::buildSavedQueryFromBuiltin($query_key); } protected function getRequiredHandlePHIDsForResultList( array $objects, PhabricatorSavedQuery $query) { $phids = array(); foreach ($objects as $event) { $phids[$event->getUserPHID()] = 1; } return array_keys($phids); } protected function renderResultList( array $events, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($events, 'PhabricatorCalendarEvent'); $viewer = $this->requireViewer(); $list = new PHUIObjectItemListView(); foreach ($events as $event) { if ($event->getUserPHID() == $viewer->getPHID()) { - $href = $this->getApplicationURI('/event/edit/'.$event->getID().'/'); + $href = '/E'.$event->getID(); } else { $from = $event->getDateFrom(); $month = phabricator_format_local_time($from, $viewer, 'm'); $year = phabricator_format_local_time($from, $viewer, 'Y'); $uri = new PhutilURI($this->getApplicationURI()); $uri->setQueryParams( array( 'month' => $month, 'year' => $year, )); $href = (string) $uri; } $from = phabricator_datetime($event->getDateFrom(), $viewer); $to = phabricator_datetime($event->getDateTo(), $viewer); $creator_handle = $handles[$event->getUserPHID()]; $color = ($event->getStatus() == PhabricatorCalendarEvent::STATUS_AWAY) ? 'red' : 'yellow'; $item = id(new PHUIObjectItemView()) ->setHeader($event->getTerseSummary($viewer)) ->setHref($href) ->setBarColor($color) ->addByline(pht('Creator: %s', $creator_handle->renderLink())) ->addAttribute(pht('From %s to %s', $from, $to)) ->addAttribute(id(new PhutilUTF8StringTruncator()) ->setMaximumGlyphs(64) ->truncateString($event->getDescription())); $list->addItem($item); } return $list; } } diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php index 8d6ab918d2..cb44fdbb22 100644 --- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php +++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php @@ -1,222 +1,237 @@ <?php final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO implements PhabricatorPolicyInterface, PhabricatorMarkupInterface, - PhabricatorApplicationTransactionInterface { + PhabricatorApplicationTransactionInterface, + PhabricatorSubscribableInterface { protected $name; protected $userPHID; protected $dateFrom; protected $dateTo; protected $status; protected $description; const STATUS_AWAY = 1; const STATUS_SPORADIC = 2; public static function initializeNewCalendarEvent(PhabricatorUser $actor) { $app = id(new PhabricatorApplicationQuery()) ->setViewer($actor) ->withClasses(array('PhabricatorCalendarApplication')) ->executeOne(); return id(new PhabricatorCalendarEvent()) ->setUserPHID($actor->getPHID()); } private static $statusTexts = array( self::STATUS_AWAY => 'away', self::STATUS_SPORADIC => 'sporadic', ); + public function setTextStatus($status) { + $statuses = array_flip(self::$statusTexts); + return $this->setStatus($statuses[$status]); + } + public function getTextStatus() { return self::$statusTexts[$this->status]; } public function getStatusOptions() { return array( self::STATUS_AWAY => pht('Away'), self::STATUS_SPORADIC => pht('Sporadic'), ); } public function getHumanStatus() { $options = $this->getStatusOptions(); return $options[$this->status]; } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'name' => 'text', 'dateFrom' => 'epoch', 'dateTo' => 'epoch', 'status' => 'uint32', 'description' => 'text', ), self::CONFIG_KEY_SCHEMA => array( 'userPHID_dateFrom' => array( 'columns' => array('userPHID', 'dateTo'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorCalendarEventPHIDType::TYPECONST); } public function getMonogram() { return 'E'.$this->getID(); } public function getTerseSummary(PhabricatorUser $viewer) { $until = phabricator_date($this->dateTo, $viewer); if ($this->status == PhabricatorCalendarEvent::STATUS_SPORADIC) { return pht('Sporadic until %s', $until); } else { return pht('Away until %s', $until); } } - public function setTextStatus($status) { - $statuses = array_flip(self::$statusTexts); - return $this->setStatus($statuses[$status]); + public static function getNameForStatus($value) { + switch ($value) { + case self::STATUS_AWAY: + return pht('Away'); + case self::STATUS_SPORADIC: + return pht('Sporadic'); + default: + return pht('Unknown'); + } } public function loadCurrentStatuses($user_phids) { if (!$user_phids) { return array(); } $statuses = $this->loadAllWhere( 'userPHID IN (%Ls) AND UNIX_TIMESTAMP() BETWEEN dateFrom AND dateTo', $user_phids); return mpull($statuses, null, 'getUserPHID'); } - public static function getNameForStatus($value) { - switch ($value) { - case self::STATUS_AWAY: - return pht('Away'); - case self::STATUS_SPORADIC: - return pht('Sporadic'); - default: - return pht('Unknown'); - } - } - /** * Validates data and throws exceptions for non-sensical status * windows */ public function save() { if ($this->getDateTo() <= $this->getDateFrom()) { throw new PhabricatorCalendarEventInvalidEpochException(); } return parent::save(); } /* -( Markup Interface )--------------------------------------------------- */ /** * @task markup */ public function getMarkupFieldKey($field) { $hash = PhabricatorHash::digest($this->getMarkupText($field)); $id = $this->getID(); return "calendar:T{$id}:{$field}:{$hash}"; } /** * @task markup */ public function getMarkupText($field) { return $this->getDescription(); } /** * @task markup */ public function newMarkupEngine($field) { return PhabricatorMarkupEngine::newCalendarMarkupEngine(); } /** * @task markup */ public function didMarkupText( $field, $output, PhutilMarkupEngine $engine) { return $output; } /** * @task markup */ public function shouldUseMarkupCache($field) { return (bool)$this->getID(); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return PhabricatorPolicies::getMostOpenPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getUserPHID(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } public function describeAutomaticCapability($capability) { return null; } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorCalendarEventEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new PhabricatorCalendarEventTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } +/* -( PhabricatorSubscribableInterface )----------------------------------- */ + + + public function isAutomaticallySubscribed($phid) { + return ($phid == $this->getUserPHID()); + } + + public function shouldShowSubscribersProperty() { + return true; + } + + public function shouldAllowSubscription($phid) { + return true; + } }