mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-26 15:30:58 +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',
|
||||
'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',
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
public function isImportedEvent() {
|
||||
return (bool)$this->getImportSourcePHID();
|
||||
}
|
||||
|
||||
public function getImportSource() {
|
||||
return $this->assertAttached($this->importSource);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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