mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 23:02:42 +01:00
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
This commit is contained in:
parent
c71bb0550c
commit
3d98558593
16 changed files with 643 additions and 8 deletions
8
resources/sql/autopatches/20161013.cal.01.importlog.sql
Normal file
8
resources/sql/autopatches/20161013.cal.01.importlog.sql
Normal file
|
@ -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};
|
|
@ -2104,21 +2104,31 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCalendarICSWriter' => 'applications/calendar/util/PhabricatorCalendarICSWriter.php',
|
'PhabricatorCalendarICSWriter' => 'applications/calendar/util/PhabricatorCalendarICSWriter.php',
|
||||||
'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php',
|
'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php',
|
||||||
'PhabricatorCalendarImport' => 'applications/calendar/storage/PhabricatorCalendarImport.php',
|
'PhabricatorCalendarImport' => 'applications/calendar/storage/PhabricatorCalendarImport.php',
|
||||||
|
'PhabricatorCalendarImportDefaultLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php',
|
||||||
'PhabricatorCalendarImportDisableController' => 'applications/calendar/controller/PhabricatorCalendarImportDisableController.php',
|
'PhabricatorCalendarImportDisableController' => 'applications/calendar/controller/PhabricatorCalendarImportDisableController.php',
|
||||||
'PhabricatorCalendarImportDisableTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportDisableTransaction.php',
|
'PhabricatorCalendarImportDisableTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportDisableTransaction.php',
|
||||||
|
'PhabricatorCalendarImportDuplicateLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php',
|
||||||
'PhabricatorCalendarImportEditController' => 'applications/calendar/controller/PhabricatorCalendarImportEditController.php',
|
'PhabricatorCalendarImportEditController' => 'applications/calendar/controller/PhabricatorCalendarImportEditController.php',
|
||||||
'PhabricatorCalendarImportEditEngine' => 'applications/calendar/editor/PhabricatorCalendarImportEditEngine.php',
|
'PhabricatorCalendarImportEditEngine' => 'applications/calendar/editor/PhabricatorCalendarImportEditEngine.php',
|
||||||
'PhabricatorCalendarImportEditor' => 'applications/calendar/editor/PhabricatorCalendarImportEditor.php',
|
'PhabricatorCalendarImportEditor' => 'applications/calendar/editor/PhabricatorCalendarImportEditor.php',
|
||||||
|
'PhabricatorCalendarImportEmptyLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php',
|
||||||
'PhabricatorCalendarImportEngine' => 'applications/calendar/import/PhabricatorCalendarImportEngine.php',
|
'PhabricatorCalendarImportEngine' => 'applications/calendar/import/PhabricatorCalendarImportEngine.php',
|
||||||
'PhabricatorCalendarImportICSFileTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportICSFileTransaction.php',
|
'PhabricatorCalendarImportICSFileTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportICSFileTransaction.php',
|
||||||
|
'PhabricatorCalendarImportIgnoredNodeLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportIgnoredNodeLogType.php',
|
||||||
'PhabricatorCalendarImportListController' => 'applications/calendar/controller/PhabricatorCalendarImportListController.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',
|
'PhabricatorCalendarImportNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportNameTransaction.php',
|
||||||
|
'PhabricatorCalendarImportOriginalLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php',
|
||||||
|
'PhabricatorCalendarImportOrphanLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php',
|
||||||
'PhabricatorCalendarImportPHIDType' => 'applications/calendar/phid/PhabricatorCalendarImportPHIDType.php',
|
'PhabricatorCalendarImportPHIDType' => 'applications/calendar/phid/PhabricatorCalendarImportPHIDType.php',
|
||||||
'PhabricatorCalendarImportQuery' => 'applications/calendar/query/PhabricatorCalendarImportQuery.php',
|
'PhabricatorCalendarImportQuery' => 'applications/calendar/query/PhabricatorCalendarImportQuery.php',
|
||||||
'PhabricatorCalendarImportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarImportSearchEngine.php',
|
'PhabricatorCalendarImportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarImportSearchEngine.php',
|
||||||
'PhabricatorCalendarImportTransaction' => 'applications/calendar/storage/PhabricatorCalendarImportTransaction.php',
|
'PhabricatorCalendarImportTransaction' => 'applications/calendar/storage/PhabricatorCalendarImportTransaction.php',
|
||||||
'PhabricatorCalendarImportTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarImportTransactionQuery.php',
|
'PhabricatorCalendarImportTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarImportTransactionQuery.php',
|
||||||
'PhabricatorCalendarImportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarImportTransactionType.php',
|
'PhabricatorCalendarImportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarImportTransactionType.php',
|
||||||
|
'PhabricatorCalendarImportUpdateLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php',
|
||||||
'PhabricatorCalendarImportViewController' => 'applications/calendar/controller/PhabricatorCalendarImportViewController.php',
|
'PhabricatorCalendarImportViewController' => 'applications/calendar/controller/PhabricatorCalendarImportViewController.php',
|
||||||
'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php',
|
'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php',
|
||||||
'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php',
|
'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php',
|
||||||
|
@ -6921,21 +6931,35 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
'PhabricatorDestructibleInterface',
|
'PhabricatorDestructibleInterface',
|
||||||
),
|
),
|
||||||
|
'PhabricatorCalendarImportDefaultLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
'PhabricatorCalendarImportDisableController' => 'PhabricatorCalendarController',
|
'PhabricatorCalendarImportDisableController' => 'PhabricatorCalendarController',
|
||||||
'PhabricatorCalendarImportDisableTransaction' => 'PhabricatorCalendarImportTransactionType',
|
'PhabricatorCalendarImportDisableTransaction' => 'PhabricatorCalendarImportTransactionType',
|
||||||
|
'PhabricatorCalendarImportDuplicateLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
'PhabricatorCalendarImportEditController' => 'PhabricatorCalendarController',
|
'PhabricatorCalendarImportEditController' => 'PhabricatorCalendarController',
|
||||||
'PhabricatorCalendarImportEditEngine' => 'PhabricatorEditEngine',
|
'PhabricatorCalendarImportEditEngine' => 'PhabricatorEditEngine',
|
||||||
'PhabricatorCalendarImportEditor' => 'PhabricatorApplicationTransactionEditor',
|
'PhabricatorCalendarImportEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
|
'PhabricatorCalendarImportEmptyLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
'PhabricatorCalendarImportEngine' => 'Phobject',
|
'PhabricatorCalendarImportEngine' => 'Phobject',
|
||||||
'PhabricatorCalendarImportICSFileTransaction' => 'PhabricatorCalendarImportTransactionType',
|
'PhabricatorCalendarImportICSFileTransaction' => 'PhabricatorCalendarImportTransactionType',
|
||||||
|
'PhabricatorCalendarImportIgnoredNodeLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
'PhabricatorCalendarImportListController' => 'PhabricatorCalendarController',
|
'PhabricatorCalendarImportListController' => 'PhabricatorCalendarController',
|
||||||
|
'PhabricatorCalendarImportLog' => array(
|
||||||
|
'PhabricatorCalendarDAO',
|
||||||
|
'PhabricatorPolicyInterface',
|
||||||
|
'PhabricatorDestructibleInterface',
|
||||||
|
),
|
||||||
|
'PhabricatorCalendarImportLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'PhabricatorCalendarImportLogType' => 'Phobject',
|
||||||
'PhabricatorCalendarImportNameTransaction' => 'PhabricatorCalendarImportTransactionType',
|
'PhabricatorCalendarImportNameTransaction' => 'PhabricatorCalendarImportTransactionType',
|
||||||
|
'PhabricatorCalendarImportOriginalLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
|
'PhabricatorCalendarImportOrphanLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
'PhabricatorCalendarImportPHIDType' => 'PhabricatorPHIDType',
|
'PhabricatorCalendarImportPHIDType' => 'PhabricatorPHIDType',
|
||||||
'PhabricatorCalendarImportQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorCalendarImportQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorCalendarImportSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhabricatorCalendarImportSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
'PhabricatorCalendarImportTransaction' => 'PhabricatorModularTransaction',
|
'PhabricatorCalendarImportTransaction' => 'PhabricatorModularTransaction',
|
||||||
'PhabricatorCalendarImportTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'PhabricatorCalendarImportTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhabricatorCalendarImportTransactionType' => 'PhabricatorModularTransactionType',
|
'PhabricatorCalendarImportTransactionType' => 'PhabricatorModularTransactionType',
|
||||||
|
'PhabricatorCalendarImportUpdateLogType' => 'PhabricatorCalendarImportLogType',
|
||||||
'PhabricatorCalendarImportViewController' => 'PhabricatorCalendarController',
|
'PhabricatorCalendarImportViewController' => 'PhabricatorCalendarController',
|
||||||
'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||||
'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
||||||
|
|
|
@ -30,12 +30,14 @@ final class PhabricatorCalendarImportViewController
|
||||||
$curtain = $this->buildCurtain($import);
|
$curtain = $this->buildCurtain($import);
|
||||||
$details = $this->buildPropertySection($import);
|
$details = $this->buildPropertySection($import);
|
||||||
|
|
||||||
|
$log_messages = $this->buildLogMessages($import);
|
||||||
$imported_events = $this->buildImportedEvents($import);
|
$imported_events = $this->buildImportedEvents($import);
|
||||||
|
|
||||||
$view = id(new PHUITwoColumnView())
|
$view = id(new PHUITwoColumnView())
|
||||||
->setHeader($header)
|
->setHeader($header)
|
||||||
->setMainColumn(
|
->setMainColumn(
|
||||||
array(
|
array(
|
||||||
|
$log_messages,
|
||||||
$imported_events,
|
$imported_events,
|
||||||
$timeline,
|
$timeline,
|
||||||
))
|
))
|
||||||
|
@ -134,8 +136,70 @@ final class PhabricatorCalendarImportViewController
|
||||||
return $properties;
|
return $properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildImportedEvents(
|
private function buildLogMessages(PhabricatorCalendarImport $import) {
|
||||||
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();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$engine = id(new PhabricatorCalendarEventSearchEngine())
|
$engine = id(new PhabricatorCalendarEventSearchEngine())
|
||||||
|
|
|
@ -49,8 +49,13 @@ abstract class PhabricatorCalendarImportEngine
|
||||||
$nodes = array();
|
$nodes = array();
|
||||||
foreach ($root->getChildren() as $document) {
|
foreach ($root->getChildren() as $document) {
|
||||||
foreach ($document->getChildren() as $node) {
|
foreach ($document->getChildren() as $node) {
|
||||||
if ($node->getNodeType() != $event_type) {
|
$node_type = $node->getNodeType();
|
||||||
// TODO: Warn that we ignored this.
|
if ($node_type != $event_type) {
|
||||||
|
$import->newLogMessage(
|
||||||
|
PhabricatorCalendarImportIgnoredNodeLogType::LOGTYPE,
|
||||||
|
array(
|
||||||
|
'node.type' => $node_type,
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,16 +64,62 @@ abstract class PhabricatorCalendarImportEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
$node_map = array();
|
$node_map = array();
|
||||||
$parent_uids = array();
|
|
||||||
foreach ($nodes as $node) {
|
foreach ($nodes as $node) {
|
||||||
$full_uid = $this->getFullNodeUID($node);
|
$full_uid = $this->getFullNodeUID($node);
|
||||||
if (isset($node_map[$full_uid])) {
|
if (isset($node_map[$full_uid])) {
|
||||||
// TODO: Warn that we got a duplicate.
|
$import->newLogMessage(
|
||||||
|
PhabricatorCalendarImportDuplicateLogType::LOGTYPE,
|
||||||
|
array(
|
||||||
|
'uid.full' => $full_uid,
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$node_map[$full_uid] = $node;
|
$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) {
|
if ($node_map) {
|
||||||
$events = id(new PhabricatorCalendarEventQuery())
|
$events = id(new PhabricatorCalendarEventQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
|
@ -114,7 +165,12 @@ abstract class PhabricatorCalendarImportEngine
|
||||||
// does not exist or we're going to delete it anyway. We just drop
|
// does not exist or we're going to delete it anyway. We just drop
|
||||||
// this node.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +186,10 @@ abstract class PhabricatorCalendarImportEngine
|
||||||
$content_source = PhabricatorContentSource::newForSource(
|
$content_source = PhabricatorContentSource::newForSource(
|
||||||
PhabricatorWebContentSource::SOURCECONST);
|
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);
|
$update_map = array_select_keys($update_map, $insert_order);
|
||||||
foreach ($update_map as $full_uid => $event) {
|
foreach ($update_map as $full_uid => $event) {
|
||||||
$parent_uid = $this->getParentNodeUID($node_map[$full_uid]);
|
$parent_uid = $this->getParentNodeUID($node_map[$full_uid]);
|
||||||
|
@ -144,13 +204,28 @@ abstract class PhabricatorCalendarImportEngine
|
||||||
$event_xactions = $xactions[$full_uid];
|
$event_xactions = $xactions[$full_uid];
|
||||||
|
|
||||||
$editor = id(new PhabricatorCalendarEventEditor())
|
$editor = id(new PhabricatorCalendarEventEditor())
|
||||||
->setActor($viewer)
|
->setActor($edit_actor)
|
||||||
->setActingAsPHID($import->getPHID())
|
->setActingAsPHID($import->getPHID())
|
||||||
->setContentSource($content_source)
|
->setContentSource($content_source)
|
||||||
->setContinueOnNoEffect(true)
|
->setContinueOnNoEffect(true)
|
||||||
->setContinueOnMissingFields(true);
|
->setContinueOnMissingFields(true);
|
||||||
|
|
||||||
|
$is_new = !$event->getID();
|
||||||
|
|
||||||
$editor->applyTransactions($event, $event_xactions);
|
$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
|
// TODO: When the source is a subscription-based ICS file or some other
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportDefaultLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'default';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
|
||||||
|
$type = $log->getParameter('type');
|
||||||
|
if (strlen($type)) {
|
||||||
|
return pht('Unknown Message "%s"', $type);
|
||||||
|
} else {
|
||||||
|
return pht('Unknown Message');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportDuplicateLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'duplicate';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return pht('Duplicate Event');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayDescription(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
$duplicate_uid = $log->getParameter('uid.full');
|
||||||
|
return pht(
|
||||||
|
'Ignored duplicate event "%s" present in source.',
|
||||||
|
$duplicate_uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportEmptyLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'empty';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return pht('No Events Imported');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayDescription(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return pht('Found no valid events to import.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayIcon(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return 'fa-ban';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayColor(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return 'red';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportIgnoredNodeLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'nodetype';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return pht('Ignored Node');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayDescription(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
$node_type = $log->getParameter('node.type');
|
||||||
|
return pht(
|
||||||
|
'Ignored unsupported "%s" node present in source.',
|
||||||
|
$node_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorCalendarImportLogType
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
final public function getLogTypeConstant() {
|
||||||
|
return $this->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportOriginalLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'original';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return pht('Original Event');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayDescription(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
|
||||||
|
$phid = $log->getParameter('phid');
|
||||||
|
|
||||||
|
return pht(
|
||||||
|
'Ignored an event (%s) because the original version of this event '.
|
||||||
|
'was created here.',
|
||||||
|
$viewer->renderHandle($phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportOrphanLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'orphan';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
return pht('Orphan');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayDescription(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
$child_uid = $log->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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportUpdateLogType
|
||||||
|
extends PhabricatorCalendarImportLogType {
|
||||||
|
|
||||||
|
const LOGTYPE = 'update';
|
||||||
|
|
||||||
|
public function getDisplayType(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorCalendarImportLog $log) {
|
||||||
|
$is_new = $log->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';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportLogQuery
|
||||||
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
private $ids;
|
||||||
|
private $phids;
|
||||||
|
private $importPHIDs;
|
||||||
|
|
||||||
|
public function withIDs(array $ids) {
|
||||||
|
$this->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';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -907,6 +907,10 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
return $set;
|
return $set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isImportedEvent() {
|
||||||
|
return (bool)$this->getImportSourcePHID();
|
||||||
|
}
|
||||||
|
|
||||||
public function getImportSource() {
|
public function getImportSource() {
|
||||||
return $this->assertAttached($this->importSource);
|
return $this->assertAttached($this->importSource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,17 @@ final class PhabricatorCalendarImport
|
||||||
return $timeline;
|
return $timeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newLogMessage($type, array $parameters) {
|
||||||
|
$parameters = array(
|
||||||
|
'type' => $type,
|
||||||
|
) + $parameters;
|
||||||
|
|
||||||
|
return id(new PhabricatorCalendarImportLog())
|
||||||
|
->setImportPHID($this->getPHID())
|
||||||
|
->setParameters($parameters)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
||||||
|
|
||||||
|
@ -144,12 +155,21 @@ final class PhabricatorCalendarImport
|
||||||
$this->openTransaction();
|
$this->openTransaction();
|
||||||
|
|
||||||
$events = id(new PhabricatorCalendarEventQuery())
|
$events = id(new PhabricatorCalendarEventQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
->withImportSourcePHIDs(array($this->getPHID()))
|
->withImportSourcePHIDs(array($this->getPHID()))
|
||||||
->execute();
|
->execute();
|
||||||
foreach ($events as $event) {
|
foreach ($events as $event) {
|
||||||
$engine->destroyObject($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->delete();
|
||||||
$this->saveTransaction();
|
$this->saveTransaction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarImportLog
|
||||||
|
extends PhabricatorCalendarDAO
|
||||||
|
implements
|
||||||
|
PhabricatorPolicyInterface,
|
||||||
|
PhabricatorDestructibleInterface {
|
||||||
|
|
||||||
|
protected $importPHID;
|
||||||
|
protected $parameters = array();
|
||||||
|
|
||||||
|
private $import = self::ATTACHABLE;
|
||||||
|
private $logType = self::ATTACHABLE;
|
||||||
|
|
||||||
|
protected function getConfiguration() {
|
||||||
|
return array(
|
||||||
|
self::CONFIG_SERIALIZATION => 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue