diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 82d0bde3f3..3ba1738612 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -305,6 +305,7 @@ phutil_register_library_map(array( 'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php', 'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialApplyPatchFieldSpecification.php', 'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/DifferentialArcanistProjectFieldSpecification.php', + 'DifferentialAsanaRepresentationFieldSpecification' => 'applications/differential/field/specification/DifferentialAsanaRepresentationFieldSpecification.php', 'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/DifferentialAuditorsFieldSpecification.php', 'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/DifferentialAuthorFieldSpecification.php', 'DifferentialAuxiliaryField' => 'applications/differential/storage/DifferentialAuxiliaryField.php', @@ -2239,6 +2240,7 @@ phutil_register_library_map(array( 'DifferentialAffectedPath' => 'DifferentialDAO', 'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification', + 'DifferentialAsanaRepresentationFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuxiliaryField' => 'DifferentialDAO', diff --git a/src/applications/differential/field/selector/DifferentialDefaultFieldSelector.php b/src/applications/differential/field/selector/DifferentialDefaultFieldSelector.php index 7d0498d51d..1e46717a56 100644 --- a/src/applications/differential/field/selector/DifferentialDefaultFieldSelector.php +++ b/src/applications/differential/field/selector/DifferentialDefaultFieldSelector.php @@ -32,6 +32,7 @@ final class DifferentialDefaultFieldSelector new DifferentialDateCreatedFieldSpecification(), new DifferentialAuditorsFieldSpecification(), new DifferentialDiffViewPolicyFieldSpecification(), + new DifferentialAsanaRepresentationFieldSpecification(), ); return $fields; diff --git a/src/applications/differential/field/specification/DifferentialAsanaRepresentationFieldSpecification.php b/src/applications/differential/field/specification/DifferentialAsanaRepresentationFieldSpecification.php new file mode 100644 index 0000000000..7edc8ccdd7 --- /dev/null +++ b/src/applications/differential/field/specification/DifferentialAsanaRepresentationFieldSpecification.php @@ -0,0 +1,76 @@ +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); + } + +} diff --git a/src/applications/doorkeeper/engine/DoorkeeperImportEngine.php b/src/applications/doorkeeper/engine/DoorkeeperImportEngine.php index b93c19dbf0..7bc65b6230 100644 --- a/src/applications/doorkeeper/engine/DoorkeeperImportEngine.php +++ b/src/applications/doorkeeper/engine/DoorkeeperImportEngine.php @@ -5,6 +5,7 @@ final class DoorkeeperImportEngine extends Phobject { private $viewer; private $refs = array(); private $phids = array(); + private $localOnly; public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; @@ -30,6 +31,11 @@ final class DoorkeeperImportEngine extends Phobject { return $this; } + public function needLocalOnly($local_only) { + $this->localOnly = $local_only; + return $this; + } + public function execute() { $refs = $this->getRefs(); $viewer = $this->getViewer(); @@ -64,32 +70,38 @@ final class DoorkeeperImportEngine extends Phobject { } } - $bridges = id(new PhutilSymbolLoader()) - ->setAncestorClass('DoorkeeperBridge') - ->loadObjects(); + if (!$this->localOnly) { + $bridges = id(new PhutilSymbolLoader()) + ->setAncestorClass('DoorkeeperBridge') + ->loadObjects(); - foreach ($bridges as $key => $bridge) { - if (!$bridge->isEnabled()) { - 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]); + foreach ($bridges as $key => $bridge) { + if (!$bridge->isEnabled()) { + unset($bridges[$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; } + public function executeOne() { + return head($this->execute()); + } + } diff --git a/src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php b/src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php index 2f5d78a687..6cdae91de7 100644 --- a/src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php +++ b/src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php @@ -238,6 +238,8 @@ final class DoorkeeperFeedWorkerAsana extends FeedPushWorker { $extra_data = array(); if ($main_edge) { + $extra_data = $main_edge['data']; + $refs = id(new DoorkeeperImportEngine()) ->setViewer($possessed_user) ->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"); } } - - $extra_data = $main_edge['data']; } else { $parent = $this->makeAsanaAPICall( $oauth_token, diff --git a/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php b/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php index 2cccdb8d69..da1df283f9 100644 --- a/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php +++ b/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php @@ -19,8 +19,12 @@ final class PhabricatorTaskmasterDaemon extends PhabricatorDaemon { $task = $task->executeTask(); $ex = $task->getExecutionException(); if ($ex) { - $this->log("Task {$id} failed!"); - throw $ex; + if ($ex instanceof PhabricatorWorkerPermanentFailureException) { + $this->log("Task {$id} failed permanently."); + } else { + $this->log("Task {$id} failed!"); + throw $ex; + } } else { $this->log("Task {$id} complete! Moved to archive."); }