Page MenuHomePhabricator

D16675.diff
No OneTemporary

D16675.diff

diff --git a/resources/sql/autopatches/20161005.cal.02.export.sql b/resources/sql/autopatches/20161005.cal.02.export.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20161005.cal.02.export.sql
@@ -0,0 +1,14 @@
+CREATE TABLE {$NAMESPACE}_calendar.calendar_export (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ name LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ authorPHID VARBINARY(64) NOT NULL,
+ policyMode VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
+ queryKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
+ secretKey BINARY(20) NOT NULL,
+ isDisabled BOOL NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ KEY `key_author` (authorPHID),
+ UNIQUE KEY `key_secret` (secretKey)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20161005.cal.03.exportxaction.sql b/resources/sql/autopatches/20161005.cal.03.exportxaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20161005.cal.03.exportxaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_calendar.calendar_exporttransaction (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ authorPHID VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ commentPHID VARBINARY(64) DEFAULT NULL,
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
+ oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (`phid`),
+ KEY `key_object` (`objectPHID`)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
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
@@ -2075,6 +2075,20 @@
'PhabricatorCalendarEventTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php',
'PhabricatorCalendarEventUntilDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php',
'PhabricatorCalendarEventViewController' => 'applications/calendar/controller/PhabricatorCalendarEventViewController.php',
+ 'PhabricatorCalendarExport' => 'applications/calendar/storage/PhabricatorCalendarExport.php',
+ 'PhabricatorCalendarExportDisableTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportDisableTransaction.php',
+ 'PhabricatorCalendarExportEditController' => 'applications/calendar/controller/PhabricatorCalendarExportEditController.php',
+ 'PhabricatorCalendarExportEditEngine' => 'applications/calendar/editor/PhabricatorCalendarExportEditEngine.php',
+ 'PhabricatorCalendarExportEditor' => 'applications/calendar/editor/PhabricatorCalendarExportEditor.php',
+ 'PhabricatorCalendarExportListController' => 'applications/calendar/controller/PhabricatorCalendarExportListController.php',
+ 'PhabricatorCalendarExportModeTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportModeTransaction.php',
+ 'PhabricatorCalendarExportNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportNameTransaction.php',
+ 'PhabricatorCalendarExportPHIDType' => 'applications/calendar/phid/PhabricatorCalendarExportPHIDType.php',
+ 'PhabricatorCalendarExportQuery' => 'applications/calendar/query/PhabricatorCalendarExportQuery.php',
+ 'PhabricatorCalendarExportQueryKeyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php',
+ 'PhabricatorCalendarExportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarExportSearchEngine.php',
+ 'PhabricatorCalendarExportTransaction' => 'applications/calendar/storage/PhabricatorCalendarExportTransaction.php',
+ 'PhabricatorCalendarExportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarExportTransactionType.php',
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php',
@@ -6825,6 +6839,25 @@
'PhabricatorCalendarEventTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorCalendarEventUntilDateTransaction' => 'PhabricatorCalendarEventDateTransaction',
'PhabricatorCalendarEventViewController' => 'PhabricatorCalendarController',
+ 'PhabricatorCalendarExport' => array(
+ 'PhabricatorCalendarDAO',
+ 'PhabricatorPolicyInterface',
+ 'PhabricatorApplicationTransactionInterface',
+ 'PhabricatorDestructibleInterface',
+ ),
+ 'PhabricatorCalendarExportDisableTransaction' => 'PhabricatorCalendarExportTransactionType',
+ 'PhabricatorCalendarExportEditController' => 'PhabricatorCalendarController',
+ 'PhabricatorCalendarExportEditEngine' => 'PhabricatorEditEngine',
+ 'PhabricatorCalendarExportEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhabricatorCalendarExportListController' => 'PhabricatorCalendarController',
+ 'PhabricatorCalendarExportModeTransaction' => 'PhabricatorCalendarExportTransactionType',
+ 'PhabricatorCalendarExportNameTransaction' => 'PhabricatorCalendarExportTransactionType',
+ 'PhabricatorCalendarExportPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorCalendarExportQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorCalendarExportQueryKeyTransaction' => 'PhabricatorCalendarExportTransactionType',
+ 'PhabricatorCalendarExportSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'PhabricatorCalendarExportTransaction' => 'PhabricatorModularTransaction',
+ 'PhabricatorCalendarExportTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
'PhabricatorCalendarIconSet' => 'PhabricatorIconSet',
diff --git a/src/applications/calendar/application/PhabricatorCalendarApplication.php b/src/applications/calendar/application/PhabricatorCalendarApplication.php
--- a/src/applications/calendar/application/PhabricatorCalendarApplication.php
+++ b/src/applications/calendar/application/PhabricatorCalendarApplication.php
@@ -62,6 +62,16 @@
'export/(?P<id>[1-9]\d*)/(?P<filename>[^/]*)'
=> 'PhabricatorCalendarEventExportController',
),
+ 'export/' => array(
+ $this->getQueryRoutePattern()
+ => 'PhabricatorCalendarExportListController',
+ $this->getEditRoutePattern('edit/')
+ => 'PhabricatorCalendarExportEditController',
+ '(?P<id>[1-9]\d*)/'
+ => 'PhabricatorCalendarExportViewController',
+ 'ics/(?P<secretKey>[^/]+)/(?P<filename>[^/]*)'
+ => 'PhabricatorCalendarExportICSController',
+ ),
),
);
}
diff --git a/src/applications/calendar/controller/PhabricatorCalendarExportEditController.php b/src/applications/calendar/controller/PhabricatorCalendarExportEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/controller/PhabricatorCalendarExportEditController.php
@@ -0,0 +1,12 @@
+<?php
+
+final class PhabricatorCalendarExportEditController
+ extends PhabricatorCalendarController {
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorCalendarExportEditEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+}
diff --git a/src/applications/calendar/controller/PhabricatorCalendarExportListController.php b/src/applications/calendar/controller/PhabricatorCalendarExportListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/controller/PhabricatorCalendarExportListController.php
@@ -0,0 +1,27 @@
+<?php
+
+final class PhabricatorCalendarExportListController
+ extends PhabricatorCalendarController {
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorCalendarExportSearchEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $doc_name = 'Calendar User Guide: Exporting Events';
+ $doc_href = PhabricatorEnv::getDoclink($doc_name);
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('Guide: Exporting Events'))
+ ->setIcon('fa-book')
+ ->setHref($doc_href));
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php b/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
@@ -0,0 +1,96 @@
+<?php
+
+final class PhabricatorCalendarExportEditEngine
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'calendar.export';
+
+ public function getEngineName() {
+ return pht('Calendar Exports');
+ }
+
+ public function isEngineConfigurable() {
+ return false;
+ }
+
+ public function getSummaryHeader() {
+ return pht('Configure Calendar Export Forms');
+ }
+
+ public function getSummaryText() {
+ return pht('Configure how users create and edit exports.');
+ }
+
+ public function getEngineApplicationClass() {
+ return 'PhabricatorCalendarApplication';
+ }
+
+ protected function newEditableObject() {
+ return PhabricatorCalendarExport::initializeNewCalendarExport(
+ $this->getViewer());
+ }
+
+ protected function newObjectQuery() {
+ return new PhabricatorCalendarExportQuery();
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create New Export');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit Export: %s', $object->getName());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return $object->getMonogram();
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Export');
+ }
+
+ protected function getObjectName() {
+ return pht('Export');
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+ protected function getEditorURI() {
+ return $this->getApplication()->getApplicationURI('export/edit/');
+ }
+
+ protected function buildCustomEditFields($object) {
+ $viewer = $this->getViewer();
+
+ $fields = array(
+ id(new PhabricatorTextEditField())
+ ->setKey('name')
+ ->setLabel(pht('Name'))
+ ->setDescription(pht('Name of the export.'))
+ ->setIsRequired(true)
+ ->setTransactionType(
+ PhabricatorCalendarExportNameTransaction::TRANSACTIONTYPE)
+ ->setConduitDescription(pht('Rename the export.'))
+ ->setConduitTypeDescription(pht('New export name.'))
+ ->setValue($object->getName()),
+ id(new PhabricatorBoolEditField())
+ ->setKey('disabled')
+ ->setOptions(pht('Active'), pht('Disabled'))
+ ->setLabel(pht('Disabled'))
+ ->setDescription(pht('Disable the export.'))
+ ->setTransactionType(
+ PhabricatorCalendarExportDisableTransaction::TRANSACTIONTYPE)
+ ->setIsConduitOnly(true)
+ ->setConduitDescription(pht('Disable or restore the export.'))
+ ->setConduitTypeDescription(pht('True to cancel the export.'))
+ ->setValue($object->getIsDisabled()),
+ );
+
+ return $fields;
+ }
+
+
+}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php b/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
@@ -0,0 +1,14 @@
+<?php
+
+final class PhabricatorCalendarExportEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorCalendarApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Calendar Exports');
+ }
+
+}
diff --git a/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php b/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php
@@ -0,0 +1,50 @@
+<?php
+
+final class PhabricatorCalendarExportPHIDType extends PhabricatorPHIDType {
+
+ const TYPECONST = 'CEXP';
+
+ public function getTypeName() {
+ return pht('Calendar Export');
+ }
+
+ public function newObject() {
+ return new PhabricatorCalendarExport();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorCalendarApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorCalendarExportQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $export = $objects[$phid];
+
+ $id = $export->getID();
+ $name = $export->getName();
+ $uri = $export->getURI();
+
+ $handle
+ ->setName($name)
+ ->setFullName(pht('Calendar Export %s: %s', $id, $name))
+ ->setURI($uri);
+
+ if ($export->getIsDisabled()) {
+ $handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
+ }
+ }
+ }
+
+}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportQuery.php b/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
@@ -0,0 +1,81 @@
+<?php
+
+final class PhabricatorCalendarExportQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $authorPHIDs;
+ private $isDisabled;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withAuthorPHIDs(array $phids) {
+ $this->authorPHIDs = $phids;
+ return $this;
+ }
+
+ public function withIsDisabled($is_disabled) {
+ $this->isDisabled = $is_disabled;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorCalendarExport();
+ }
+
+ protected function loadPage() {
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'export.id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'export.phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->authorPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'export.authorPHID IN (%Ls)',
+ $this->authorPHIDs);
+ }
+
+ if ($this->isDisabled !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'export.isDisabled = %d',
+ (int)$this->isDisabled);
+ }
+
+ return $where;
+ }
+
+ protected function getPrimaryTableAlias() {
+ return 'export';
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorCalendarApplication';
+ }
+
+}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
@@ -0,0 +1,109 @@
+<?php
+
+final class PhabricatorCalendarExportSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Calendar Exports');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorCalendarApplication';
+ }
+
+ public function newQuery() {
+ $viewer = $this->requireViewer();
+
+ return id(new PhabricatorCalendarExportQuery())
+ ->withAuthorPHIDs(array($viewer->getPHID()));
+ }
+
+ protected function buildCustomSearchFields() {
+ return array();
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+
+ return $query;
+ }
+
+ protected function getURI($path) {
+ return '/calendar/export/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Exports'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function renderResultList(
+ array $exports,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+
+ assert_instances_of($exports, 'PhabricatorCalendarExport');
+ $viewer = $this->requireViewer();
+
+ $list = new PHUIObjectItemListView();
+ foreach ($exports as $export) {
+ $item = id(new PHUIObjectItemView())
+ ->setViewer($viewer)
+ ->setHeader($export->getName())
+ ->setHref($export->getURI());
+
+ if ($export->getIsDisabled()) {
+ $item->setDisabled(true);
+ }
+
+ $list->addItem($item);
+ }
+
+ $result = new PhabricatorApplicationSearchResultView();
+ $result->setObjectList($list);
+ $result->setNoDataString(pht('No exports found.'));
+
+ return $result;
+ }
+
+ protected function getNewUserBody() {
+ $doc_name = 'Calendar User Guide: Exporting Events';
+ $doc_href = PhabricatorEnv::getDoclink($doc_name);
+
+ $create_button = id(new PHUIButtonView())
+ ->setTag('a')
+ ->setIcon('fa-book white')
+ ->setText($doc_name)
+ ->setHref($doc_href)
+ ->setColor(PHUIButtonView::GREEN);
+
+ $icon = $this->getApplication()->getIcon();
+ $app_name = $this->getApplication()->getName();
+ $view = id(new PHUIBigInfoView())
+ ->setIcon('fa-download')
+ ->setTitle(pht('No Exports Configured'))
+ ->setDescription(
+ pht(
+ 'You have not set up any events for export from Calendar yet. '.
+ 'See the documentation for instructions on how to get started.'))
+ ->addAction($create_button);
+
+ return $view;
+ }
+
+}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarExport.php b/src/applications/calendar/storage/PhabricatorCalendarExport.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/storage/PhabricatorCalendarExport.php
@@ -0,0 +1,144 @@
+<?php
+
+final class PhabricatorCalendarExport extends PhabricatorCalendarDAO
+ implements
+ PhabricatorPolicyInterface,
+ PhabricatorApplicationTransactionInterface,
+ PhabricatorDestructibleInterface {
+
+ protected $name;
+ protected $authorPHID;
+ protected $policyMode;
+ protected $queryKey;
+ protected $secretKey;
+ protected $isDisabled = 0;
+
+ const MODE_PUBLIC = 'public';
+ const MODE_PRIVATE = 'private';
+
+ public static function initializeNewCalendarExport(PhabricatorUser $actor) {
+ return id(new self())
+ ->setAuthorPHID($actor->getPHID())
+ ->setPolicyMode(self::MODE_PRIVATE)
+ ->setIsDisabled(0);
+ }
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'name' => 'text',
+ 'policyMode' => 'text64',
+ 'queryKey' => 'text64',
+ 'secretKey' => 'bytes20',
+ 'isDisabled' => 'bool',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_author' => array(
+ 'columns' => array('authorPHID'),
+ ),
+ 'key_secret' => array(
+ 'columns' => array('secretKey'),
+ 'unique' => true,
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function getPHIDType() {
+ return PhabricatorCalendarExportPHIDType::TYPECONST;
+ }
+
+ public function save() {
+ if (!$this->getSecretKey()) {
+ $this->setSecretKey(Filesystem::readRandomCharacters(20));
+ }
+
+ return parent::save();
+ }
+
+ public function getURI() {
+ $id = $this->getID();
+ return "/calendar/export/{$id}/";
+ }
+
+ private static function getPolicyModeMap() {
+ return array(
+ self::MODE_PUBLIC => array(
+ 'name' => pht('Public'),
+ ),
+ self::MODE_PRIVATE => array(
+ 'name' => pht('Private'),
+ ),
+ );
+ }
+
+ private static function getPolicyModeSpec($const) {
+ return idx(self::getPolicyModeMap(), $const, array());
+ }
+
+ public static function getPolicyModeName($const) {
+ $map = self::getPolicyModeSpec($const);
+ return idx($map, 'name', $const);
+ }
+
+ public static function getPolicyModes() {
+ return array_keys(self::getPolicyModeMap());
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ );
+ }
+
+ public function getPolicy($capability) {
+ return $this->getAuthorPHID();
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return null;
+ }
+
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new PhabricatorCalendarExportEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorCalendarExportTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+
+ return $timeline;
+ }
+
+
+/* -( PhabricatorDestructibleInterface )----------------------------------- */
+
+
+ public function destroyObjectPermanently(
+ PhabricatorDestructionEngine $engine) {
+ $this->delete();
+ }
+
+}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarExportTransaction.php b/src/applications/calendar/storage/PhabricatorCalendarExportTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/storage/PhabricatorCalendarExportTransaction.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorCalendarExportTransaction
+ extends PhabricatorModularTransaction {
+
+ public function getApplicationName() {
+ return 'calendar';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorCalendarExportPHIDType::TYPECONST;
+ }
+
+ public function getBaseTransactionClass() {
+ return 'PhabricatorCalendarExportTransactionType';
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarExportDisableTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarExportDisableTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarExportDisableTransaction.php
@@ -0,0 +1,28 @@
+<?php
+
+final class PhabricatorCalendarExportDisableTransaction
+ extends PhabricatorCalendarExportTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.export.disable';
+
+ public function generateOldValue($object) {
+ return (int)$object->getIsDisabled();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setIsDisabled((int)$value);
+ }
+
+ public function getTitle() {
+ if ($this->getNewValue()) {
+ return pht(
+ '%s disabled this export.',
+ $this->renderAuthor());
+ } else {
+ return pht(
+ '%s enabled this export.',
+ $this->renderAuthor());
+ }
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarExportModeTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarExportModeTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarExportModeTransaction.php
@@ -0,0 +1,54 @@
+<?php
+
+final class PhabricatorCalendarExportModeTransaction
+ extends PhabricatorCalendarExportTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.export.mode';
+
+ public function generateOldValue($object) {
+ return $object->getPolicyMode();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setPolicyMode($value);
+ }
+
+ public function getTitle() {
+ $old_value = $this->getOldValue();
+ $new_value = $this->getNewValue();
+
+ $old_name = PhabricatorCalendarExport::getPolicyModeName($old_value);
+ $new_name = PhabricatorCalendarExport::getPolicyModeName($new_value);
+
+ return pht(
+ '%s changed the policy mode for this export from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderValue($old_name),
+ $this->renderValue($new_name));
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ $valid = PhabricatorCalendarExport::getPolicyModes();
+ $valid = array_fuse($valid);
+
+ foreach ($xactions as $xaction) {
+ $value = $xaction->getNewValue();
+
+ if (isset($valid[$value])) {
+ continue;
+ }
+
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Mode "%s" is not a valid policy mode. Valid modes are: %s.',
+ $value,
+ implode(', ', $valid)),
+ $xaction);
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarExportNameTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarExportNameTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarExportNameTransaction.php
@@ -0,0 +1,35 @@
+<?php
+
+final class PhabricatorCalendarExportNameTransaction
+ extends PhabricatorCalendarExportTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.export.name';
+
+ public function generateOldValue($object) {
+ return $object->getName();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setName($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s renamed this export from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldValue(),
+ $this->renderNewValue());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Calendar exports must have a name.'));
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php
@@ -0,0 +1,51 @@
+<?php
+
+final class PhabricatorCalendarExportQueryKeyTransaction
+ extends PhabricatorCalendarExportTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.export.querykey';
+
+ public function generateOldValue($object) {
+ return $object->getQueryKey();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setQueryKey($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the query for this export.',
+ $this->renderAuthor());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ foreach ($xactions as $xaction) {
+ $value = $xaction->getNewValue();
+
+ $query = id(new PhabricatorSavedQueryQuery())
+ ->withEngineClassNames(array('PhabricatorCalendarEventSearchEngine'))
+ ->withQueryKeys(array($value))
+ ->executeOne();
+ if ($query) {
+ continue;
+ }
+
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Query key "%s" does not identify a valid event query.',
+ $value),
+ $xaction);
+ }
+
+ if ($this->isEmptyTextTransaction($object->getQueryKey(), $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Calendar exports must have a query key.'));
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarExportTransactionType.php b/src/applications/calendar/xaction/PhabricatorCalendarExportTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarExportTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class PhabricatorCalendarExportTransactionType
+ extends PhabricatorModularTransactionType {}
diff --git a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
--- a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
+++ b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
@@ -421,7 +421,7 @@
'you need to get done. Tasks assigned to you will appear here.'))
->addAction($create_button);
- return $view;
+ return $view;
}
}
diff --git a/src/docs/user/userguide/calendar_exports.diviner b/src/docs/user/userguide/calendar_exports.diviner
new file mode 100644
--- /dev/null
+++ b/src/docs/user/userguide/calendar_exports.diviner
@@ -0,0 +1,12 @@
+@title Calendar User Guide: Exporting Events
+@group userguide
+
+Exporting events to other calendars.
+
+Overview
+========
+
+IMPORTANT: Calendar is a prototype application. See
+@{article:User Guide: Prototype Applications}.
+
+Coming soon!
diff --git a/src/infrastructure/storage/lisk/LiskDAO.php b/src/infrastructure/storage/lisk/LiskDAO.php
--- a/src/infrastructure/storage/lisk/LiskDAO.php
+++ b/src/infrastructure/storage/lisk/LiskDAO.php
@@ -1339,11 +1339,12 @@
* @task hook
*/
public function generatePHID() {
- throw new Exception(
- pht(
- 'To use %s, you need to overload %s to perform PHID generation.',
- 'CONFIG_AUX_PHID',
- 'generatePHID()'));
+ $type = $this->getPHIDType();
+ return PhabricatorPHID::generateNewPHID($type);
+ }
+
+ public function getPHIDType() {
+ throw new PhutilMethodNotImplementedException();
}

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 14, 10:12 PM (3 d, 14 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6720778
Default Alt Text
D16675.diff (30 KB)

Event Timeline