From 3d985585937c9ed24f11e03532f1a8ae16aa465a Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 13 Oct 2016 10:45:15 -0700 Subject: [PATCH] Add import log messages to Calendar imports Summary: Ref T10747. When stuff goes wrong (or right) let the user know what happened. Test Plan: {F1870139} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10747 Differential Revision: https://secure.phabricator.com/D16704 --- .../autopatches/20161013.cal.01.importlog.sql | 8 ++ src/__phutil_library_map__.php | 24 ++++ ...habricatorCalendarImportViewController.php | 68 ++++++++++- .../PhabricatorCalendarImportEngine.php | 87 +++++++++++++- ...habricatorCalendarImportDefaultLogType.php | 20 ++++ ...bricatorCalendarImportDuplicateLogType.php | 23 ++++ .../PhabricatorCalendarImportEmptyLogType.php | 32 +++++ ...icatorCalendarImportIgnoredNodeLogType.php | 23 ++++ .../PhabricatorCalendarImportLogType.php | 39 ++++++ ...abricatorCalendarImportOriginalLogType.php | 26 ++++ ...PhabricatorCalendarImportOrphanLogType.php | 25 ++++ ...PhabricatorCalendarImportUpdateLogType.php | 38 ++++++ .../PhabricatorCalendarImportLogQuery.php | 111 ++++++++++++++++++ .../storage/PhabricatorCalendarEvent.php | 4 + .../storage/PhabricatorCalendarImport.php | 20 ++++ .../storage/PhabricatorCalendarImportLog.php | 103 ++++++++++++++++ 16 files changed, 643 insertions(+), 8 deletions(-) create mode 100644 resources/sql/autopatches/20161013.cal.01.importlog.sql create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportIgnoredNodeLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php create mode 100644 src/applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php create mode 100644 src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php create mode 100644 src/applications/calendar/storage/PhabricatorCalendarImportLog.php diff --git a/resources/sql/autopatches/20161013.cal.01.importlog.sql b/resources/sql/autopatches/20161013.cal.01.importlog.sql new file mode 100644 index 0000000000..938f0c8d72 --- /dev/null +++ b/resources/sql/autopatches/20161013.cal.01.importlog.sql @@ -0,0 +1,8 @@ +CREATE TABLE {$NAMESPACE}_calendar.calendar_importlog ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + importPHID VARBINARY(64) NOT NULL, + parameters LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL, + KEY `key_import` (`importPHID`) +) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 34d379c376..02a69fb3aa 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2104,21 +2104,31 @@ phutil_register_library_map(array( 'PhabricatorCalendarICSWriter' => 'applications/calendar/util/PhabricatorCalendarICSWriter.php', 'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php', 'PhabricatorCalendarImport' => 'applications/calendar/storage/PhabricatorCalendarImport.php', + 'PhabricatorCalendarImportDefaultLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php', 'PhabricatorCalendarImportDisableController' => 'applications/calendar/controller/PhabricatorCalendarImportDisableController.php', 'PhabricatorCalendarImportDisableTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportDisableTransaction.php', + 'PhabricatorCalendarImportDuplicateLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php', 'PhabricatorCalendarImportEditController' => 'applications/calendar/controller/PhabricatorCalendarImportEditController.php', 'PhabricatorCalendarImportEditEngine' => 'applications/calendar/editor/PhabricatorCalendarImportEditEngine.php', 'PhabricatorCalendarImportEditor' => 'applications/calendar/editor/PhabricatorCalendarImportEditor.php', + 'PhabricatorCalendarImportEmptyLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php', 'PhabricatorCalendarImportEngine' => 'applications/calendar/import/PhabricatorCalendarImportEngine.php', 'PhabricatorCalendarImportICSFileTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportICSFileTransaction.php', + 'PhabricatorCalendarImportIgnoredNodeLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportIgnoredNodeLogType.php', 'PhabricatorCalendarImportListController' => 'applications/calendar/controller/PhabricatorCalendarImportListController.php', + 'PhabricatorCalendarImportLog' => 'applications/calendar/storage/PhabricatorCalendarImportLog.php', + 'PhabricatorCalendarImportLogQuery' => 'applications/calendar/query/PhabricatorCalendarImportLogQuery.php', + 'PhabricatorCalendarImportLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportLogType.php', 'PhabricatorCalendarImportNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportNameTransaction.php', + 'PhabricatorCalendarImportOriginalLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php', + 'PhabricatorCalendarImportOrphanLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php', 'PhabricatorCalendarImportPHIDType' => 'applications/calendar/phid/PhabricatorCalendarImportPHIDType.php', 'PhabricatorCalendarImportQuery' => 'applications/calendar/query/PhabricatorCalendarImportQuery.php', 'PhabricatorCalendarImportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarImportSearchEngine.php', 'PhabricatorCalendarImportTransaction' => 'applications/calendar/storage/PhabricatorCalendarImportTransaction.php', 'PhabricatorCalendarImportTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarImportTransactionQuery.php', 'PhabricatorCalendarImportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarImportTransactionType.php', + 'PhabricatorCalendarImportUpdateLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php', 'PhabricatorCalendarImportViewController' => 'applications/calendar/controller/PhabricatorCalendarImportViewController.php', 'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php', 'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php', @@ -6921,21 +6931,35 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), + 'PhabricatorCalendarImportDefaultLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportDisableController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportDisableTransaction' => 'PhabricatorCalendarImportTransactionType', + 'PhabricatorCalendarImportDuplicateLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportEditController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportEditEngine' => 'PhabricatorEditEngine', 'PhabricatorCalendarImportEditor' => 'PhabricatorApplicationTransactionEditor', + 'PhabricatorCalendarImportEmptyLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportEngine' => 'Phobject', 'PhabricatorCalendarImportICSFileTransaction' => 'PhabricatorCalendarImportTransactionType', + 'PhabricatorCalendarImportIgnoredNodeLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportListController' => 'PhabricatorCalendarController', + 'PhabricatorCalendarImportLog' => array( + 'PhabricatorCalendarDAO', + 'PhabricatorPolicyInterface', + 'PhabricatorDestructibleInterface', + ), + 'PhabricatorCalendarImportLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorCalendarImportLogType' => 'Phobject', 'PhabricatorCalendarImportNameTransaction' => 'PhabricatorCalendarImportTransactionType', + 'PhabricatorCalendarImportOriginalLogType' => 'PhabricatorCalendarImportLogType', + 'PhabricatorCalendarImportOrphanLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportPHIDType' => 'PhabricatorPHIDType', 'PhabricatorCalendarImportQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarImportSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCalendarImportTransaction' => 'PhabricatorModularTransaction', 'PhabricatorCalendarImportTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorCalendarImportTransactionType' => 'PhabricatorModularTransactionType', + 'PhabricatorCalendarImportUpdateLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportViewController' => 'PhabricatorCalendarController', 'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', diff --git a/src/applications/calendar/controller/PhabricatorCalendarImportViewController.php b/src/applications/calendar/controller/PhabricatorCalendarImportViewController.php index 92da19d61b..5da2be2044 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarImportViewController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarImportViewController.php @@ -30,12 +30,14 @@ final class PhabricatorCalendarImportViewController $curtain = $this->buildCurtain($import); $details = $this->buildPropertySection($import); + $log_messages = $this->buildLogMessages($import); $imported_events = $this->buildImportedEvents($import); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setMainColumn( array( + $log_messages, $imported_events, $timeline, )) @@ -134,8 +136,70 @@ final class PhabricatorCalendarImportViewController return $properties; } - private function buildImportedEvents( - PhabricatorCalendarImport $import) { + private function buildLogMessages(PhabricatorCalendarImport $import) { + $viewer = $this->getViewer(); + + $logs = id(new PhabricatorCalendarImportLogQuery()) + ->setViewer($viewer) + ->withImportPHIDs(array($import->getPHID())) + ->setLimit(25) + ->execute(); + + $rows = array(); + foreach ($logs as $log) { + $icon = $log->getDisplayIcon($viewer); + $color = $log->getDisplayColor($viewer); + $name = $log->getDisplayType($viewer); + $description = $log->getDisplayDescription($viewer); + + $rows[] = array( + $log->getID(), + id(new PHUIIconView())->setIcon($icon, $color), + $name, + $description, + phabricator_datetime($log->getDateCreated(), $viewer), + ); + } + + $table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + pht('ID'), + null, + pht('Type'), + pht('Mesage'), + pht('Date'), + )) + ->setColumnClasses( + array( + null, + null, + 'pri', + 'wide', + null, + )); + + $all_uri = $this->getApplicationURI('import/log/'); + $all_uri = (string)id(new PhutilURI($all_uri)) + ->setQueryParam('importSourcePHID', $import->getPHID()); + + $all_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText(pht('View All')) + ->setIcon('fa-search') + ->setHref($all_uri); + + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Log Messages')) + ->addActionLink($all_button); + + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->setTable($table); + } + + private function buildImportedEvents(PhabricatorCalendarImport $import) { $viewer = $this->getViewer(); $engine = id(new PhabricatorCalendarEventSearchEngine()) diff --git a/src/applications/calendar/import/PhabricatorCalendarImportEngine.php b/src/applications/calendar/import/PhabricatorCalendarImportEngine.php index e6242762ff..14c96a76ae 100644 --- a/src/applications/calendar/import/PhabricatorCalendarImportEngine.php +++ b/src/applications/calendar/import/PhabricatorCalendarImportEngine.php @@ -49,8 +49,13 @@ abstract class PhabricatorCalendarImportEngine $nodes = array(); foreach ($root->getChildren() as $document) { foreach ($document->getChildren() as $node) { - if ($node->getNodeType() != $event_type) { - // TODO: Warn that we ignored this. + $node_type = $node->getNodeType(); + if ($node_type != $event_type) { + $import->newLogMessage( + PhabricatorCalendarImportIgnoredNodeLogType::LOGTYPE, + array( + 'node.type' => $node_type, + )); continue; } @@ -59,16 +64,62 @@ abstract class PhabricatorCalendarImportEngine } $node_map = array(); - $parent_uids = array(); foreach ($nodes as $node) { $full_uid = $this->getFullNodeUID($node); if (isset($node_map[$full_uid])) { - // TODO: Warn that we got a duplicate. + $import->newLogMessage( + PhabricatorCalendarImportDuplicateLogType::LOGTYPE, + array( + 'uid.full' => $full_uid, + )); continue; } $node_map[$full_uid] = $node; } + // If we already know about some of these events and they were created + // here, we're not going to import it again. This can happen if a user + // exports an event and then tries to import it again. This is probably + // not what they meant to do and this pathway generally leads to madness. + $likely_phids = array(); + foreach ($node_map as $full_uid => $node) { + $uid = $node->getUID(); + $matches = null; + if (preg_match('/^(PHID-.*)@(.*)\z/', $uid, $matches)) { + $likely_phids[$full_uid] = $matches[1]; + } + } + + if ($likely_phids) { + // NOTE: We're using the omnipotent viewer here because we don't want + // to collide with events that already exist, even if you can't see + // them. + $events = id(new PhabricatorCalendarEventQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withPHIDs($likely_phids) + ->execute(); + $events = mpull($events, null, 'getPHID'); + foreach ($node_map as $full_uid => $node) { + $phid = idx($likely_phids, $full_uid); + if (!$phid) { + continue; + } + + $event = idx($events, $phid); + if (!$event) { + continue; + } + + $import->newLogMessage( + PhabricatorCalendarImportOriginalLogType::LOGTYPE, + array( + 'phid' => $event->getPHID(), + )); + + unset($node_map[$full_uid]); + } + } + if ($node_map) { $events = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) @@ -114,7 +165,12 @@ abstract class PhabricatorCalendarImportEngine // does not exist or we're going to delete it anyway. We just drop // this node. - // TODO: Warn that we got rid of an event with no parent. + $import->newLogMessage( + PhabricatorCalendarImportOrphanLogType::LOGTYPE, + array( + 'uid.full' => $full_uid, + 'uid.parent' => $parent_uid, + )); continue; } @@ -130,6 +186,10 @@ abstract class PhabricatorCalendarImportEngine $content_source = PhabricatorContentSource::newForSource( PhabricatorWebContentSource::SOURCECONST); + // NOTE: We're using the omnipotent user here because imported events are + // otherwise immutable. + $edit_actor = PhabricatorUser::getOmnipotentUser(); + $update_map = array_select_keys($update_map, $insert_order); foreach ($update_map as $full_uid => $event) { $parent_uid = $this->getParentNodeUID($node_map[$full_uid]); @@ -144,13 +204,28 @@ abstract class PhabricatorCalendarImportEngine $event_xactions = $xactions[$full_uid]; $editor = id(new PhabricatorCalendarEventEditor()) - ->setActor($viewer) + ->setActor($edit_actor) ->setActingAsPHID($import->getPHID()) ->setContentSource($content_source) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true); + $is_new = !$event->getID(); + $editor->applyTransactions($event, $event_xactions); + + $import->newLogMessage( + PhabricatorCalendarImportUpdateLogType::LOGTYPE, + array( + 'new' => $is_new, + 'phid' => $event->getPHID(), + )); + } + + if (!$update_map) { + $import->newLogMessage( + PhabricatorCalendarImportEmptyLogType::LOGTYPE, + array()); } // TODO: When the source is a subscription-based ICS file or some other diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php new file mode 100644 index 0000000000..4e61e3f94f --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php @@ -0,0 +1,20 @@ +getParameter('type'); + if (strlen($type)) { + return pht('Unknown Message "%s"', $type); + } else { + return pht('Unknown Message'); + } + } + +} diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php new file mode 100644 index 0000000000..0f72932404 --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php @@ -0,0 +1,23 @@ +getParameter('uid.full'); + return pht( + 'Ignored duplicate event "%s" present in source.', + $duplicate_uid); + } + +} diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php new file mode 100644 index 0000000000..5a540645ba --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php @@ -0,0 +1,32 @@ +getParameter('node.type'); + return pht( + 'Ignored unsupported "%s" node present in source.', + $node_type); + } + +} diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportLogType.php new file mode 100644 index 0000000000..a6c4ca4ec3 --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportLogType.php @@ -0,0 +1,39 @@ +getPhobjectClassConstant('LOGTYPE', 64); + } + + final public static function getAllLogTypes() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getLogTypeConstant') + ->execute(); + } + + abstract public function getDisplayType( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log); + + public function getDisplayIcon( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log) { + return 'fa-warning'; + } + + public function getDisplayColor( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log) { + return 'yellow'; + } + + public function getDisplayDescription( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log) { + return null; + } + +} diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php new file mode 100644 index 0000000000..567cc5f68e --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php @@ -0,0 +1,26 @@ +getParameter('phid'); + + return pht( + 'Ignored an event (%s) because the original version of this event '. + 'was created here.', + $viewer->renderHandle($phid)); + } + +} diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php new file mode 100644 index 0000000000..236b0e7f65 --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php @@ -0,0 +1,25 @@ +getParameter('uid.full'); + $parent_uid = $log->getParameter('uid.parent'); + return pht( + 'Found orphaned child event ("%s") without a parent event ("%s").', + $child_uid, + $parent_uid); + } + +} diff --git a/src/applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php b/src/applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php new file mode 100644 index 0000000000..9b20c54615 --- /dev/null +++ b/src/applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php @@ -0,0 +1,38 @@ +getParameter('new'); + if ($is_new) { + return pht('Imported Event'); + } else { + return pht('Updated Event'); + } + } + + public function getDisplayDescription( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log) { + $event_phid = $log->getParameter('phid'); + return $viewer->renderHandle($event_phid); + } + + public function getDisplayIcon( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log) { + return 'fa-upload'; + } + + public function getDisplayColor( + PhabricatorUser $viewer, + PhabricatorCalendarImportLog $log) { + return 'green'; + } + +} diff --git a/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php b/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php new file mode 100644 index 0000000000..81f309bdca --- /dev/null +++ b/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php @@ -0,0 +1,111 @@ +ids = $ids; + return $this; + } + + public function withPHIDs(array $phids) { + $this->phids = $phids; + return $this; + } + + public function withImportPHIDs(array $phids) { + $this->importPHIDs = $phids; + return $this; + } + + public function newResultObject() { + return new PhabricatorCalendarImportLog(); + } + + protected function loadPage() { + return $this->loadStandardPage($this->newResultObject()); + } + + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { + $where = parent::buildWhereClauseParts($conn); + + if ($this->ids !== null) { + $where[] = qsprintf( + $conn, + 'log.id IN (%Ld)', + $this->ids); + } + + if ($this->phids !== null) { + $where[] = qsprintf( + $conn, + 'log.phid IN (%Ls)', + $this->phids); + } + + if ($this->importPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'log.importPHID IN (%Ls)', + $this->importPHIDs); + } + + + return $where; + } + + protected function willFilterPage(array $page) { + $viewer = $this->getViewer(); + + $type_map = PhabricatorCalendarImportLogType::getAllLogTypes(); + foreach ($page as $log) { + $type_constant = $log->getParameter('type'); + + $type_object = idx($type_map, $type_constant); + if (!$type_object) { + $type_object = new PhabricatorCalendarImportDefaultLogType(); + } + + $type_object = clone $type_object; + $log->attachLogType($type_object); + } + + $import_phids = mpull($page, 'getImportPHID'); + + if ($import_phids) { + $imports = id(new PhabricatorCalendarImportQuery()) + ->setViewer($viewer) + ->withPHIDs($import_phids) + ->execute(); + $imports = mpull($imports, null, 'getPHID'); + } else { + $imports = array(); + } + + foreach ($page as $key => $log) { + $import = idx($imports, $log->getImportPHID()); + if (!$import) { + $this->didRejectResult($import); + unset($page[$key]); + continue; + } + + $log->attachImport($import); + } + + return $page; + } + + protected function getPrimaryTableAlias() { + return 'log'; + } + + public function getQueryApplicationClass() { + return 'PhabricatorCalendarApplication'; + } + +} diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php index 2cf9e4117c..7ad6d85881 100644 --- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php +++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php @@ -907,6 +907,10 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO return $set; } + public function isImportedEvent() { + return (bool)$this->getImportSourcePHID(); + } + public function getImportSource() { return $this->assertAttached($this->importSource); } diff --git a/src/applications/calendar/storage/PhabricatorCalendarImport.php b/src/applications/calendar/storage/PhabricatorCalendarImport.php index 18c113a5c6..b1d0ddf58b 100644 --- a/src/applications/calendar/storage/PhabricatorCalendarImport.php +++ b/src/applications/calendar/storage/PhabricatorCalendarImport.php @@ -133,6 +133,17 @@ final class PhabricatorCalendarImport return $timeline; } + public function newLogMessage($type, array $parameters) { + $parameters = array( + 'type' => $type, + ) + $parameters; + + return id(new PhabricatorCalendarImportLog()) + ->setImportPHID($this->getPHID()) + ->setParameters($parameters) + ->save(); + } + /* -( PhabricatorDestructibleInterface )----------------------------------- */ @@ -144,12 +155,21 @@ final class PhabricatorCalendarImport $this->openTransaction(); $events = id(new PhabricatorCalendarEventQuery()) + ->setViewer($viewer) ->withImportSourcePHIDs(array($this->getPHID())) ->execute(); foreach ($events as $event) { $engine->destroyObject($event); } + $logs = id(new PhabricatorCalendarImportLogQuery()) + ->setViewer($viewer) + ->withImportPHIDs(array($this->getPHID())) + ->execute(); + foreach ($logs as $log) { + $engine->destroyObject($log); + } + $this->delete(); $this->saveTransaction(); } diff --git a/src/applications/calendar/storage/PhabricatorCalendarImportLog.php b/src/applications/calendar/storage/PhabricatorCalendarImportLog.php new file mode 100644 index 0000000000..e25a3090e0 --- /dev/null +++ b/src/applications/calendar/storage/PhabricatorCalendarImportLog.php @@ -0,0 +1,103 @@ + array( + 'parameters' => self::SERIALIZATION_JSON, + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_import' => array( + 'columns' => array('importPHID'), + ), + ), + ) + parent::getConfiguration(); + } + + public function getParameter($key, $default = null) { + return idx($this->parameters, $key, $default); + } + + public function setParameter($key, $value) { + $this->parameters[$key] = $value; + return $this; + } + + public function getImport() { + return $this->assertAttached($this->import); + } + + public function attachImport(PhabricatorCalendarImport $import) { + $this->import = $import; + return $this; + } + + public function getDisplayIcon(PhabricatorUser $viewer) { + return $this->getLogType()->getDisplayIcon($viewer, $this); + } + + public function getDisplayColor(PhabricatorUser $viewer) { + return $this->getLogType()->getDisplayColor($viewer, $this); + } + + public function getDisplayType(PhabricatorUser $viewer) { + return $this->getLogType()->getDisplayType($viewer, $this); + } + + public function getDisplayDescription(PhabricatorUser $viewer) { + return $this->getLogType()->getDisplayDescription($viewer, $this); + } + + public function getLogType() { + return $this->assertAttached($this->logType); + } + + public function attachLogType(PhabricatorCalendarImportLogType $type) { + $this->logType = $type; + return $this; + } + + +/* -( PhabricatorPolicyInterface )----------------------------------------- */ + + + public function getCapabilities() { + return array( + PhabricatorPolicyCapability::CAN_VIEW, + ); + } + + public function getPolicy($capability) { + return PhabricatorPolicies::getMostOpenPolicy(); + } + + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { + return false; + } + + public function describeAutomaticCapability($capability) { + return null; + } + + +/* -( PhabricatorDestructibleInterface )----------------------------------- */ + + + public function destroyObjectPermanently( + PhabricatorDestructionEngine $engine) { + $viewer = $engine->getViewer(); + $this->delete(); + } + +} -- 2.51.2