mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 18:22:41 +01:00
Add a link to the main Asana task from Differential
Summary: Ref T2852. When a Differential revision is linked to an Asana task, show the related task in Differential. Test Plan: {F49234} Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T2852 Differential Revision: https://secure.phabricator.com/D6387
This commit is contained in:
parent
e5f200c654
commit
13e2489739
6 changed files with 118 additions and 23 deletions
|
@ -305,6 +305,7 @@ phutil_register_library_map(array(
|
||||||
'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php',
|
'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php',
|
||||||
'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialApplyPatchFieldSpecification.php',
|
'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialApplyPatchFieldSpecification.php',
|
||||||
'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/DifferentialArcanistProjectFieldSpecification.php',
|
'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/DifferentialArcanistProjectFieldSpecification.php',
|
||||||
|
'DifferentialAsanaRepresentationFieldSpecification' => 'applications/differential/field/specification/DifferentialAsanaRepresentationFieldSpecification.php',
|
||||||
'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/DifferentialAuditorsFieldSpecification.php',
|
'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/DifferentialAuditorsFieldSpecification.php',
|
||||||
'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/DifferentialAuthorFieldSpecification.php',
|
'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/DifferentialAuthorFieldSpecification.php',
|
||||||
'DifferentialAuxiliaryField' => 'applications/differential/storage/DifferentialAuxiliaryField.php',
|
'DifferentialAuxiliaryField' => 'applications/differential/storage/DifferentialAuxiliaryField.php',
|
||||||
|
@ -2239,6 +2240,7 @@ phutil_register_library_map(array(
|
||||||
'DifferentialAffectedPath' => 'DifferentialDAO',
|
'DifferentialAffectedPath' => 'DifferentialDAO',
|
||||||
'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
|
'DifferentialAsanaRepresentationFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
'DifferentialAuxiliaryField' => 'DifferentialDAO',
|
'DifferentialAuxiliaryField' => 'DifferentialDAO',
|
||||||
|
|
|
@ -32,6 +32,7 @@ final class DifferentialDefaultFieldSelector
|
||||||
new DifferentialDateCreatedFieldSpecification(),
|
new DifferentialDateCreatedFieldSpecification(),
|
||||||
new DifferentialAuditorsFieldSpecification(),
|
new DifferentialAuditorsFieldSpecification(),
|
||||||
new DifferentialDiffViewPolicyFieldSpecification(),
|
new DifferentialDiffViewPolicyFieldSpecification(),
|
||||||
|
new DifferentialAsanaRepresentationFieldSpecification(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DifferentialAsanaRepresentationFieldSpecification
|
||||||
|
extends DifferentialFieldSpecification {
|
||||||
|
|
||||||
|
public function shouldAppearOnRevisionView() {
|
||||||
|
return (bool)PhabricatorEnv::getEnvConfig('asana.workspace-id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderLabelForRevisionView() {
|
||||||
|
return pht('In Asana:');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderValueForRevisionView() {
|
||||||
|
$viewer = $this->getUser();
|
||||||
|
$src_phid = $this->getRevision()->getPHID();
|
||||||
|
$edge_type = PhabricatorEdgeConfig::TYPE_PHOB_HAS_ASANATASK;
|
||||||
|
|
||||||
|
$query = id(new PhabricatorEdgeQuery())
|
||||||
|
->withSourcePHIDs(array($src_phid))
|
||||||
|
->withEdgeTypes(array($edge_type))
|
||||||
|
->needEdgeData(true);
|
||||||
|
|
||||||
|
$edges = $query->execute();
|
||||||
|
if (!$edges) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$edge = head($edges[$src_phid][$edge_type]);
|
||||||
|
|
||||||
|
if (!empty($edge['data']['gone'])) {
|
||||||
|
return phutil_tag(
|
||||||
|
'em',
|
||||||
|
array(),
|
||||||
|
pht('Asana Task Deleted'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$ref = id(new DoorkeeperImportEngine())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(array($edge['dst']))
|
||||||
|
->needLocalOnly(true)
|
||||||
|
->executeOne();
|
||||||
|
|
||||||
|
if (!$ref) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tag_id = celerity_generate_unique_node_id();
|
||||||
|
$xobj = $ref->getExternalObject();
|
||||||
|
$href = $xobj->getObjectURI();
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'doorkeeper-tag',
|
||||||
|
array(
|
||||||
|
'tags' => array(
|
||||||
|
array(
|
||||||
|
'id' => $tag_id,
|
||||||
|
'ref' => array(
|
||||||
|
$ref->getApplicationType(),
|
||||||
|
$ref->getApplicationDomain(),
|
||||||
|
$ref->getObjectType(),
|
||||||
|
$ref->getObjectID(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
return id(new PhabricatorTagView())
|
||||||
|
->setID($tag_id)
|
||||||
|
->setName($href)
|
||||||
|
->setHref($href)
|
||||||
|
->setType(PhabricatorTagView::TYPE_OBJECT)
|
||||||
|
->setExternal(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ final class DoorkeeperImportEngine extends Phobject {
|
||||||
private $viewer;
|
private $viewer;
|
||||||
private $refs = array();
|
private $refs = array();
|
||||||
private $phids = array();
|
private $phids = array();
|
||||||
|
private $localOnly;
|
||||||
|
|
||||||
public function setViewer(PhabricatorUser $viewer) {
|
public function setViewer(PhabricatorUser $viewer) {
|
||||||
$this->viewer = $viewer;
|
$this->viewer = $viewer;
|
||||||
|
@ -30,6 +31,11 @@ final class DoorkeeperImportEngine extends Phobject {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function needLocalOnly($local_only) {
|
||||||
|
$this->localOnly = $local_only;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function execute() {
|
public function execute() {
|
||||||
$refs = $this->getRefs();
|
$refs = $this->getRefs();
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
@ -64,32 +70,38 @@ final class DoorkeeperImportEngine extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$bridges = id(new PhutilSymbolLoader())
|
if (!$this->localOnly) {
|
||||||
->setAncestorClass('DoorkeeperBridge')
|
$bridges = id(new PhutilSymbolLoader())
|
||||||
->loadObjects();
|
->setAncestorClass('DoorkeeperBridge')
|
||||||
|
->loadObjects();
|
||||||
|
|
||||||
foreach ($bridges as $key => $bridge) {
|
foreach ($bridges as $key => $bridge) {
|
||||||
if (!$bridge->isEnabled()) {
|
if (!$bridge->isEnabled()) {
|
||||||
unset($bridges[$key]);
|
unset($bridges[$key]);
|
||||||
}
|
|
||||||
$bridge->setViewer($viewer);
|
|
||||||
}
|
|
||||||
|
|
||||||
$working_set = $refs;
|
|
||||||
foreach ($bridges as $bridge) {
|
|
||||||
$bridge_refs = array();
|
|
||||||
foreach ($working_set as $key => $ref) {
|
|
||||||
if ($bridge->canPullRef($ref)) {
|
|
||||||
$bridge_refs[$key] = $ref;
|
|
||||||
unset($working_set[$key]);
|
|
||||||
}
|
}
|
||||||
|
$bridge->setViewer($viewer);
|
||||||
}
|
}
|
||||||
if ($bridge_refs) {
|
|
||||||
$bridge->pullRefs($bridge_refs);
|
$working_set = $refs;
|
||||||
|
foreach ($bridges as $bridge) {
|
||||||
|
$bridge_refs = array();
|
||||||
|
foreach ($working_set as $key => $ref) {
|
||||||
|
if ($bridge->canPullRef($ref)) {
|
||||||
|
$bridge_refs[$key] = $ref;
|
||||||
|
unset($working_set[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($bridge_refs) {
|
||||||
|
$bridge->pullRefs($bridge_refs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $refs;
|
return $refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function executeOne() {
|
||||||
|
return head($this->execute());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,8 @@ final class DoorkeeperFeedWorkerAsana extends FeedPushWorker {
|
||||||
|
|
||||||
$extra_data = array();
|
$extra_data = array();
|
||||||
if ($main_edge) {
|
if ($main_edge) {
|
||||||
|
$extra_data = $main_edge['data'];
|
||||||
|
|
||||||
$refs = id(new DoorkeeperImportEngine())
|
$refs = id(new DoorkeeperImportEngine())
|
||||||
->setViewer($possessed_user)
|
->setViewer($possessed_user)
|
||||||
->withPHIDs(array($main_edge['dst']))
|
->withPHIDs(array($main_edge['dst']))
|
||||||
|
@ -289,8 +291,6 @@ final class DoorkeeperFeedWorkerAsana extends FeedPushWorker {
|
||||||
"Skipping main task update, cursor is ahead of the story.\n");
|
"Skipping main task update, cursor is ahead of the story.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$extra_data = $main_edge['data'];
|
|
||||||
} else {
|
} else {
|
||||||
$parent = $this->makeAsanaAPICall(
|
$parent = $this->makeAsanaAPICall(
|
||||||
$oauth_token,
|
$oauth_token,
|
||||||
|
|
|
@ -19,8 +19,12 @@ final class PhabricatorTaskmasterDaemon extends PhabricatorDaemon {
|
||||||
$task = $task->executeTask();
|
$task = $task->executeTask();
|
||||||
$ex = $task->getExecutionException();
|
$ex = $task->getExecutionException();
|
||||||
if ($ex) {
|
if ($ex) {
|
||||||
$this->log("Task {$id} failed!");
|
if ($ex instanceof PhabricatorWorkerPermanentFailureException) {
|
||||||
throw $ex;
|
$this->log("Task {$id} failed permanently.");
|
||||||
|
} else {
|
||||||
|
$this->log("Task {$id} failed!");
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->log("Task {$id} complete! Moved to archive.");
|
$this->log("Task {$id} complete! Moved to archive.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue