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 @@ -3747,6 +3747,7 @@ 'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php', 'ProjectRemarkupRuleTestCase' => 'applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php', 'ProjectReplyHandler' => 'applications/project/mail/ProjectReplyHandler.php', + 'ProjectSearchConduitAPIMethod' => 'applications/project/conduit/ProjectSearchConduitAPIMethod.php', 'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php', 'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php', 'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php', @@ -7146,6 +7147,7 @@ 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', + 'PhabricatorConduitResultInterface', ), 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectApplication' => 'PhabricatorApplication', @@ -8296,6 +8298,7 @@ 'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ProjectRemarkupRuleTestCase' => 'PhabricatorTestCase', 'ProjectReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', + 'ProjectSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'QueryFormattingTestCase' => 'PhabricatorTestCase', 'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification', 'ReleephBranch' => array( diff --git a/src/applications/project/conduit/ProjectSearchConduitAPIMethod.php b/src/applications/project/conduit/ProjectSearchConduitAPIMethod.php new file mode 100644 --- /dev/null +++ b/src/applications/project/conduit/ProjectSearchConduitAPIMethod.php @@ -0,0 +1,24 @@ +<?php + +final class ProjectSearchConduitAPIMethod + extends PhabricatorSearchEngineAPIMethod { + + public function getAPIMethodName() { + return 'project.search'; + } + + public function newSearchEngine() { + return new PhabricatorProjectSearchEngine(); + } + + public function getMethodSummary() { + return pht('Read information about projects.'); + } + + protected function getCustomQueryMaps($query) { + return array( + 'slugMap' => $query->getSlugMap(), + ); + } + +} diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -9,7 +9,8 @@ PhabricatorSubscribableInterface, PhabricatorCustomFieldInterface, PhabricatorDestructibleInterface, - PhabricatorFulltextInterface { + PhabricatorFulltextInterface, + PhabricatorConduitResultInterface { protected $name; protected $status = PhabricatorProjectStatus::STATUS_ACTIVE; @@ -525,4 +526,32 @@ return new PhabricatorProjectFulltextEngine(); } + +/* -( PhabricatorConduitResultInterface )---------------------------------- */ + + + public function getFieldSpecificationsForConduit() { + return array( + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('name') + ->setType('string') + ->setDescription(pht('The name of the project.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('slug') + ->setType('string') + ->setDescription(pht('Primary slug/hashtag.')), + ); + } + + public function getFieldValuesForConduit() { + return array( + 'name' => $this->getName(), + 'slug' => $this->getPrimarySlug(), + ); + } + + public function getConduitSearchAttachments() { + return array(); + } + } diff --git a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php --- a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php +++ b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php @@ -1081,7 +1081,9 @@ return $fields; } - public function buildConduitResponse(ConduitAPIRequest $request) { + public function buildConduitResponse( + ConduitAPIRequest $request, + ConduitAPIMethod $method) { $viewer = $this->requireViewer(); $query_key = $request->getValue('queryKey'); @@ -1172,6 +1174,12 @@ $attachment_specs[$key]); } + // If this is empty, we still want to emit a JSON object, not a + // JSON list. + if (!$attachment_map) { + $attachment_map = (object)$attachment_map; + } + $id = (int)$object->getID(); $phid = $object->getPHID(); @@ -1187,6 +1195,7 @@ return array( 'data' => $data, + 'maps' => $method->getQueryMaps($query), 'query' => array( 'queryKey' => $saved_query->getQueryKey(), ), diff --git a/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php b/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php --- a/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php +++ b/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php @@ -5,6 +5,23 @@ abstract public function newSearchEngine(); + final public function getQueryMaps($query) { + $maps = $this->getCustomQueryMaps($query); + + // Make sure we emit empty maps as objects, not lists. + foreach ($maps as $key => $map) { + if (!$map) { + $maps[$key] = (object)$map; + } + } + + return $maps; + } + + protected function getCustomQueryMaps($query) { + return array(); + } + public function getApplication() { $engine = $this->newSearchEngine(); $class = $engine->getApplicationClassName(); @@ -36,7 +53,7 @@ $engine = $this->newSearchEngine() ->setViewer($request->getUser()); - return $engine->buildConduitResponse($request); + return $engine->buildConduitResponse($request, $this); } final public function getMethodDescription() {