Page MenuHomePhabricator

D16676.id40139.diff
No OneTemporary

D16676.id40139.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2089,7 +2089,9 @@
'PhabricatorCalendarExportQueryKeyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php',
'PhabricatorCalendarExportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarExportSearchEngine.php',
'PhabricatorCalendarExportTransaction' => 'applications/calendar/storage/PhabricatorCalendarExportTransaction.php',
+ 'PhabricatorCalendarExportTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarExportTransactionQuery.php',
'PhabricatorCalendarExportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarExportTransactionType.php',
+ 'PhabricatorCalendarExportViewController' => 'applications/calendar/controller/PhabricatorCalendarExportViewController.php',
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php',
@@ -6859,7 +6861,9 @@
'PhabricatorCalendarExportQueryKeyTransaction' => 'PhabricatorCalendarExportTransactionType',
'PhabricatorCalendarExportSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorCalendarExportTransaction' => 'PhabricatorModularTransaction',
+ 'PhabricatorCalendarExportTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorCalendarExportTransactionType' => 'PhabricatorModularTransactionType',
+ 'PhabricatorCalendarExportViewController' => 'PhabricatorCalendarController',
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
'PhabricatorCalendarIconSet' => 'PhabricatorIconSet',
diff --git a/src/applications/calendar/controller/PhabricatorCalendarExportViewController.php b/src/applications/calendar/controller/PhabricatorCalendarExportViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/controller/PhabricatorCalendarExportViewController.php
@@ -0,0 +1,154 @@
+<?php
+
+final class PhabricatorCalendarExportViewController
+ extends PhabricatorCalendarController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $export = id(new PhabricatorCalendarExportQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($request->getURIData('id')))
+ ->executeOne();
+ if (!$export) {
+ return new Aphront404Response();
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(
+ pht('Exports'),
+ '/calendar/export/');
+ $crumbs->addTextCrumb(pht('Export %d', $export->getID()));
+ $crumbs->setBorder(true);
+
+ $timeline = $this->buildTransactionTimeline(
+ $export,
+ new PhabricatorCalendarExportTransactionQuery());
+ $timeline->setShouldTerminate(true);
+
+ $header = $this->buildHeaderView($export);
+ $curtain = $this->buildCurtain($export);
+ $details = $this->buildPropertySection($export);
+
+ $view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setMainColumn(
+ array(
+ $timeline,
+ ))
+ ->setCurtain($curtain)
+ ->addPropertySection(pht('Details'), $details);
+
+ $page_title = pht('Export %d %s', $export->getID(), $export->getName());
+
+ return $this->newPage()
+ ->setTitle($page_title)
+ ->setCrumbs($crumbs)
+ ->setPageObjectPHIDs(array($export->getPHID()))
+ ->appendChild($view);
+ }
+
+ private function buildHeaderView(
+ PhabricatorCalendarExport $export) {
+ $viewer = $this->getViewer();
+ $id = $export->getID();
+
+ if ($export->getIsDisabled()) {
+ $icon = 'fa-ban';
+ $color = 'grey';
+ $status = pht('Disabled');
+ } else {
+ $icon = 'fa-check';
+ $color = 'bluegrey';
+ $status = pht('Active');
+ }
+
+ $header = id(new PHUIHeaderView())
+ ->setUser($viewer)
+ ->setHeader($export->getName())
+ ->setStatus($icon, $color, $status)
+ ->setPolicyObject($export);
+
+ return $header;
+ }
+
+ private function buildCurtain(PhabricatorCalendarExport $export) {
+ $viewer = $this->getRequest()->getUser();
+ $id = $export->getID();
+
+ $curtain = $this->newCurtainView($export);
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $export,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $ics_uri = $export->getICSURI();
+
+ $edit_uri = "export/edit/{$id}/";
+ $edit_uri = $this->getApplicationURI($edit_uri);
+
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Export'))
+ ->setIcon('fa-pencil')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit)
+ ->setHref($edit_uri));
+
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Export as .ics'))
+ ->setIcon('fa-download')
+ ->setHref($ics_uri));
+
+ return $curtain;
+ }
+
+ private function buildPropertySection(
+ PhabricatorCalendarExport $export) {
+ $viewer = $this->getViewer();
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer);
+
+ $mode = $export->getPolicyMode();
+
+ $policy_icon = PhabricatorCalendarExport::getPolicyModeIcon($mode);
+ $policy_name = PhabricatorCalendarExport::getPolicyModeName($mode);
+ $policy_desc = PhabricatorCalendarExport::getPolicyModeDescription($mode);
+ $policy_color = PhabricatorCalendarExport::getPolicyModeColor($mode);
+
+ $policy_view = id(new PHUIStatusListView())
+ ->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon($policy_icon, $policy_color)
+ ->setTarget($policy_name)
+ ->setNote($policy_desc));
+
+ $properties->addProperty(pht('Mode'), $policy_view);
+
+ $query_key = $export->getQueryKey();
+ $query_link = phutil_tag(
+ 'a',
+ array(
+ 'href' => $this->getApplicationURI("/query/{$query_key}/"),
+ ),
+ $query_key);
+ $properties->addProperty(pht('Query'), $query_link);
+
+ $ics_uri = $export->getICSURI();
+ $ics_uri = PhabricatorEnv::getURI($ics_uri);
+
+ $properties->addProperty(
+ pht('ICS URI'),
+ phutil_tag(
+ 'a',
+ array(
+ 'href' => $ics_uri,
+ ),
+ $ics_uri));
+
+ return $properties;
+ }
+}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php b/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
--- a/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
@@ -43,7 +43,7 @@
}
protected function getObjectEditShortText($object) {
- return $object->getMonogram();
+ return pht('Export %d', $object->getID());
}
protected function getObjectCreateShortText() {
@@ -65,6 +65,22 @@
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
+ $export_modes = PhabricatorCalendarExport::getAvailablePolicyModes();
+ $export_modes = array_fuse($export_modes);
+
+ $current_mode = $object->getPolicyMode();
+ if (empty($export_modes[$current_mode])) {
+ array_shift($export_modes, $current_mode);
+ }
+
+ $mode_options = array();
+ foreach ($export_modes as $export_mode) {
+ $mode_name = PhabricatorCalendarExport::getPolicyModeName($export_mode);
+ $mode_summary = PhabricatorCalendarExport::getPolicyModeSummary(
+ $export_mode);
+ $mode_options[$export_mode] = pht('%s: %s', $mode_name, $mode_summary);
+ }
+
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
@@ -87,6 +103,27 @@
->setConduitDescription(pht('Disable or restore the export.'))
->setConduitTypeDescription(pht('True to cancel the export.'))
->setValue($object->getIsDisabled()),
+ id(new PhabricatorTextEditField())
+ ->setKey('queryKey')
+ ->setLabel(pht('Query Key'))
+ ->setDescription(pht('Query to execute.'))
+ ->setIsRequired(true)
+ ->setTransactionType(
+ PhabricatorCalendarExportQueryKeyTransaction::TRANSACTIONTYPE)
+ ->setConduitDescription(pht('Change the export query key.'))
+ ->setConduitTypeDescription(pht('New export query key.'))
+ ->setValue($object->getQueryKey()),
+ id(new PhabricatorSelectEditField())
+ ->setKey('mode')
+ ->setLabel(pht('Mode'))
+ ->setTransactionType(
+ PhabricatorCalendarExportModeTransaction::TRANSACTIONTYPE)
+ ->setOptions($mode_options)
+ ->setDescription(pht('Change the policy mode for the export.'))
+ ->setConduitDescription(pht('Adjust export mode.'))
+ ->setConduitTypeDescription(pht('New export mode.'))
+ ->setValue($current_mode),
+
);
return $fields;
diff --git a/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php b/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
--- a/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
@@ -11,4 +11,8 @@
return pht('Calendar Exports');
}
+ public function getCreateObjectTitle($author, $object) {
+ return pht('%s created this export.', $author);
+ }
+
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
--- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
@@ -255,11 +255,20 @@
array $handles) {
if ($this->isMonthView($query)) {
- return $this->buildCalendarMonthView($events, $query);
+ $result = $this->buildCalendarMonthView($events, $query);
} else if ($this->isDayView($query)) {
- return $this->buildCalendarDayView($events, $query);
+ $result = $this->buildCalendarDayView($events, $query);
+ } else {
+ $result = $this->buildCalendarListView($events, $query);
}
+ return $result;
+ }
+
+ private function buildCalendarListView(
+ array $events,
+ PhabricatorSavedQuery $query) {
+
assert_instances_of($events, 'PhabricatorCalendarEvent');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
@@ -562,4 +571,17 @@
return false;
}
+ public function newUseResultsActions(PhabricatorSavedQuery $saved) {
+ $viewer = $this->requireViewer();
+ $can_export = $viewer->isLoggedIn();
+
+ return array(
+ id(new PhabricatorActionView())
+ ->setIcon('fa-download')
+ ->setName(pht('Export Query as .ics'))
+ ->setDisabled(!$can_export)
+ ->setHref('/calendar/export/edit/?queryKey='.$saved->getQueryKey()),
+ );
+ }
+
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
--- a/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
@@ -64,6 +64,7 @@
foreach ($exports as $export) {
$item = id(new PHUIObjectItemView())
->setViewer($viewer)
+ ->setObjectName(pht('Export %d', $export->getID()))
->setHeader($export->getName())
->setHref($export->getURI());
@@ -71,6 +72,15 @@
$item->setDisabled(true);
}
+ $mode = $export->getPolicyMode();
+ $policy_icon = PhabricatorCalendarExport::getPolicyModeIcon($mode);
+ $policy_name = PhabricatorCalendarExport::getPolicyModeName($mode);
+ $policy_color = PhabricatorCalendarExport::getPolicyModeColor($mode);
+
+ $item->addIcon(
+ "{$policy_icon} {$policy_color}",
+ $policy_name);
+
$list->addItem($item);
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportTransactionQuery.php b/src/applications/calendar/query/PhabricatorCalendarExportTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/query/PhabricatorCalendarExportTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorCalendarExportTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorCalendarExportTransaction();
+ }
+
+}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarExport.php b/src/applications/calendar/storage/PhabricatorCalendarExport.php
--- a/src/applications/calendar/storage/PhabricatorCalendarExport.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarExport.php
@@ -14,12 +14,12 @@
protected $isDisabled = 0;
const MODE_PUBLIC = 'public';
- const MODE_PRIVATE = 'private';
+ const MODE_PRIVILEGED = 'privileged';
public static function initializeNewCalendarExport(PhabricatorUser $actor) {
return id(new self())
->setAuthorPHID($actor->getPHID())
- ->setPolicyMode(self::MODE_PRIVATE)
+ ->setPolicyMode(self::MODE_PRIVILEGED)
->setIsDisabled(0);
}
@@ -65,10 +65,23 @@
private static function getPolicyModeMap() {
return array(
self::MODE_PUBLIC => array(
+ 'icon' => 'fa-globe',
'name' => pht('Public'),
+ 'color' => 'bluegrey',
+ 'summary' => pht(
+ 'Export only public data.'),
+ 'description' => pht(
+ 'Only publicly available data is exported.'),
),
- self::MODE_PRIVATE => array(
- 'name' => pht('Private'),
+ self::MODE_PRIVILEGED => array(
+ 'icon' => 'fa-unlock-alt',
+ 'name' => pht('Privileged'),
+ 'color' => 'red',
+ 'summary' => pht(
+ 'Export private data.'),
+ 'description' => pht(
+ 'Anyone who knows the URI for this export can view all event '.
+ 'details as though they were logged in with your account.'),
),
);
}
@@ -78,14 +91,55 @@
}
public static function getPolicyModeName($const) {
- $map = self::getPolicyModeSpec($const);
- return idx($map, 'name', $const);
+ $spec = self::getPolicyModeSpec($const);
+ return idx($spec, 'name', $const);
+ }
+
+ public static function getPolicyModeIcon($const) {
+ $spec = self::getPolicyModeSpec($const);
+ return idx($spec, 'icon', $const);
+ }
+
+ public static function getPolicyModeColor($const) {
+ $spec = self::getPolicyModeSpec($const);
+ return idx($spec, 'color', $const);
+ }
+
+ public static function getPolicyModeSummary($const) {
+ $spec = self::getPolicyModeSpec($const);
+ return idx($spec, 'summary', $const);
+ }
+
+ public static function getPolicyModeDescription($const) {
+ $spec = self::getPolicyModeSpec($const);
+ return idx($spec, 'description', $const);
}
public static function getPolicyModes() {
return array_keys(self::getPolicyModeMap());
}
+ public static function getAvailablePolicyModes() {
+ $modes = array();
+
+ if (PhabricatorEnv::getEnvConfig('policy.allow-public')) {
+ $modes[] = self::MODE_PUBLIC;
+ }
+
+ $modes[] = self::MODE_PRIVILEGED;
+
+ return $modes;
+ }
+
+ public function getICSFilename() {
+ return PhabricatorSlug::normalizeProjectSlug($this->getName()).'.ics';
+ }
+
+ public function getICSURI() {
+ $secret_key = $this->getSecretKey();
+ $ics_name = $this->getICSFilename();
+ return "/calendar/export/ics/{$secret_key}/{$ics_name}";
+ }
/* -( PhabricatorPolicyInterface )----------------------------------------- */
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php
--- a/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php
+++ b/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php
@@ -20,12 +20,15 @@
}
public function validateTransactions($object, array $xactions) {
+ $actor = $this->getActor();
+
$errors = array();
foreach ($xactions as $xaction) {
$value = $xaction->getNewValue();
$query = id(new PhabricatorSavedQueryQuery())
+ ->setViewer($actor)
->withEngineClassNames(array('PhabricatorCalendarEventSearchEngine'))
->withQueryKeys(array($value))
->executeOne();
@@ -33,6 +36,13 @@
continue;
}
+ $builtin = id(new PhabricatorCalendarEventSearchEngine())
+ ->setViewer($actor)
+ ->getBuiltinQueries($actor);
+ if (isset($builtin[$value])) {
+ continue;
+ }
+
$errors[] = $this->newInvalidError(
pht(
'Query key "%s" does not identify a valid event query.',
diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php
--- a/src/applications/search/controller/PhabricatorApplicationSearchController.php
+++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php
@@ -252,12 +252,6 @@
get_class($engine)));
}
- if ($list->getActions()) {
- foreach ($list->getActions() as $action) {
- $header->addActionLink($action);
- }
- }
-
if ($list->getObjectList()) {
$box->setObjectList($list->getObjectList());
}
@@ -274,6 +268,21 @@
$result_header = $list->getHeader();
if ($result_header) {
$box->setHeader($result_header);
+ $header = $result_header;
+ }
+
+ if ($list->getActions()) {
+ foreach ($list->getActions() as $action) {
+ $header->addActionLink($action);
+ }
+ }
+
+ $use_actions = $engine->newUseResultsActions($saved_query);
+ if ($use_actions) {
+ $use_dropdown = $this->newUseResultsDropdown(
+ $saved_query,
+ $use_actions);
+ $header->addActionLink($use_dropdown);
}
$more_crumbs = $list->getCrumbs();
@@ -496,5 +505,24 @@
return $nux_view;
}
+ private function newUseResultsDropdown(
+ PhabricatorSavedQuery $query,
+ array $dropdown_items) {
+
+ $viewer = $this->getViewer();
+
+ $action_list = id(new PhabricatorActionListView())
+ ->setViewer($viewer);
+ foreach ($dropdown_items as $dropdown_item) {
+ $action_list->addAction($dropdown_item);
+ }
+
+ return id(new PHUIButtonView())
+ ->setTag('a')
+ ->setHref('#')
+ ->setText(pht('Use Results...'))
+ ->setIcon('fa-road')
+ ->setDropdownMenu($action_list);
+ }
}
diff --git a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
--- a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
+++ b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
@@ -1390,4 +1390,8 @@
return null;
}
+ public function newUseResultsActions(PhabricatorSavedQuery $saved) {
+ return array();
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 21, 10:57 PM (3 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6740141
Default Alt Text
D16676.id40139.diff (19 KB)

Event Timeline