Page MenuHomePhabricator

D15511.id37407.diff
No OneTemporary

D15511.id37407.diff

diff --git a/src/applications/doorkeeper/bridge/DoorkeeperBridgeGitHubIssue.php b/src/applications/doorkeeper/bridge/DoorkeeperBridgeGitHubIssue.php
--- a/src/applications/doorkeeper/bridge/DoorkeeperBridgeGitHubIssue.php
+++ b/src/applications/doorkeeper/bridge/DoorkeeperBridgeGitHubIssue.php
@@ -76,9 +76,6 @@
$ref->setAttribute('name', $body['title']);
$obj = $ref->getExternalObject();
- if ($obj->getID()) {
- continue;
- }
$this->fillObjectFromData($obj, $result);
@@ -92,6 +89,19 @@
$body = $result->getBody();
$uri = $body['html_url'];
$obj->setObjectURI($uri);
+
+ $title = idx($body, 'title');
+ $description = idx($body, 'body');
+
+ $created = idx($body, 'created_at');
+ $created = strtotime($created);
+
+ $state = idx($body, 'state');
+
+ $obj->setProperty('task.title', $title);
+ $obj->setProperty('task.description', $description);
+ $obj->setProperty('task.created', $created);
+ $obj->setProperty('task.state', $state);
}
}
diff --git a/src/applications/nuance/github/NuanceGitHubRawEvent.php b/src/applications/nuance/github/NuanceGitHubRawEvent.php
--- a/src/applications/nuance/github/NuanceGitHubRawEvent.php
+++ b/src/applications/nuance/github/NuanceGitHubRawEvent.php
@@ -90,6 +90,10 @@
return null;
}
+ public function getComment() {
+ return 'TODO: Actually extract comment text.';
+ }
+
public function getURI() {
$raw = $this->raw;
diff --git a/src/applications/nuance/item/NuanceGitHubEventItemType.php b/src/applications/nuance/item/NuanceGitHubEventItemType.php
--- a/src/applications/nuance/item/NuanceGitHubEventItemType.php
+++ b/src/applications/nuance/item/NuanceGitHubEventItemType.php
@@ -5,6 +5,8 @@
const ITEMTYPE = 'github.event';
+ private $externalObject;
+
public function getItemTypeDisplayName() {
return pht('GitHub Event');
}
@@ -79,29 +81,13 @@
// TODO: Link up the requestor, etc.
- $source = $item->getSource();
- $token = $source->getSourceProperty('github.token');
- $token = new PhutilOpaqueEnvelope($token);
+ $is_dirty = false;
- $ref = $this->getDoorkeeperRef($item);
- if ($ref) {
- $ref = id(new DoorkeeperImportEngine())
- ->setViewer($viewer)
- ->setRefs(array($ref))
- ->setThrowOnMissingLink(true)
- ->setContextProperty('github.token', $token)
- ->executeOne();
-
- if ($ref->getSyncFailed()) {
- $xobj = null;
- } else {
- $xobj = $ref->getExternalObject();
- }
+ $xobj = $this->reloadExternalObject($item);
- if ($xobj) {
- $item->setItemProperty('doorkeeper.xobj.phid', $xobj->getPHID());
- $is_dirty = true;
- }
+ if ($xobj) {
+ $item->setItemProperty('doorkeeper.xobj.phid', $xobj->getPHID());
+ $is_dirty = true;
}
if ($item->getStatus() == NuanceItem::STATUS_IMPORTING) {
@@ -137,6 +123,56 @@
->setObjectID($full_ref);
}
+ private function reloadExternalObject(NuanceItem $item, $local = false) {
+ $ref = $this->getDoorkeeperRef($item);
+ if (!$ref) {
+ return null;
+ }
+
+ $source = $item->getSource();
+ $token = $source->getSourceProperty('github.token');
+ $token = new PhutilOpaqueEnvelope($token);
+
+ $viewer = $this->getViewer();
+
+ $ref = id(new DoorkeeperImportEngine())
+ ->setViewer($viewer)
+ ->setRefs(array($ref))
+ ->setThrowOnMissingLink(true)
+ ->setContextProperty('github.token', $token)
+ ->needLocalOnly($local)
+ ->executeOne();
+
+ if ($ref->getSyncFailed()) {
+ $xobj = null;
+ } else {
+ $xobj = $ref->getExternalObject();
+ }
+
+ if ($xobj) {
+ $this->externalObject = $xobj;
+ }
+
+ return $xobj;
+ }
+
+ private function getExternalObject(NuanceItem $item) {
+ if ($this->externalObject === null) {
+ $xobj = $this->reloadExternalObject($item, $local = true);
+ if ($xobj) {
+ $this->externalObject = $xobj;
+ } else {
+ $this->externalObject = false;
+ }
+ }
+
+ if ($this->externalObject) {
+ return $this->externalObject;
+ }
+
+ return null;
+ }
+
private function newRawEvent(NuanceItem $item) {
$type = $item->getItemProperty('api.type');
$raw = $item->getItemProperty('api.raw', array());
@@ -147,6 +183,15 @@
public function getItemActions(NuanceItem $item) {
$actions = array();
+ $xobj = $this->getExternalObject($item);
+ if ($xobj) {
+ $actions[] = $this->newItemAction($item, 'reload')
+ ->setName(pht('Reload from GitHub'))
+ ->setIcon('fa-refresh')
+ ->setWorkflow(true)
+ ->setRenderAsForm(true);
+ }
+
$actions[] = $this->newItemAction($item, 'sync')
->setName(pht('Import to Maniphest'))
->setIcon('fa-anchor')
@@ -189,6 +234,7 @@
->appendForm($form)
->addCancelButton($item->getURI(), pht('Done'));
case 'sync':
+ case 'reload':
$item->issueCommand($viewer->getPHID(), $action);
return id(new AphrontRedirectResponse())->setURI($item->getURI());
}
@@ -238,9 +284,117 @@
->appendChild($property_list);
}
- protected function handleCommand(NuanceItem $item, $action) {
+ protected function handleCommand(
+ NuanceItem $item,
+ NuanceItemCommand $command) {
+
+ $action = $command->getCommand();
+ switch ($action) {
+ case 'sync':
+ return $this->syncItem($item, $command);
+ case 'reload':
+ $this->reloadExternalObject($item);
+ return true;
+ }
+
return null;
}
+ private function syncItem(
+ NuanceItem $item,
+ NuanceItemCommand $command) {
+
+ $xobj_phid = $item->getItemProperty('doorkeeper.xobj.phid');
+ if (!$xobj_phid) {
+ throw new Exception(
+ pht(
+ 'Unable to sync: no external object PHID.'));
+ }
+
+ // TODO: Write some kind of marker to prevent double-synchronization.
+
+ $viewer = $this->getViewer();
+
+ $xobj = id(new DoorkeeperExternalObjectQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($xobj_phid))
+ ->executeOne();
+ if (!$xobj) {
+ throw new Exception(
+ pht(
+ 'Unable to sync: failed to load object "%s".',
+ $xobj_phid));
+ }
+
+ $nuance_phid = id(new PhabricatorNuanceApplication())->getPHID();
+
+ $xactions = array();
+
+ $task = id(new ManiphestTaskQuery())
+ ->setViewer($viewer)
+ ->withBridgedObjectPHIDs(array($xobj_phid))
+ ->executeOne();
+ if (!$task) {
+ $task = ManiphestTask::initializeNewTask($viewer)
+ ->setAuthorPHID($nuance_phid)
+ ->setBridgedObjectPHID($xobj_phid);
+
+ $title = $xobj->getProperty('task.title');
+ if (!strlen($title)) {
+ $title = pht('Nuance Item %d Task', $item->getID());
+ }
+
+ $description = $xobj->getProperty('task.description');
+ $created = $xobj->getProperty('task.created');
+ $state = $xobj->getProperty('task.state');
+
+ $xactions[] = id(new ManiphestTransaction())
+ ->setTransactionType(ManiphestTransaction::TYPE_TITLE)
+ ->setNewValue($title)
+ ->setDateCreated($created);
+
+ $xactions[] = id(new ManiphestTransaction())
+ ->setTransactionType(ManiphestTransaction::TYPE_DESCRIPTION)
+ ->setNewValue($description)
+ ->setDateCreated($created);
+
+ $task->setDateCreated($created);
+
+ // TODO: Synchronize state.
+ }
+
+ $event = $this->newRawEvent($item);
+ $comment = $event->getComment();
+ if (strlen($comment)) {
+ $xactions[] = id(new ManiphestTransaction())
+ ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
+ ->attachComment(
+ id(new ManiphestTransactionComment())
+ ->setContent($comment));
+ }
+
+ // TODO: Preserve the item's original source.
+ $source = PhabricatorContentSource::newForSource(
+ PhabricatorContentSource::SOURCE_DAEMON,
+ array());
+
+ // TOOD: This should really be the external source.
+ $acting_phid = $nuance_phid;
+
+ $editor = id(new ManiphestTransactionEditor())
+ ->setActor($viewer)
+ ->setActingAsPHID($acting_phid)
+ ->setContentSource($source)
+ ->setContinueOnNoEffect(true)
+ ->setContinueOnMissingFields(true);
+
+ $xactions = $editor->applyTransactions($task, $xactions);
+
+ return array(
+ 'objectPHID' => $task->getPHID(),
+ 'xactionPHIDs' => mpull($xactions, 'getPHID'),
+ );
+ }
+
}
diff --git a/src/applications/nuance/item/NuanceItemType.php b/src/applications/nuance/item/NuanceItemType.php
--- a/src/applications/nuance/item/NuanceItemType.php
+++ b/src/applications/nuance/item/NuanceItemType.php
@@ -131,7 +131,9 @@
->applyTransactions($item, array($xaction));
}
- protected function handleCommand(NuanceItem $item, $action) {
+ protected function handleCommand(
+ NuanceItem $item,
+ NuanceItemCommand $command) {
return null;
}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 16, 5:49 AM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7706149
Default Alt Text
D15511.id37407.diff (8 KB)

Event Timeline