From 40aa51622e7a8c086e937cc5b3eca2aad50e5411 Mon Sep 17 00:00:00 2001 From: amy bones Date: Mon, 9 Jun 2025 21:09:41 -0700 Subject: [PATCH] Make search select fields usable over Conduit Summary: Previously, search select fields (@{class:PhabricatorSearchSelectField}) did not support conduit queries, as they had no `newConduitParameterType` method. Now they do. This takes a very simple approach and treats them similarly to how @{class:PhabricatorSearchCheckboxesField} works. Only these applications use search select fields presently: - Calendar - Dashboard - Macro - Maniphest - Project - Repository Of those, only the following expose modern application search methods: - Calendar - Maniphest - Project - Repository Calendar and Repository work without changes. For Maniphest, `group` now works a bit better by including the project PHID grouped-by in the results, when grouping by project. For Project, the status field has been lightly refactored to use constants for consistency, and especially now the project status is included in the conduit results. Test Plan: ### Projects 1. attempt to use status field to query projects before this diff: get query error. 2. apply this diff. 3. attempt to use status field again: see that filtering works, and project results include their status. ### Maniphest 1. do maniphest queries in the UI before this diff: see that grouping works. 2. look at the conduit page [[ /conduit/method/maniphest.search/ ]], see `group`. 3. Observe that `group` throws an error if you attempt to use it. 4. apply this diff. 5. return to the conduit page and find that using `group` no longer errors. 6. do more maniphest queries in the UI and see that grouping still works. Reviewers: O1 Blessed Committers, aklapper Reviewed By: O1 Blessed Committers, aklapper Subscribers: aklapper, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Differential Revision: https://we.phorge.it/D26166 --- .../maniphest/storage/ManiphestTask.php | 6 +++++ .../constants/PhabricatorProjectStatus.php | 13 +++++++++++ .../query/PhabricatorProjectSearchEngine.php | 22 +++++++++++++------ .../project/storage/PhabricatorProject.php | 1 + .../field/PhabricatorSearchSelectField.php | 15 +++++++++++++ 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php index 32cfb0966a..6bd9b40f40 100644 --- a/src/applications/maniphest/storage/ManiphestTask.php +++ b/src/applications/maniphest/storage/ManiphestTask.php @@ -494,6 +494,11 @@ final class ManiphestTask extends ManiphestDAO $closed_epoch = (int)$closed_epoch; } + $group_by_phid = $this->groupByProjectPHID; + if ($group_by_phid === self::ATTACHABLE) { + $group_by_phid = null; + } + return array( 'name' => $this->getTitle(), 'description' => array( @@ -507,6 +512,7 @@ final class ManiphestTask extends ManiphestDAO 'subtype' => $this->getSubtype(), 'closerPHID' => $this->getCloserPHID(), 'dateClosed' => $closed_epoch, + 'groupByProjectPHID' => $group_by_phid, ); } diff --git a/src/applications/project/constants/PhabricatorProjectStatus.php b/src/applications/project/constants/PhabricatorProjectStatus.php index 79b1ee823c..5138bb2d2b 100644 --- a/src/applications/project/constants/PhabricatorProjectStatus.php +++ b/src/applications/project/constants/PhabricatorProjectStatus.php @@ -5,6 +5,9 @@ final class PhabricatorProjectStatus extends Phobject { const STATUS_ACTIVE = 0; const STATUS_ARCHIVED = 100; + const STATUS_ACTIVE_KEY = 'active'; + const STATUS_ARCHIVED_KEY = 'archived'; + public static function getNameForStatus($status) { $map = array( self::STATUS_ACTIVE => pht('Active'), @@ -21,4 +24,14 @@ final class PhabricatorProjectStatus extends Phobject { ); } + public static function getStatusKeys() { + return array( + self::STATUS_ACTIVE_KEY => self::STATUS_ACTIVE, + self::STATUS_ARCHIVED_KEY => self::STATUS_ARCHIVED, + ); + } + + public static function getKeyForStatus(int $status) { + return array_flip(self::getStatusKeys())[$status]; + } } diff --git a/src/applications/project/query/PhabricatorProjectSearchEngine.php b/src/applications/project/query/PhabricatorProjectSearchEngine.php index 0c96d72994..8d18c9eb24 100644 --- a/src/applications/project/query/PhabricatorProjectSearchEngine.php +++ b/src/applications/project/query/PhabricatorProjectSearchEngine.php @@ -247,37 +247,45 @@ final class PhabricatorProjectSearchEngine // By default, do not show milestones in the list view. $query->setParameter('isMilestone', false); + $active = PhabricatorProjectStatus::STATUS_ACTIVE_KEY; + switch ($query_key) { case 'all': return $query; case 'active': return $query - ->setParameter('status', 'active'); + ->setParameter('status', $active); case 'joined': return $query ->setParameter('memberPHIDs', array($viewer_phid)) - ->setParameter('status', 'active'); + ->setParameter('status', $active); case 'watching': return $query ->setParameter('watcherPHIDs', array($viewer_phid)) - ->setParameter('status', 'active'); + ->setParameter('status', $active); } return parent::buildSavedQueryFromBuiltin($query_key); } private function getStatusOptions() { + $active = PhabricatorProjectStatus::STATUS_ACTIVE_KEY; + $archived = PhabricatorProjectStatus::STATUS_ARCHIVED_KEY; + return array( - 'active' => pht('Show Only Active Projects'), - 'archived' => pht('Show Only Archived Projects'), + $active => pht('Show Only Active Projects'), + $archived => pht('Show Only Archived Projects'), 'all' => pht('Show All Projects'), ); } private function getStatusValues() { + $active = PhabricatorProjectStatus::STATUS_ACTIVE_KEY; + $archived = PhabricatorProjectStatus::STATUS_ARCHIVED_KEY; + return array( - 'active' => PhabricatorProjectQuery::STATUS_ACTIVE, - 'archived' => PhabricatorProjectQuery::STATUS_ARCHIVED, + $active => PhabricatorProjectQuery::STATUS_ACTIVE, + $archived => PhabricatorProjectQuery::STATUS_ARCHIVED, 'all' => PhabricatorProjectQuery::STATUS_ANY, ); } diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 7fcf1b2f35..53dd5f1ff9 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -930,6 +930,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO 'key' => $color_key, 'name' => $color_name, ), + 'status' => PhabricatorProjectStatus::getKeyForStatus($this->getStatus()), ); } diff --git a/src/applications/search/field/PhabricatorSearchSelectField.php b/src/applications/search/field/PhabricatorSearchSelectField.php index 0806174220..7c735f26b5 100644 --- a/src/applications/search/field/PhabricatorSearchSelectField.php +++ b/src/applications/search/field/PhabricatorSearchSelectField.php @@ -33,4 +33,19 @@ final class PhabricatorSearchSelectField ->setOptions($this->getOptions()); } + protected function newConduitParameterType() { + return new ConduitStringParameterType(); + } + + public function newConduitConstants() { + $list = array(); + + foreach ($this->getOptions() as $key => $option) { + $list[] = id(new ConduitConstantDescription()) + ->setKey($key) + ->setValue($option); + } + + return $list; + } } -- 2.51.2