diff --git a/resources/sql/autopatches/20160321.nuance.01.taskbridge.sql b/resources/sql/autopatches/20160321.nuance.01.taskbridge.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20160321.nuance.01.taskbridge.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task + ADD bridgedObjectPHID VARBINARY(64); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -845,6 +845,7 @@ 'DoorkeeperBridgeGitHubIssue' => 'applications/doorkeeper/bridge/DoorkeeperBridgeGitHubIssue.php', 'DoorkeeperBridgeJIRA' => 'applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php', 'DoorkeeperBridgeJIRATestCase' => 'applications/doorkeeper/bridge/__tests__/DoorkeeperBridgeJIRATestCase.php', + 'DoorkeeperBridgedObjectInterface' => 'applications/doorkeeper/bridge/DoorkeeperBridgedObjectInterface.php', 'DoorkeeperDAO' => 'applications/doorkeeper/storage/DoorkeeperDAO.php', 'DoorkeeperExternalObject' => 'applications/doorkeeper/storage/DoorkeeperExternalObject.php', 'DoorkeeperExternalObjectQuery' => 'applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php', @@ -5636,6 +5637,7 @@ 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', + 'DoorkeeperBridgedObjectInterface', ), 'ManiphestTaskAssignHeraldAction' => 'HeraldAction', 'ManiphestTaskAssignOtherHeraldAction' => 'ManiphestTaskAssignHeraldAction', diff --git a/src/applications/doorkeeper/bridge/DoorkeeperBridgedObjectInterface.php b/src/applications/doorkeeper/bridge/DoorkeeperBridgedObjectInterface.php new file mode 100644 --- /dev/null +++ b/src/applications/doorkeeper/bridge/DoorkeeperBridgedObjectInterface.php @@ -0,0 +1,8 @@ +bridgedObjectPHIDs = $phids; + return $this; + } + public function newResultObject() { return new ManiphestTask(); } @@ -417,6 +423,13 @@ $this->subpriorityMax); } + if ($this->bridgedObjectPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'task.bridgedObjectPHID IN (%Ls)', + $this->bridgedObjectPHIDs); + } + return $where; } diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php --- a/src/applications/maniphest/storage/ManiphestTask.php +++ b/src/applications/maniphest/storage/ManiphestTask.php @@ -15,7 +15,8 @@ PhabricatorProjectInterface, PhabricatorSpacesInterface, PhabricatorConduitResultInterface, - PhabricatorFulltextInterface { + PhabricatorFulltextInterface, + DoorkeeperBridgedObjectInterface { const MARKUP_FIELD_DESCRIPTION = 'markup:desc'; @@ -36,6 +37,7 @@ protected $ownerOrdering; protected $spacePHID; + protected $bridgedObjectPHID; protected $properties = array(); protected $points; @@ -43,6 +45,7 @@ private $groupByProjectPHID = self::ATTACHABLE; private $customFields = self::ATTACHABLE; private $edgeProjectPHIDs = self::ATTACHABLE; + private $bridgedObject = self::ATTACHABLE; public static function initializeNewTask(PhabricatorUser $actor) { $app = id(new PhabricatorApplicationQuery()) @@ -82,6 +85,7 @@ 'originalEmailSource' => 'text255?', 'subpriority' => 'double', 'points' => 'double?', + 'bridgedObjectPHID' => 'phid?', ), self::CONFIG_KEY_SCHEMA => array( 'key_phid' => null, @@ -116,6 +120,10 @@ 'key_title' => array( 'columns' => array('title(64)'), ), + 'key_bridgedobject' => array( + 'columns' => array('bridgedObjectPHID'), + 'unique' => true, + ), ), ) + parent::getConfiguration(); } @@ -504,4 +512,18 @@ return new ManiphestTaskFulltextEngine(); } + +/* -( DoorkeeperBridgedObjectInterface )----------------------------------- */ + + + public function getBridgedObject() { + return $this->assertAttached($this->bridgedObject); + } + + public function attachBridgedObject( + DoorkeeperExternalObject $object = null) { + $this->bridgedObject = $object; + return $this; + } + } diff --git a/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php --- a/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php @@ -234,6 +234,9 @@ if ($page) { $maybe_visible = $this->willFilterPage($page); + if ($maybe_visible) { + $maybe_visible = $this->applyWillFilterPageExtensions($maybe_visible); + } } else { $maybe_visible = array(); } @@ -672,4 +675,52 @@ return PhabricatorApplication::isClassInstalledForViewer($class, $viewer); } + private function applyWillFilterPageExtensions(array $page) { + $bridges = array(); + foreach ($page as $key => $object) { + if ($object instanceof DoorkeeperBridgedObjectInterface) { + $bridges[$key] = $object; + } + } + + if ($bridges) { + $external_phids = array(); + foreach ($bridges as $bridge) { + $external_phid = $bridge->getBridgedObjectPHID(); + if ($external_phid) { + $external_phids[$key] = $external_phid; + } + } + + if ($external_phids) { + $external_objects = id(new DoorkeeperExternalObjectQuery()) + ->setViewer($this->getViewer()) + ->withPHIDs($external_phids) + ->execute(); + $external_objects = mpull($external_objects, null, 'getPHID'); + } else { + $external_objects = array(); + } + + foreach ($bridges as $key => $bridge) { + $external_phid = idx($external_phids, $key); + if (!$external_phid) { + $bridge->attachBridgedObject(null); + continue; + } + + $external_object = idx($external_objects, $external_phid); + if (!$external_object) { + $this->didRejectResult($bridge); + unset($page[$key]); + continue; + } + + $bridge->attachBridgedObject($external_object); + } + } + + return $page; + } + }