Differential D14910 Diff 36035 src/applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php
- This file was added.
| <?php | |||||
| final class PhabricatorProjectLogicalAncestorDatasource | |||||
| extends PhabricatorTypeaheadCompositeDatasource { | |||||
| public function getBrowseTitle() { | |||||
| return pht('Browse Projects'); | |||||
| } | |||||
| public function getPlaceholderText() { | |||||
| return pht('Type a project name...'); | |||||
| } | |||||
| public function getDatasourceApplicationClass() { | |||||
| return 'PhabricatorProjectApplication'; | |||||
| } | |||||
| public function getComponentDatasources() { | |||||
| return array( | |||||
| new PhabricatorProjectDatasource(), | |||||
| ); | |||||
| } | |||||
| protected function didEvaluateTokens(array $results) { | |||||
| $phids = array(); | |||||
| foreach ($results as $result) { | |||||
| if (!is_string($result)) { | |||||
| continue; | |||||
| } | |||||
| $phids[] = $result; | |||||
| } | |||||
| $map = array(); | |||||
| $skip = array(); | |||||
| if ($phids) { | |||||
| $phids = array_fuse($phids); | |||||
| $viewer = $this->getViewer(); | |||||
| $all_projects = id(new PhabricatorProjectQuery()) | |||||
| ->setViewer($viewer) | |||||
| ->withAncestorProjectPHIDs($phids) | |||||
| ->execute(); | |||||
| foreach ($phids as $phid) { | |||||
| $map[$phid][] = $phid; | |||||
| } | |||||
| foreach ($all_projects as $project) { | |||||
| $project_phid = $project->getPHID(); | |||||
| $map[$project_phid][] = $project_phid; | |||||
| foreach ($project->getAncestorProjects() as $ancestor) { | |||||
| $ancestor_phid = $ancestor->getPHID(); | |||||
| if (isset($phids[$project_phid]) && isset($phids[$ancestor_phid])) { | |||||
| // This is a descendant of some other project in the query, so | |||||
| // we don't need to query for that project. This happens if a user | |||||
| // runs a query for both "Engineering" and "Engineering > Warp | |||||
| // Drive". We can only ever match the "Warp Drive" results, so | |||||
| // we do not need to add the weaker "Engineering" constraint. | |||||
| $skip[$ancestor_phid] = true; | |||||
| } | |||||
| $map[$ancestor_phid][] = $project_phid; | |||||
| } | |||||
| } | |||||
| } | |||||
| foreach ($results as $key => $result) { | |||||
| if (!is_string($result)) { | |||||
| continue; | |||||
| } | |||||
| if (empty($map[$result])) { | |||||
| continue; | |||||
| } | |||||
| // This constraint is implied by another, stronger constraint. | |||||
| if (isset($skip[$result])) { | |||||
| unset($results[$key]); | |||||
| continue; | |||||
| } | |||||
| // If we have duplicates, don't apply the second constraint. | |||||
| $skip[$result] = true; | |||||
| $results[$key] = new PhabricatorQueryConstraint( | |||||
| PhabricatorQueryConstraint::OPERATOR_ANCESTOR, | |||||
| $map[$result]); | |||||
| } | |||||
| return $results; | |||||
| } | |||||
| } | |||||