From c0bec6c0ed8137c921e1d34c3ade74d9303f276e Mon Sep 17 00:00:00 2001 From: epriestley Date: Sun, 8 Jan 2017 11:39:57 -0800 Subject: [PATCH] Add "parent" and "ancestor" information to the project.search API Summary: Ref T12074. - Adds a new "parent" property on main results. This shows an abbreviated version of the project's parent, or `null` if the project is a root project. - Adds a new "ancestor" attachment to pull the entire ancestor list. - Adds a new "depth" property on main results. - You can use "parent" or "depth" to tell if a project is a subproject or not. These attempt to balance convenience, power, and performance: the full ancestor list can be big so I made it an attachment, but the other stuff isn't too big and is cheap and seems reasonable to always include. Test Plan: In API results: - Saw null parent (root projects) and non-null parent (subprojects/milestones). - Used "ancestors" attchment, got full list of ancestors. - Saw appropriate "depth" values. Reviewers: chad Reviewed By: chad Maniphest Tasks: T12074 Differential Revision: https://secure.phabricator.com/D17154 --- src/__phutil_library_map__.php | 2 + ...rojectsAncestorsSearchEngineAttachment.php | 30 +++++++++++++++ .../project/storage/PhabricatorProject.php | 37 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 src/applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 43ab0407e6..32ac036ef9 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3514,6 +3514,7 @@ phutil_register_library_map(array( 'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php', 'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php', 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', + 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php', 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', @@ -8666,6 +8667,7 @@ phutil_register_library_map(array( 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject', 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', + 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', diff --git a/src/applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php b/src/applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php new file mode 100644 index 0000000000..3113068664 --- /dev/null +++ b/src/applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php @@ -0,0 +1,30 @@ +getAncestorProjects(); + + // Order ancestors by depth, ascending. + $ancestors = array_reverse($ancestors); + + $results = array(); + foreach ($ancestors as $ancestor) { + $results[] = $ancestor->getRefForConduit(); + } + + return array( + 'ancestors' => $results, + ); + } + +} diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index c8b5e2e45a..a46ebd3352 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -745,6 +745,20 @@ final class PhabricatorProject extends PhabricatorProjectDAO ->setKey('milestone') ->setType('int?') ->setDescription(pht('For milestones, milestone sequence number.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('parent') + ->setType('map?') + ->setDescription( + pht( + 'For subprojects and milestones, a brief description of the '. + 'parent project.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('depth') + ->setType('int') + ->setDescription( + pht( + 'For subprojects and milestones, depth of this project in the '. + 'tree. Root projects have depth 0.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('icon') ->setType('map') @@ -766,10 +780,19 @@ final class PhabricatorProject extends PhabricatorProjectDAO $milestone = null; } + $parent = $this->getParentProject(); + if ($parent) { + $parent_ref = $parent->getRefForConduit(); + } else { + $parent_ref = null; + } + return array( 'name' => $this->getName(), 'slug' => $this->getPrimarySlug(), 'milestone' => $milestone, + 'depth' => (int)$this->getProjectDepth(), + 'parent' => $parent_ref, 'icon' => array( 'key' => $this->getDisplayIconKey(), 'name' => $this->getDisplayIconName(), @@ -788,6 +811,20 @@ final class PhabricatorProject extends PhabricatorProjectDAO ->setAttachmentKey('members'), id(new PhabricatorProjectsWatchersSearchEngineAttachment()) ->setAttachmentKey('watchers'), + id(new PhabricatorProjectsAncestorsSearchEngineAttachment()) + ->setAttachmentKey('ancestors'), + ); + } + + /** + * Get an abbreviated representation of this project for use in providing + * "parent" and "ancestor" information. + */ + public function getRefForConduit() { + return array( + 'id' => (int)$this->getID(), + 'phid' => $this->getPHID(), + 'name' => $this->getName(), ); }